diff options
author | John Chang <cweichun@google.com> | 2023-11-02 22:32:50 +0000 |
---|---|---|
committer | John Chang <cweichun@google.com> | 2023-11-28 22:50:11 +0000 |
commit | 63c6c5feae3d5ae217899a94fe77349762066c5a (patch) | |
tree | 51cc31c0dc103041a9a6c03a9a9a3a702131daf0 | |
parent | 64b51ff82f4d0a92e5405e017ed3529100d6cdfc (diff) | |
download | common-63c6c5feae3d5ae217899a94fe77349762066c5a.tar.gz |
libhwc2.1: suspend VRR controller thread during OFF and AOD states
Bug: 309014371
Test: verify if the power mode is not equal to HWC_POWER_MODE_NORMAL,
the thread will be locked by a conditional variable, awaiting a signal
with no further actions permitted during this interval
Change-Id: Ib5553789b648bf829d7da60a5be75d359b19f8ea
-rw-r--r-- | libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp | 22 | ||||
-rw-r--r-- | libhwc2.1/libvrr/VariableRefreshRateController.cpp | 55 | ||||
-rw-r--r-- | libhwc2.1/libvrr/VariableRefreshRateController.h | 9 |
3 files changed, 73 insertions, 13 deletions
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp index cc1a7e1..3495d01 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp @@ -492,27 +492,35 @@ int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) { mOperationRateManager->getTargetOperationRate()); } + int32_t res = HWC2_ERROR_BAD_PARAMETER; switch (mode) { case HWC2_POWER_MODE_DOZE: - case HWC2_POWER_MODE_DOZE_SUSPEND: + case HWC2_POWER_MODE_DOZE_SUSPEND: { if (mode == HWC2_POWER_MODE_DOZE && mDisplayInterface->needRefreshOnLP()) { ALOGI("Refresh before setting power doze."); mDevice->onRefresh(mDisplayId); } - return setPowerDoze(static_cast<hwc2_power_mode_t>(mode)); + res = setPowerDoze(static_cast<hwc2_power_mode_t>(mode)); + break; + } case HWC2_POWER_MODE_OFF: - setPowerOff(); + res = setPowerOff(); break; case HWC2_POWER_MODE_ON: - setPowerOn(); + res = setPowerOn(); break; default: - return HWC2_ERROR_BAD_PARAMETER; + return res; + } + if (res != HWC2_ERROR_NONE) { + return res; } ExynosDisplay::updateRefreshRateHint(); - - return HWC2_ERROR_NONE; + if (mVariableRefreshRateController) { + mVariableRefreshRateController->setPowerMode(mode); + } + return res; } void ExynosPrimaryDisplay::firstPowerOn() { diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.cpp b/libhwc2.1/libvrr/VariableRefreshRateController.cpp index 8f0af10..e382c00 100644 --- a/libhwc2.1/libvrr/VariableRefreshRateController.cpp +++ b/libhwc2.1/libvrr/VariableRefreshRateController.cpp @@ -72,7 +72,7 @@ VariableRefreshRateController::VariableRefreshRateController(ExynosDisplay* disp } VariableRefreshRateController::~VariableRefreshRateController() { - stopThread(); + stopThread(true); const std::lock_guard<std::mutex> lock(mMutex); if (mLastPresentFence.has_value()) { @@ -146,19 +146,65 @@ void VariableRefreshRateController::setEnable(bool isEnabled) { mCondition.notify_all(); } +void VariableRefreshRateController::setPowerMode(int32_t powerMode) { + ATRACE_CALL(); + LOG(INFO) << "VrrController: Set power mode to " << powerMode; + + { + const std::lock_guard<std::mutex> lock(mMutex); + if (mPowerMode == powerMode) { + return; + } + switch (powerMode) { + case HWC_POWER_MODE_OFF: + case HWC_POWER_MODE_DOZE: + case HWC_POWER_MODE_DOZE_SUSPEND: { + mState = VrrControllerState::kDisable; + dropEventLocked(); + break; + } + case HWC_POWER_MODE_NORMAL: { + // We should transition from either HWC_POWER_MODE_OFF, HWC_POWER_MODE_DOZE, or + // HWC_POWER_MODE_DOZE_SUSPEND. At this point, there should be no pending events + // posted. + if (!mEventQueue.empty()) { + LOG(WARNING) << "VrrController: there should be no pending event when resume " + "from power mode = " + << mPowerMode << " to power mode = " << powerMode; + } + mState = VrrControllerState::kRendering; + const auto& vrrConfig = mVrrConfigs[mVrrActiveConfig]; + postEvent(VrrControllerEventType::kRenderingTimeout, + getNowNs() + vrrConfig.notifyExpectedPresentConfig.TimeoutNs); + break; + } + default: { + LOG(ERROR) << "VrrController: Unknown power mode = " << powerMode; + return; + } + } + mPowerMode = powerMode; + } + mCondition.notify_all(); +} + void VariableRefreshRateController::setVrrConfigurations( std::unordered_map<hwc2_config_t, VrrConfig_t> configs) { ATRACE_CALL(); + for (const auto& it : configs) { + LOG(INFO) << "VrrController: set Vrr configuration id = " << it.first; + } + const std::lock_guard<std::mutex> lock(mMutex); mVrrConfigs = std::move(configs); } -void VariableRefreshRateController::stopThread() { +void VariableRefreshRateController::stopThread(bool exit) { ATRACE_CALL(); { const std::lock_guard<std::mutex> lock(mMutex); - mThreadExit = true; + mThreadExit = exit; mEnabled = false; mState = VrrControllerState::kDisable; } @@ -172,6 +218,9 @@ void VariableRefreshRateController::onPresent(int fence) { ATRACE_CALL(); { const std::lock_guard<std::mutex> lock(mMutex); + if (mState == VrrControllerState::kDisable) { + return; + } if (!mRecord.mPendingCurrentPresentTime.has_value()) { LOG(WARNING) << "VrrController: VrrController: Present without expected present time " "information"; diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.h b/libhwc2.1/libvrr/VariableRefreshRateController.h index c28b388..796c1f7 100644 --- a/libhwc2.1/libvrr/VariableRefreshRateController.h +++ b/libhwc2.1/libvrr/VariableRefreshRateController.h @@ -50,12 +50,14 @@ public: void setEnable(bool isEnabled); + void setPowerMode(int32_t mode); + void setVrrConfigurations(std::unordered_map<hwc2_config_t, VrrConfig_t> configs); private: static constexpr int kDefaultRingBufferCapacity = 128; static constexpr int64_t kDefaultWakeUpTimeInPowerSaving = - 100 * (std::nano::den / std::milli::den); // 10 Hz = 100 ms + 500 * (std::nano::den / std::milli::den); // 500 ms static constexpr int64_t SIGNAL_TIME_PENDING = INT64_MAX; static constexpr int64_t SIGNAL_TIME_INVALID = -1; @@ -92,7 +94,7 @@ private: std::optional<PresentEvent> mNextExpectedPresentTime = std::nullopt; std::optional<PresentEvent> mPendingCurrentPresentTime = std::nullopt; - ; + typedef RingBuffer<PresentEvent, kDefaultRingBufferCapacity> PresentTimeRecord; typedef RingBuffer<VsyncEvent, kDefaultRingBufferCapacity> VsyncRecord; PresentTimeRecord mPresentHistory; @@ -169,7 +171,7 @@ private: void postEvent(VrrControllerEventType type, int64_t when); - void stopThread(); + void stopThread(bool exit); // The core function of the VRR controller thread. void threadBody(); @@ -180,6 +182,7 @@ private: int mPendingFramesToInsert = 0; std::priority_queue<VrrControllerEvent> mEventQueue; VrrRecord mRecord; + int32_t mPowerMode = -1; VrrControllerState mState; hwc2_config_t mVrrActiveConfig; std::unordered_map<hwc2_config_t, VrrConfig_t> mVrrConfigs; |