SF: Update present timing per display
Calculate presentation timing info (i.e. expected- and earliest-
PresentTime) separately for each display, since they are generally not
in sync. This allows SF to present each display at the proper time,
using tools that are already in use for the pacesetter display.
CompositionRefreshArgs:
- Replace earliest- and expected- PresentTime with a map of
FrameTargets which hold the times.
Output:
- Retrieve appropriate times from the relevant FrameTarget.
- Note: Since HAL virtual displays do not have a FrameTarget, they now
are provided with the default expected (0) and earliest (nullopt)
-PresentTimes. This is fine, since these times are irrelevant for
a virtual display. Previously, they simply used the pacesetter's
times.
- Trace the expected present time.
Scheduler:
- Compute the expectedPresentTime aka expectedVsyncTime for follower
displays via the next VSYNC after the pacesetter's
expectedPresentTime. TODO (b/256196556): The "followers" should
follow the frontrunner, not the pacesetter.
SurfaceFlinger:
- Populate CompositionRefreshArgs' map of FrameTargets.
For now, continue using the same scheduledFrameTime for all follower
displays. This is only used as a deadline for determining whether to
render a CachedSet. Adjusting it per follower would make us more likely
to render more CachedSets per frame, and we need a more holistic
approach for caching anyway.
Bug: 255601557
Bug: 256196556
Bug: 259132483
Test: perfetto traces
Change-Id: I2c27dc709afd1f33bddbf9c2ca1cd61dd335f66c
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5f10e79..c22f2b3 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -190,7 +190,6 @@
const FrameTargeter::BeginFrameArgs beginFrameArgs =
{.frameBeginTime = SchedulerClock::now(),
.vsyncId = vsyncId,
- // TODO(b/255601557): Calculate per display.
.expectedVsyncTime = expectedVsyncTime,
.sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
.hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration};
@@ -202,11 +201,20 @@
FrameTargets targets;
targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target());
+ // TODO (b/256196556): Followers should use the next VSYNC after the frontrunner, not the
+ // pacesetter.
+ // Update expectedVsyncTime, which may have been adjusted by beginFrame.
+ expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime();
+
for (const auto& [id, display] : mDisplays) {
if (id == pacesetterPtr->displayId) continue;
+ auto followerBeginFrameArgs = beginFrameArgs;
+ followerBeginFrameArgs.expectedVsyncTime =
+ display.schedulePtr->vsyncDeadlineAfter(expectedVsyncTime);
+
FrameTargeter& targeter = *display.targeterPtr;
- targeter.beginFrame(beginFrameArgs, *display.schedulePtr);
+ targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr);
targets.try_emplace(id, &targeter.target());
}