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_;