summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Chang <cweichun@google.com>2023-11-03 21:45:14 +0000
committerJohn Chang <cweichun@google.com>2023-11-22 16:34:16 +0000
commitad24e0f98c17e6379be9444990fd6626e1ba36fa (patch)
tree80145d05d90dd6c24d25c9d66389669ad8c8e2f8
parent8dbde53ab1b8e89b40d7ef95c9d3d8f35eeec322 (diff)
downloadcommon-ad24e0f98c17e6379be9444990fd6626e1ba36fa.tar.gz
libhwc2.1: vrrController: address issue of missing to close fence file
Bug: 309156309 Test: initially, the issue would occur after about 10 minutes of operation. With this fix, conducting playback tests for over 2 hours, the system remains stable. Change-Id: I1b140aabb0f21388fb0ae4b95d8ddd7eb9b7dd6d
-rw-r--r--libhwc2.1/libvrr/VariableRefreshRateController.cpp107
-rw-r--r--libhwc2.1/libvrr/VariableRefreshRateController.h8
2 files changed, 82 insertions, 33 deletions
diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.cpp b/libhwc2.1/libvrr/VariableRefreshRateController.cpp
index cf0ab5b..60beb7f 100644
--- a/libhwc2.1/libvrr/VariableRefreshRateController.cpp
+++ b/libhwc2.1/libvrr/VariableRefreshRateController.cpp
@@ -71,6 +71,18 @@ VariableRefreshRateController::VariableRefreshRateController(ExynosDisplay* disp
}
}
+VariableRefreshRateController::~VariableRefreshRateController() {
+ stopThread();
+
+ const std::lock_guard<std::mutex> lock(mMutex);
+ if (mLastPresentFence.has_value()) {
+ if (close(mLastPresentFence.value())) {
+ LOG(ERROR) << "VrrController:: close fence file failed, errno = " << errno;
+ }
+ mLastPresentFence = std::nullopt;
+ }
+};
+
int VariableRefreshRateController::notifyExpectedPresent(int64_t timestamp,
int32_t frameIntervalNs) {
ATRACE_CALL();
@@ -90,8 +102,13 @@ void VariableRefreshRateController::reset() {
const std::lock_guard<std::mutex> lock(mMutex);
mEventQueue = std::priority_queue<VrrControllerEvent>();
mRecord.clear();
- mLastFence = -1;
dropEventLocked();
+ if (mLastPresentFence.has_value()) {
+ if (close(mLastPresentFence.value())) {
+ LOG(ERROR) << "VrrController:: close fence file failed, errno = " << errno;
+ }
+ mLastPresentFence = std::nullopt;
+ }
}
void VariableRefreshRateController::setActiveVrrConfiguration(hwc2_config_t config) {
@@ -149,8 +166,6 @@ void VariableRefreshRateController::stopThread() {
void VariableRefreshRateController::onPresent(int fence) {
ATRACE_CALL();
- int lastFence;
- hwc2_config_t currentConfig;
{
const std::lock_guard<std::mutex> lock(mMutex);
if (!mRecord.mPendingCurrentPresentTime.has_value()) {
@@ -158,9 +173,6 @@ void VariableRefreshRateController::onPresent(int fence) {
"information";
return;
} else {
- LOG(INFO) << "VrrController: On present frame: time = "
- << mRecord.mPendingCurrentPresentTime.value().mTime
- << " duration = " << mRecord.mPendingCurrentPresentTime.value().mDuration;
mRecord.mPresentHistory.next() = mRecord.mPendingCurrentPresentTime.value();
mRecord.mPendingCurrentPresentTime = std::nullopt;
}
@@ -170,9 +182,24 @@ void VariableRefreshRateController::onPresent(int fence) {
mState = VrrControllerState::kRendering;
dropEventLocked(kHibernateTimeout);
}
- lastFence = mLastFence;
- currentConfig = mVrrActiveConfig;
- mLastFence = dup(fence);
+ }
+
+ // Prior to pushing the most recent fence update, verify the release timestamps of all preceding
+ // fences.
+ // TODO(b/309873055): delegate the task of executing updateVsyncHistory to the Vrr controller's
+ // loop thread in order to reduce the workload of calling thread.
+ updateVsyncHistory();
+ int dupFence = dup(fence);
+ if (dupFence < 0) {
+ LOG(ERROR) << "VrrController: duplicate fence file failed." << errno;
+ }
+
+ {
+ const std::lock_guard<std::mutex> lock(mMutex);
+ if (mLastPresentFence.has_value()) {
+ LOG(WARNING) << "VrrController: last present fence remains open.";
+ }
+ mLastPresentFence = dupFence;
// Drop the out of date timeout.
dropEventLocked(kRenderingTimeout);
dropEventLocked(kNextFrameInsertion);
@@ -181,21 +208,6 @@ void VariableRefreshRateController::onPresent(int fence) {
getNowNs() + mVrrConfigs[mVrrActiveConfig].notifyExpectedPresentConfig.TimeoutNs);
}
mCondition.notify_all();
-
- if (lastFence < 0) {
- return;
- }
- int64_t lastSignalTime = getLastFenceSignalTimeUnlocked(lastFence);
- 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,
- .mConfig = currentConfig,
- .mTime = lastSignalTime};
}
void VariableRefreshRateController::setExpectedPresentTime(int64_t timestampNanos,
@@ -211,10 +223,39 @@ void VariableRefreshRateController::onVsync(int64_t timestampNanos,
const std::lock_guard<std::mutex> lock(mMutex);
mRecord.mVsyncHistory
.next() = {.mType = VariableRefreshRateController::VsyncEvent::Type::kVblank,
- .mConfig = mVrrActiveConfig,
.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};
+ }
+}
+
int VariableRefreshRateController::doFrameInsertionLocked() {
ATRACE_CALL();
static const std::string kNodeName = "refresh_ctrl";
@@ -336,7 +377,7 @@ void VariableRefreshRateController::handleCadenceChange() {
"information.";
return;
}
- // TODO(cweichun): handle frame rate change.
+ // TODO(b/305311056): handle frame rate change.
mRecord.mNextExpectedPresentTime = std::nullopt;
}
@@ -347,7 +388,7 @@ void VariableRefreshRateController::handleResume() {
<< "VrrController: resume occurs without the expected present timing information.";
return;
}
- // TODO(cweichun): handle panel resume.
+ // TODO(b/305311281): handle panel resume.
mRecord.mNextExpectedPresentTime = std::nullopt;
}
@@ -358,14 +399,14 @@ void VariableRefreshRateController::handleHibernate() {
int ret = doFrameInsertionLocked(kNumFramesToInsert);
LOG(INFO) << "VrrController: apply frame insertion, ret = " << ret;
- // TODO(cweichun): handle entering panel hibernate.
+ // TODO(b/305311206): handle entering panel hibernate.
postEvent(VrrControllerEventType::kHibernateTimeout,
getNowNs() + kDefaultWakeUpTimeInPowerSaving);
}
void VariableRefreshRateController::handleStayHibernate() {
ATRACE_CALL();
- // TODO(cweichun): handle keeping panel hibernate.
+ // TODO(b/305311698): handle keeping panel hibernate.
postEvent(VrrControllerEventType::kHibernateTimeout,
getNowNs() + kDefaultWakeUpTimeInPowerSaving);
}
@@ -377,6 +418,7 @@ void VariableRefreshRateController::threadBody() {
return;
}
for (;;) {
+ bool stateChanged = false;
{
std::unique_lock<std::mutex> lock(mMutex);
if (mThreadExit) break;
@@ -411,6 +453,7 @@ void VariableRefreshRateController::threadBody() {
case VrrControllerEventType::kRenderingTimeout: {
handleHibernate();
mState = VrrControllerState::kHibernate;
+ stateChanged = true;
break;
}
case VrrControllerEventType::kNotifyExpectedPresentConfig: {
@@ -439,6 +482,7 @@ void VariableRefreshRateController::threadBody() {
case VrrControllerEventType::kNotifyExpectedPresentConfig: {
handleResume();
mState = VrrControllerState::kRendering;
+ stateChanged = true;
break;
}
case VrrControllerEventType::kNextFrameInsertion: {
@@ -451,6 +495,11 @@ void VariableRefreshRateController::threadBody() {
}
}
}
+ // TODO(b/309873055): implement a handler to serialize all outer function calls to the same
+ // thread owned by the VRR controller.
+ if (stateChanged) {
+ updateVsyncHistory();
+ }
}
}
diff --git a/libhwc2.1/libvrr/VariableRefreshRateController.h b/libhwc2.1/libvrr/VariableRefreshRateController.h
index 5c8043d..c28b388 100644
--- a/libhwc2.1/libvrr/VariableRefreshRateController.h
+++ b/libhwc2.1/libvrr/VariableRefreshRateController.h
@@ -34,7 +34,7 @@ constexpr uint64_t kMillisecondToNanoSecond = 1000000;
class VariableRefreshRateController : public VsyncListener, public PresentListener {
public:
- ~VariableRefreshRateController() { stopThread(); };
+ ~VariableRefreshRateController();
auto static CreateInstance(ExynosDisplay* display)
-> std::shared_ptr<VariableRefreshRateController>;
@@ -77,7 +77,6 @@ private:
kReleaseFence,
};
Type mType;
- hwc2_config_t mConfig;
int64_t mTime;
} VsyncEvent;
@@ -146,6 +145,8 @@ private:
// Implement interface VsyncListener.
virtual void onVsync(int64_t timestamp, int32_t vsyncPeriodNanos) override;
+ void updateVsyncHistory();
+
int doFrameInsertionLocked();
int doFrameInsertionLocked(int frames);
@@ -182,8 +183,7 @@ private:
VrrControllerState mState;
hwc2_config_t mVrrActiveConfig;
std::unordered_map<hwc2_config_t, VrrConfig_t> mVrrConfigs;
-
- int mLastFence = -1;
+ std::optional<int> mLastPresentFence;
std::unique_ptr<FileNodeWriter> mFileNodeWritter;