[SurfaceFlinger] Don't touch hw vsync in DEFAULT RR with kernel timeout
As a power optimization, hw vsync shouldn't be enabled when the kernel
timer resets if the display is going to run at 60hz anyways.
Bug: 136197211
Test: systrace when scrolling at peak refresh rate of 60hz.
Change-Id: Ic7df3e7b735f79b183cdd91f770de83082e491b4
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index cfdbd91..d2270d3 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -380,11 +380,17 @@
}
void Scheduler::setChangeRefreshRateCallback(
- const ChangeRefreshRateCallback& changeRefreshRateCallback) {
+ const ChangeRefreshRateCallback&& changeRefreshRateCallback) {
std::lock_guard<std::mutex> lock(mCallbackLock);
mChangeRefreshRateCallback = changeRefreshRateCallback;
}
+void Scheduler::setGetCurrentRefreshRateTypeCallback(
+ const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateTypeCallback) {
+ std::lock_guard<std::mutex> lock(mCallbackLock);
+ mGetCurrentRefreshRateTypeCallback = getCurrentRefreshRateTypeCallback;
+}
+
void Scheduler::setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod) {
std::lock_guard<std::mutex> lock(mCallbackLock);
mGetVsyncPeriod = getVsyncPeriod;
@@ -427,8 +433,13 @@
void Scheduler::resetKernelTimerCallback() {
ATRACE_INT("ExpiredKernelIdleTimer", 0);
std::lock_guard<std::mutex> lock(mCallbackLock);
- if (mGetVsyncPeriod) {
- resyncToHardwareVsync(true, mGetVsyncPeriod());
+ if (mGetVsyncPeriod && mGetCurrentRefreshRateTypeCallback) {
+ // If we're not in performance mode then the kernel timer shouldn't do
+ // anything, as the refresh rate during DPU power collapse will be the
+ // same.
+ if (mGetCurrentRefreshRateTypeCallback() == Scheduler::RefreshRateType::PERFORMANCE) {
+ resyncToHardwareVsync(true, mGetVsyncPeriod());
+ }
}
}
@@ -450,10 +461,16 @@
}
void Scheduler::expiredKernelTimerCallback() {
+ std::lock_guard<std::mutex> lock(mCallbackLock);
ATRACE_INT("ExpiredKernelIdleTimer", 1);
- // Disable HW Vsync if the timer expired, as we don't need it
- // enabled if we're not pushing frames.
- disableHardwareVsync(false);
+ if (mGetCurrentRefreshRateTypeCallback) {
+ if (mGetCurrentRefreshRateTypeCallback() != Scheduler::RefreshRateType::PERFORMANCE) {
+ // Disable HW Vsync if the timer expired, as we don't need it
+ // enabled if we're not pushing frames, and if we're in PERFORMANCE
+ // mode then we'll need to re-update the DispSync model anyways.
+ disableHardwareVsync(false);
+ }
+ }
}
std::string Scheduler::doDump() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index eaad37c..c97664f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -49,6 +49,7 @@
}
using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+ using GetCurrentRefreshRateTypeCallback = std::function<RefreshRateType()>;
using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
using GetVsyncPeriod = std::function<nsecs_t()>;
@@ -165,7 +166,9 @@
// Updates FPS based on the most content presented.
void updateFpsBasedOnContent();
// Callback that gets invoked when Scheduler wants to change the refresh rate.
- void setChangeRefreshRateCallback(const ChangeRefreshRateCallback& changeRefreshRateCallback);
+ void setChangeRefreshRateCallback(const ChangeRefreshRateCallback&& changeRefreshRateCallback);
+ void setGetCurrentRefreshRateTypeCallback(
+ const GetCurrentRefreshRateTypeCallback&& getCurrentRefreshRateType);
void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
// Returns whether idle timer is enabled or not
@@ -283,6 +286,7 @@
std::unique_ptr<scheduler::IdleTimer> mTouchTimer;
std::mutex mCallbackLock;
+ GetCurrentRefreshRateTypeCallback mGetCurrentRefreshRateTypeCallback GUARDED_BY(mCallbackLock);
ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 94eeef5..577deff 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -713,6 +713,24 @@
Mutex::Autolock lock(mStateLock);
setRefreshRateTo(type, event);
});
+ mScheduler->setGetCurrentRefreshRateTypeCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (!display) {
+ // If we don't have a default display the fallback to the default
+ // refresh rate type
+ return RefreshRateType::DEFAULT;
+ }
+
+ const int configId = display->getActiveConfig();
+ for (const auto& [type, refresh] : mRefreshRateConfigs.getRefreshRates()) {
+ if (refresh && refresh->configId == configId) {
+ return type;
+ }
+ }
+ // This should never happen, but just gracefully fallback to default.
+ return RefreshRateType::DEFAULT;
+ });
mScheduler->setGetVsyncPeriodCallback([this] {
Mutex::Autolock lock(mStateLock);
return getVsyncPeriod();
@@ -1045,6 +1063,7 @@
desiredActiveConfigChangeDone();
return false;
}
+
mUpcomingActiveConfig = desiredActiveConfig;
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);