[SurfaceFlinger] correct present time for negative phase offsets
DispSync::expectedPresentTime returns the expected presentation time for
the current frame, but when we're in negative offsets we are targetting
the following frame instead.
Bug: 133241520
Bug: 134589085
Test: systrace when flinging through news
Change-Id: I7cc05a0b9e8e9b5c3e8d0c4b1d59b0a7dabd43d4
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index bd0b55f..57f1008 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -143,7 +143,7 @@
}
Mutex::Autolock lock(mQueueItemLock);
- return mQueueItems[0].mTimestamp <= mFlinger->mScheduler->expectedPresentTime();
+ return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferQueueLayer::getDesiredPresentTime() {
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 05c721f..203bd72 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -380,7 +380,7 @@
return true;
}
- return mDesiredPresentTime <= mFlinger->mScheduler->expectedPresentTime();
+ return mDesiredPresentTime <= mFlinger->getExpectedPresentTime();
}
nsecs_t BufferStateLayer::getDesiredPresentTime() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 50fabe3..dadb3fe 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1643,6 +1643,18 @@
return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
}
+nsecs_t SurfaceFlinger::getExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
+ DisplayStatInfo stats;
+ mScheduler->getDisplayStatInfo(&stats);
+ const nsecs_t presentTime = mScheduler->expectedPresentTime();
+ // Inflate the expected present time if we're targetting the next vsync.
+ const nsecs_t correctedTime =
+ mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+ ? presentTime
+ : presentTime + stats.vsyncPeriod;
+ return correctedTime;
+}
+
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
switch (what) {
@@ -3244,8 +3256,7 @@
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
- nsecs_t expectedPresentTime;
- expectedPresentTime = mScheduler->expectedPresentTime();
+ const nsecs_t expectedPresentTime = getExpectedPresentTime();
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 74fefa7..3d98ec1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -298,6 +298,11 @@
// TODO: this should be made accessible only to MessageQueue
void onMessageReceived(int32_t what);
+ // Returns the expected present time for this frame.
+ // When we are in negative offsets, we perform a correction so that the
+ // predicted vsync for the *next* frame is used instead.
+ nsecs_t getExpectedPresentTime();
+
// for debugging only
// TODO: this should be made accessible only to HWComposer
const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);