SF: Stop passing DispSync around.
Instead of passing DispSync around, so that the functions can compute
next refresh time, compute the time in SurfaceFlinger, and pass around
the calculated value.
Test: SF tests pass.
Change-Id: I27f28257c866426bc871671eb57dd309b88b92be
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 54a1b51..a12ae83 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -726,6 +726,54 @@
result.appendFormat("current monotonic time: %" PRId64 "\n", now);
}
+// TODO(b/113612090): Figure out how much of this is still relevant.
+// We need to determine the time when a buffer acquired now will be
+// displayed. This can be calculated:
+// time when previous buffer's actual-present fence was signaled
+// + current display refresh rate * HWC latency
+// + a little extra padding
+//
+// Buffer producers are expected to set their desired presentation time
+// based on choreographer time stamps, which (coming from vsync events)
+// will be slightly later then the actual-present timing. If we get a
+// desired-present time that is unintentionally a hair after the next
+// vsync, we'll hold the frame when we really want to display it. We
+// need to take the offset between actual-present and reported-vsync
+// into account.
+//
+// If the system is configured without a DispSync phase offset for the app,
+// we also want to throw in a bit of padding to avoid edge cases where we
+// just barely miss. We want to do it here, not in every app. A major
+// source of trouble is the app's use of the display's ideal refresh time
+// (via Display.getRefreshRate()), which could be off of the actual refresh
+// by a few percent, with the error multiplied by the number of frames
+// between now and when the buffer should be displayed.
+//
+// If the refresh reported to the app has a phase offset, we shouldn't need
+// to tweak anything here.
+nsecs_t DispSync::expectedPresentTime() {
+ // The HWC doesn't currently have a way to report additional latency.
+ // Assume that whatever we submit now will appear right after the flip.
+ // For a smart panel this might be 1. This is expressed in frames,
+ // rather than time, because we expect to have a constant frame delay
+ // regardless of the refresh rate.
+ const uint32_t hwcLatency = 0;
+
+ // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
+ const nsecs_t nextRefresh = computeNextRefresh(hwcLatency);
+
+ // The DispSync time is already adjusted for the difference between
+ // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
+ // we don't need to factor that in here. Pad a little to avoid
+ // weird effects if apps might be requesting times right on the edge.
+ nsecs_t extraPadding = 0;
+ if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
+ extraPadding = 1000000; // 1ms (6% of 60Hz)
+ }
+
+ return nextRefresh + extraPadding;
+}
+
} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index b3aef2d..89f5cdb 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -57,6 +57,7 @@
virtual status_t changePhaseOffset(Callback* callback, nsecs_t phase) = 0;
virtual nsecs_t computeNextRefresh(int periodOffset) const = 0;
virtual void setIgnorePresentFences(bool ignore) = 0;
+ virtual nsecs_t expectedPresentTime() = 0;
virtual void dump(String8& result) const = 0;
};
@@ -164,6 +165,9 @@
// true from addPresentFence() and addResyncSample().
void setIgnorePresentFences(bool ignore) override;
+ // Determine the expected present time when a buffer acquired now will be displayed.
+ nsecs_t expectedPresentTime();
+
// dump appends human-readable debug info to the result string.
void dump(String8& result) const override;