diff options
author | John Chang <cweichun@google.com> | 2023-11-30 16:40:22 +0000 |
---|---|---|
committer | John Chang <cweichun@google.com> | 2023-11-30 17:16:29 +0000 |
commit | 633b2fb66c155e7c450c25e03e6b9a7b52500a35 (patch) | |
tree | b2f3950577c3226a38278512653946800f250595 | |
parent | a230a07fa931e97f616690ca2ad824f09575a74e (diff) | |
download | common-633b2fb66c155e7c450c25e03e6b9a7b52500a35.tar.gz |
libhwc2.1: vrrController: apply frame insetion
Bug: 305311206
Test: verify successful frame insertion with the configured insertion timer
Change-Id: Ic79ba98fb06217e9620820596f6a1a1a8c636085
-rw-r--r-- | libhwc2.1/libhwchelper/ExynosHWCHelper.h | 3 | ||||
-rw-r--r-- | libhwc2.1/libvrr/VariableRefreshRateController.cpp | 95 | ||||
-rw-r--r-- | libhwc2.1/libvrr/VariableRefreshRateController.h | 9 |
3 files changed, 63 insertions, 44 deletions
diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.h b/libhwc2.1/libhwchelper/ExynosHWCHelper.h index f9cec57..5dbd76e 100644 --- a/libhwc2.1/libhwchelper/ExynosHWCHelper.h +++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.h @@ -692,7 +692,8 @@ public: std::string cmdString = std::to_string(cmd); int ret = write(fd, cmdString.c_str(), std::strlen(cmdString.c_str())); if (ret < 0) { - ALOGE("Write to file node %s failed: %d", mNodePath.c_str(), ret); + ALOGE("Write to file node %s failed, ret = %d errno = %d", mNodePath.c_str(), ret, + errno); return false; } } else { diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.cpp b/libhwc2.1/libvrr/VariableRefreshRateController.cpp index e382c00..f886ec3 100644 --- a/libhwc2.1/libvrr/VariableRefreshRateController.cpp +++ b/libhwc2.1/libvrr/VariableRefreshRateController.cpp @@ -30,6 +30,8 @@ namespace android::hardware::graphics::composer { +const std::string VariableRefreshRateController::kFrameInsertionNodeName = "refresh_ctrl"; + namespace { int64_t getNowNs() { @@ -255,10 +257,14 @@ void VariableRefreshRateController::onPresent(int fence) { mLastPresentFence = dupFence; // Drop the out of date timeout. dropEventLocked(kRenderingTimeout); - dropEventLocked(kNextFrameInsertion); + cancelFrameInsertionLocked(); // Post next rendering timeout. postEvent(VrrControllerEventType::kRenderingTimeout, getNowNs() + mVrrConfigs[mVrrActiveConfig].notifyExpectedPresentConfig.TimeoutNs); + // Post next frmae insertion event. + mPendingFramesToInsert = kDefaultNumFramesToInsert; + postEvent(VrrControllerEventType::kNextFrameInsertion, + getNowNs() + kDefaultFrameInsertionTimer); } mCondition.notify_all(); } @@ -279,55 +285,34 @@ void VariableRefreshRateController::onVsync(int64_t timestampNanos, .mTime = timestampNanos}; } -void VariableRefreshRateController::updateVsyncHistory() { - int fence = -1; - - { - const std::lock_guard<std::mutex> lock(mMutex); - if (!mLastPresentFence.has_value()) { - return; - } - fence = mLastPresentFence.value(); - mLastPresentFence = std::nullopt; - } - - // Execute the following logic unlocked to enhance performance. - int64_t lastSignalTime = getLastFenceSignalTimeUnlocked(fence); - if (close(fence)) { - LOG(ERROR) << "VrrController: close fence file failed, errno = " << errno; - return; - } else if (lastSignalTime == SIGNAL_TIME_PENDING || lastSignalTime == SIGNAL_TIME_INVALID) { - return; - } - - { - // Acquire the mutex again to store the vsync record. - const std::lock_guard<std::mutex> lock(mMutex); - mRecord.mVsyncHistory - .next() = {.mType = VariableRefreshRateController::VsyncEvent::Type::kReleaseFence, - .mTime = lastSignalTime}; - } +void VariableRefreshRateController::cancelFrameInsertionLocked() { + dropEventLocked(kNextFrameInsertion); + mPendingFramesToInsert = 0; } int VariableRefreshRateController::doFrameInsertionLocked() { ATRACE_CALL(); - static const std::string kNodeName = "refresh_ctrl"; + if (mState == VrrControllerState::kDisable) { + cancelFrameInsertionLocked(); + return 0; + } if (mPendingFramesToInsert <= 0) { LOG(ERROR) << "VrrController: the number of frames to be inserted should >= 1, but is " << mPendingFramesToInsert << " now."; return -1; } - bool ret = mFileNodeWritter->WriteCommandString(kNodeName, PANEL_REFRESH_CTRL_FI); + bool ret = mFileNodeWritter->WriteCommandString(kFrameInsertionNodeName, PANEL_REFRESH_CTRL_FI); if (!ret) { - LOG(ERROR) << "VrrController: write command to file node failed."; + LOG(ERROR) << "VrrController: write command to file node failed. " << getStateName(mState) + << " " << mPowerMode; return -1; } if (--mPendingFramesToInsert > 0) { postEvent(VrrControllerEventType::kNextFrameInsertion, getNowNs() + mVrrConfigs[mVrrActiveConfig].minFrameIntervalNs); } - return ret; + return 0; } int VariableRefreshRateController::doFrameInsertionLocked(int frames) { @@ -337,6 +322,7 @@ int VariableRefreshRateController::doFrameInsertionLocked(int frames) { void VariableRefreshRateController::dropEventLocked() { mEventQueue = std::priority_queue<VrrControllerEvent>(); + mPendingFramesToInsert = 0; } void VariableRefreshRateController::dropEventLocked(VrrControllerEventType event_type) { @@ -447,11 +433,6 @@ void VariableRefreshRateController::handleResume() { void VariableRefreshRateController::handleHibernate() { ATRACE_CALL(); - - static constexpr int kNumFramesToInsert = 2; - int ret = doFrameInsertionLocked(kNumFramesToInsert); - LOG(INFO) << "VrrController: apply frame insertion, ret = " << ret; - // TODO(b/305311206): handle entering panel hibernate. postEvent(VrrControllerEventType::kHibernateTimeout, getNowNs() + kDefaultWakeUpTimeInPowerSaving); @@ -513,6 +494,10 @@ void VariableRefreshRateController::threadBody() { handleCadenceChange(); break; } + case VrrControllerEventType::kNextFrameInsertion: { + doFrameInsertionLocked(); + break; + } default: { break; } @@ -538,10 +523,6 @@ void VariableRefreshRateController::threadBody() { stateChanged = true; break; } - case VrrControllerEventType::kNextFrameInsertion: { - doFrameInsertionLocked(); - break; - } default: { break; } @@ -563,4 +544,34 @@ void VariableRefreshRateController::postEvent(VrrControllerEventType type, int64 mEventQueue.emplace(event); } +void VariableRefreshRateController::updateVsyncHistory() { + int fence = -1; + + { + const std::lock_guard<std::mutex> lock(mMutex); + if (!mLastPresentFence.has_value()) { + return; + } + fence = mLastPresentFence.value(); + mLastPresentFence = std::nullopt; + } + + // Execute the following logic unlocked to enhance performance. + int64_t lastSignalTime = getLastFenceSignalTimeUnlocked(fence); + if (close(fence)) { + LOG(ERROR) << "VrrController: close fence file failed, errno = " << errno; + return; + } else if (lastSignalTime == SIGNAL_TIME_PENDING || lastSignalTime == SIGNAL_TIME_INVALID) { + return; + } + + { + // Acquire the mutex again to store the vsync record. + const std::lock_guard<std::mutex> lock(mMutex); + mRecord.mVsyncHistory + .next() = {.mType = VariableRefreshRateController::VsyncEvent::Type::kReleaseFence, + .mTime = lastSignalTime}; + } +} + } // namespace android::hardware::graphics::composer diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.h b/libhwc2.1/libvrr/VariableRefreshRateController.h index 796c1f7..1a20109 100644 --- a/libhwc2.1/libvrr/VariableRefreshRateController.h +++ b/libhwc2.1/libvrr/VariableRefreshRateController.h @@ -61,6 +61,11 @@ private: static constexpr int64_t SIGNAL_TIME_PENDING = INT64_MAX; static constexpr int64_t SIGNAL_TIME_INVALID = -1; + static const std::string kFrameInsertionNodeName; + static constexpr int kDefaultNumFramesToInsert = 2; + static constexpr int64_t kDefaultFrameInsertionTimer = + 33 * (std::nano::den / std::milli::den); // 33 ms + enum class VrrControllerState { kDisable = 0, kRendering, @@ -147,7 +152,7 @@ private: // Implement interface VsyncListener. virtual void onVsync(int64_t timestamp, int32_t vsyncPeriodNanos) override; - void updateVsyncHistory(); + void cancelFrameInsertionLocked(); int doFrameInsertionLocked(); int doFrameInsertionLocked(int frames); @@ -176,6 +181,8 @@ private: // The core function of the VRR controller thread. void threadBody(); + void updateVsyncHistory(); + ExynosDisplay* mDisplay; // The subsequent variables must be guarded by mMutex when accessed. |