drm_hwcomposer: Set vsync period for vsync thread Make HwcDisplay set the VsyncWorker's vsync_period whenever it changes, rather than having VsyncWorker query the vsync_period from HwcDisplay. Doing so prevents the VsyncWorker thread from needing to acquire the global lock to read HwcDisplay's state. The original change called GetVsyncPeriod, which checks the vsync period for the mode that is currently committed to the kernel based on HwcDisplay::configs_.active_config_id, so call VsyncWorker::SetVsyncPeriod whenever active_config_id is set. Change-Id: Ie301c47e2496748117db8cca8a6ee9691e723c74 Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp index 963a37b..f4c0710 100644 --- a/drm/VSyncWorker.cpp +++ b/drm/VSyncWorker.cpp
@@ -58,6 +58,11 @@ cv_.notify_all(); } +void VSyncWorker::SetVsyncPeriodNs(uint32_t vsync_period_ns) { + const std::lock_guard<std::mutex> lock(mutex_); + vsync_period_ns_ = vsync_period_ns; +} + void VSyncWorker::StopThread() { { const std::lock_guard<std::mutex> lock(mutex_); @@ -97,9 +102,7 @@ // Default to 60Hz refresh rate constexpr uint32_t kDefaultVSPeriodNs = 16666666; - auto period_ns = kDefaultVSPeriodNs; - if (callbacks_.get_vperiod_ns && callbacks_.get_vperiod_ns() != 0) - period_ns = callbacks_.get_vperiod_ns(); + auto period_ns = vsync_period_ns_ ? vsync_period_ns_ : kDefaultVSPeriodNs; auto phased_timestamp = GetPhasedVSync(period_ns, time_now); struct timespec vsync {};
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h index 2a4c7c8..2ee7f37 100644 --- a/drm/VSyncWorker.h +++ b/drm/VSyncWorker.h
@@ -28,7 +28,6 @@ struct VSyncWorkerCallbacks { std::function<void(uint64_t /*timestamp*/)> out_event; - std::function<uint32_t()> get_vperiod_ns; }; class VSyncWorker { @@ -40,6 +39,10 @@ -> std::shared_ptr<VSyncWorker>; void VSyncControl(bool enabled); + + // Set the expected vsync period. + void SetVsyncPeriodNs(uint32_t vsync_period_ns); + void StopThread(); private: @@ -59,6 +62,9 @@ bool thread_exit_ = false; int64_t last_timestamp_ = -1; + // Needs to be threadsafe. + uint32_t vsync_period_ns_ = 0; + std::condition_variable cv_; std::thread vswt_; std::mutex mutex_;
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 0503f39..6b676c2 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp
@@ -232,6 +232,8 @@ ALOGV("Blocking config succeeded."); configs_.active_config_id = config; staged_mode_config_id_.reset(); + vsync_worker_->SetVsyncPeriodNs(new_config->mode.GetVSyncPeriodNs()); + // set new vsync period return ConfigError::kNone; } @@ -329,11 +331,6 @@ vsync_worker_->VSyncControl(false); } }, - .get_vperiod_ns = [this]() -> uint32_t { - uint32_t outVsyncPeriod = 0; - GetDisplayVsyncPeriod(&outVsyncPeriod); - return outVsyncPeriod; - }, }; if (type_ != HWC2::DisplayType::Virtual) { @@ -698,6 +695,7 @@ .bottom = int(staged_config->mode.GetRawMode().vdisplay)}); configs_.active_config_id = staged_mode_config_id_.value(); + vsync_worker_->SetVsyncPeriodNs(staged_config->mode.GetVSyncPeriodNs()); a_args.display_mode = staged_config->mode; if (!a_args.test_only) {