SF: do not skip a frame if it will not cause backpressure on dvrr
Bug: 340633280
Test: android.platform.test.scenario.sysui.people.PeopleSpaceActivityMicrobenchmark#startPeopleSpaceActivity
Change-Id: If230ef0ab2f8ac3846e4e3701e51d1821192548c
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 0b47924..85ce713 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -650,29 +650,33 @@
const auto threshold = model.slope / 2;
const auto lastFrameMissed =
lastVsyncOpt && std::abs(*lastVsyncOpt - missedVsync.vsync.ns()) < threshold;
- if (FlagManager::getInstance().vrr_config() && lastFrameMissed) {
- // If the last frame missed is the last vsync, we already shifted the timeline. Depends on
- // whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a different
- // fixup. There is no need to to shift the vsync timeline again.
- vsyncTime += missedVsync.fixup.ns();
- ATRACE_FORMAT_INSTANT("lastFrameMissed");
- } else if (FlagManager::getInstance().vrr_config() && minFramePeriodOpt && mRenderRateOpt &&
- lastVsyncOpt) {
- // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
- // first before trying to use it.
- lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
- const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
- if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
- // avoid a duplicate vsync
- ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f which "
- "is %.2f "
- "from "
- "prev. "
- "adjust by %.2f",
- static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
- static_cast<float>(vsyncDiff) / 1e6f,
- static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
- vsyncTime += mRenderRateOpt->getPeriodNsecs();
+ const auto mightBackpressure = minFramePeriodOpt && mRenderRateOpt &&
+ mRenderRateOpt->getPeriod() < 2 * (*minFramePeriodOpt);
+ if (FlagManager::getInstance().vrr_config()) {
+ if (lastFrameMissed) {
+ // If the last frame missed is the last vsync, we already shifted the timeline. Depends
+ // on whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a
+ // different fixup. There is no need to to shift the vsync timeline again.
+ vsyncTime += missedVsync.fixup.ns();
+ ATRACE_FORMAT_INSTANT("lastFrameMissed");
+ } else if (mightBackpressure && lastVsyncOpt) {
+ // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it
+ // first before trying to use it.
+ lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt);
+ const auto vsyncDiff = vsyncTime - *lastVsyncOpt;
+ if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) {
+ // avoid a duplicate vsync
+ ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f "
+ "which "
+ "is %.2f "
+ "from "
+ "prev. "
+ "adjust by %.2f",
+ static_cast<float>(vsyncTime - TimePoint::now().ns()) / 1e6f,
+ static_cast<float>(vsyncDiff) / 1e6f,
+ static_cast<float>(mRenderRateOpt->getPeriodNsecs()) / 1e6f);
+ vsyncTime += mRenderRateOpt->getPeriodNsecs();
+ }
}
}