summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Chang <cweichun@google.com>2023-11-30 16:40:22 +0000
committerJohn Chang <cweichun@google.com>2023-11-30 17:16:29 +0000
commit633b2fb66c155e7c450c25e03e6b9a7b52500a35 (patch)
treeb2f3950577c3226a38278512653946800f250595
parenta230a07fa931e97f616690ca2ad824f09575a74e (diff)
downloadcommon-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.h3
-rw-r--r--libhwc2.1/libvrr/VariableRefreshRateController.cpp95
-rw-r--r--libhwc2.1/libvrr/VariableRefreshRateController.h9
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.