drm_hwcomposer: Move vsync tracking into VSyncWorker

Track the timestamp of the last vsync event in VSyncWorker, and provide
an interface for HwcDisplay to enable/disable tracking, and to query the
most recent timestamp.

Moving this into VSyncWorker avoids the need for the VSyncWorker thread
to acquire the global lock.

Change-Id: Ib79d9a6dc5e0f7d6a36ca01dbcda5434a0f582a4
Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp
index 851e87c..c120af6 100644
--- a/drm/VSyncWorker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -63,6 +63,21 @@
   vsync_period_ns_ = vsync_period_ns;
 }
 
+void VSyncWorker::SetVsyncTimestampTracking(bool enabled) {
+  const std::lock_guard<std::mutex> lock(mutex_);
+  enable_vsync_timestamps_ = enabled;
+  if (enabled) {
+    // Reset the last timestamp so the caller knows if a vsync timestamp is
+    // fresh or not.
+    last_vsync_timestamp_ = 0;
+  }
+}
+
+uint32_t VSyncWorker::GetLastVsyncTimestamp() {
+  const std::lock_guard<std::mutex> lock(mutex_);
+  return last_vsync_timestamp_;
+}
+
 void VSyncWorker::StopThread() {
   {
     const std::lock_guard<std::mutex> lock(mutex_);
@@ -164,6 +179,9 @@
       if (!enabled_)
         continue;
       callback = callbacks_.out_event;
+      if (enable_vsync_timestamps_) {
+        last_vsync_timestamp_ = timestamp;
+      }
     }
 
     if (callback)
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h
index aff34d8..f0367ae 100644
--- a/drm/VSyncWorker.h
+++ b/drm/VSyncWorker.h
@@ -43,6 +43,12 @@
   // Set the expected vsync period.
   void SetVsyncPeriodNs(uint32_t vsync_period_ns);
 
+  // Enable vsync timestamp tracking. GetLastVsyncTimestamp will return 0 if
+  // vsync tracking is disabled, or if no vsync has happened since it was
+  // enabled.
+  void SetVsyncTimestampTracking(bool enabled);
+  uint32_t GetLastVsyncTimestamp();
+
   void StopThread();
 
  private:
@@ -66,6 +72,8 @@
   static constexpr uint32_t kDefaultVSPeriodNs = 16666666;
   // Needs to be threadsafe.
   uint32_t vsync_period_ns_ = kDefaultVSPeriodNs;
+  bool enable_vsync_timestamps_ = false;
+  uint32_t last_vsync_timestamp_ = 0;
 
   std::condition_variable cv_;
   std::thread vswt_;
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 2260e36..8d6b0a3 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -265,8 +265,7 @@
   staged_mode_config_id_ = config;
 
   // Enable vsync events until the mode has been applied.
-  last_vsync_ts_ = 0;
-  vsync_tracking_en_ = true;
+  vsync_worker_->SetVsyncTimestampTracking(true);
   vsync_worker_->VSyncControl(true);
 
   return ConfigError::kNone;
@@ -324,10 +323,7 @@
               GetDisplayVsyncPeriod(&period_ns);
               hwc_->SendVsyncEventToClient(handle_, timestamp, period_ns);
             }
-            if (vsync_tracking_en_) {
-              last_vsync_ts_ = timestamp;
-            }
-            if (!vsync_event_en_ && !vsync_tracking_en_) {
+            if (!vsync_event_en_) {
               vsync_worker_->VSyncControl(false);
             }
           },
@@ -776,10 +772,12 @@
   if (new_vsync_period_ns) {
     vsync_worker_->SetVsyncPeriodNs(new_vsync_period_ns.value());
     staged_mode_config_id_.reset();
-    vsync_tracking_en_ = false;
-    if (last_vsync_ts_ != 0) {
+
+    vsync_worker_->SetVsyncTimestampTracking(false);
+    uint32_t last_vsync_ts = vsync_worker_->GetLastVsyncTimestamp();
+    if (last_vsync_ts != 0) {
       hwc_->SendVsyncPeriodTimingChangedEventToClient(handle_,
-                                                      last_vsync_ts_ +
+                                                      last_vsync_ts +
                                                           prev_vperiod_ns);
     }
   }
@@ -1167,8 +1165,7 @@
   outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints
                                               ->desiredTimeNanos;
 
-  last_vsync_ts_ = 0;
-  vsync_tracking_en_ = true;
+  vsync_worker_->SetVsyncTimestampTracking(true);
   vsync_worker_->VSyncControl(true);
 
   return HWC2::Error::None;
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index ecca514..5d593bb 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -248,8 +248,6 @@
 
   std::shared_ptr<VSyncWorker> vsync_worker_;
   bool vsync_event_en_{};
-  bool vsync_tracking_en_{};
-  int64_t last_vsync_ts_{};
 
   const hwc2_display_t handle_;
   HWC2::DisplayType type_;