drm_hwcomposer: Set vsync callback on demand

Set and clear a vsync callback based on when the client requests vsync
events to be enabled or not. The new vsync callback does not need to
acquire the global resource lock.

The vsync callback uses the vsync period that was set in the VSyncWorker
rather than querying it from the HwcDisplay.

Change-Id: Ic7868af4963ad40aa5a0982a190c67f1642d5b32
Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp
index c120af6..6123e5c 100644
--- a/drm/VSyncWorker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -78,6 +78,12 @@
   return last_vsync_timestamp_;
 }
 
+void VSyncWorker::SetTimestampCallback(
+    std::optional<VsyncTimestampCallback> &&callback) {
+  const std::lock_guard<std::mutex> lock(mutex_);
+  callback_ = std::move(callback);
+}
+
 void VSyncWorker::StopThread() {
   {
     const std::lock_guard<std::mutex> lock(mutex_);
@@ -173,6 +179,7 @@
     }
 
     decltype(callbacks_.out_event) callback;
+    std::optional<VsyncTimestampCallback> vsync_callback;
 
     {
       const std::lock_guard<std::mutex> lock(mutex_);
@@ -182,6 +189,11 @@
       if (enable_vsync_timestamps_) {
         last_vsync_timestamp_ = timestamp;
       }
+      vsync_callback = callback_;
+    }
+
+    if (vsync_callback) {
+      vsync_callback.value()(timestamp, vsync_period_ns_);
     }
 
     if (callback)
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h
index f0367ae..f032d79 100644
--- a/drm/VSyncWorker.h
+++ b/drm/VSyncWorker.h
@@ -32,6 +32,9 @@
 
 class VSyncWorker {
  public:
+  using VsyncTimestampCallback = std::function<void(int64_t /*timestamp*/,
+                                                    uint32_t /*period*/)>;
+
   ~VSyncWorker() = default;
 
   auto static CreateInstance(std::shared_ptr<DrmDisplayPipeline> &pipe,
@@ -43,6 +46,9 @@
   // Set the expected vsync period.
   void SetVsyncPeriodNs(uint32_t vsync_period_ns);
 
+  // Set or clear a callback to be fired on vsync.
+  void SetTimestampCallback(std::optional<VsyncTimestampCallback> &&callback);
+
   // Enable vsync timestamp tracking. GetLastVsyncTimestamp will return 0 if
   // vsync tracking is disabled, or if no vsync has happened since it was
   // enabled.
@@ -74,6 +80,7 @@
   uint32_t vsync_period_ns_ = kDefaultVSPeriodNs;
   bool enable_vsync_timestamps_ = false;
   uint32_t last_vsync_timestamp_ = 0;
+  std::optional<VsyncTimestampCallback> callback_;
 
   std::condition_variable cv_;
   std::thread vswt_;