Early wake-up for transitions (1/2)
On some devices it's very likely that we fall into GL comp during
app transitions. However, SF offsets are chosen in a way such that
the time to finish a frame is just too tight to be completely jank
free when hitting GL composition in SurfaceFlinger. Thus, we
introduce the concept of a separate early offset, and wakeup
SurfaceFlinger at that time if we think that hitting GL comp is
likely, or we already hit GL comp in the last frame.
Test: Open app, check vsync offsets in systrace
Test: Open many dialogs/apps to fall into GPU comp.
Bug: 75985430
Change-Id: Ie17e30c4575359fa11bb8912f68dcafe3e569ddb
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 18b2f68..50495ec 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -296,6 +296,12 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
+ property_get("debug.sf.early_phase_offset_ns", value, "0");
+ const int earlyWakeupOffsetOffsetNs = atoi(value);
+ ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset");
+ mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs,
+ sfVsyncPhaseOffsetNs);
+
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
// comes online to attempt to read the property. The property is
@@ -522,19 +528,10 @@
return;
}
- // Remove the listener with the old offset
- status_t err = mDispSync->removeEventListener(
- static_cast<DispSync::Callback*>(this));
+ status_t err = mDispSync->changePhaseOffset(static_cast<DispSync::Callback*>(this),
+ mPhaseOffset);
if (err != NO_ERROR) {
- ALOGE("error unregistering vsync callback: %s (%d)",
- strerror(-err), err);
- }
-
- // Add a listener with the new offset
- err = mDispSync->addEventListener(mName, mPhaseOffset,
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error registering vsync callback: %s (%d)",
+ ALOGE("error changing vsync offset: %s (%d)",
strerror(-err), err);
}
}
@@ -623,6 +620,7 @@
mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), *this, true,
"sfEventThread");
mEventQueue->setEventThread(mSFEventThread.get());
+ mVsyncModulator.setEventThread(mSFEventThread.get());
// Get a RenderEngine for the given display / config (can't fail)
getBE().mRenderEngine =
@@ -1498,6 +1496,7 @@
mHadClientComposition = mHadClientComposition ||
getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
}
+ mVsyncModulator.setLastFrameUsedRenderEngine(mHadClientComposition);
mLayersWithQueuedFrames.clear();
}
@@ -2122,6 +2121,7 @@
// with mStateLock held to guarantee that mCurrentState won't change
// until the transaction is committed.
+ mVsyncModulator.setTransactionStart(VSyncModulator::TransactionStart::NORMAL);
transactionFlags = getTransactionFlags(eTransactionMask);
handleTransactionLocked(transactionFlags);
@@ -3070,7 +3070,13 @@
}
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
+ return setTransactionFlags(flags, VSyncModulator::TransactionStart::NORMAL);
+}
+
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags,
+ VSyncModulator::TransactionStart transactionStart) {
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
+ mVsyncModulator.setTransactionStart(transactionStart);
if ((old & flags)==0) { // wake the server up
signalTransaction();
}
@@ -3159,7 +3165,10 @@
}
// this triggers the transaction
- setTransactionFlags(transactionFlags);
+ const auto start = (flags & eEarlyWakeup)
+ ? VSyncModulator::TransactionStart::EARLY
+ : VSyncModulator::TransactionStart::NORMAL;
+ setTransactionFlags(transactionFlags, start);
// if this is a synchronous transaction, wait for it to take effect
// before returning.
@@ -4099,9 +4108,9 @@
colorizer.bold(result);
result.append("DispSync configuration: ");
colorizer.reset(result);
- result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
- "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+ result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
+ " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
result.append("\n");