SF: Only latch buffers after fence signals
Changes SurfaceFlinger to only latch a buffer after its corresponding
acquire fence has signaled. This will enable us to move
SurfaceFlinger closer to vsync since there is no risk of fence waits
blocking composition.
Bug: 29413700
Change-Id: I26f4fd600c1611b8d736ec654d1f0f02cf69ae5f
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5145a3f..548b048 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1100,6 +1100,25 @@
}
}
+bool Layer::headFenceHasSignaled() const {
+#ifdef USE_HWC2
+ Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return true;
+ }
+ if (mQueueItems[0].mIsDroppable) {
+ // Even though this buffer's fence may not have signaled yet, it could
+ // be replaced by another buffer before it has a chance to, which means
+ // that it's possible to get into a situation where a buffer is never
+ // able to be latched. To avoid this, grab this buffer anyway.
+ return true;
+ }
+ return mQueueItems[0].mFence->getSignalTime() != INT64_MAX;
+#else
+ return true;
+#endif
+}
+
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
if (point->getFrameNumber() <= mCurrentFrameNumber) {
// Don't bother with a SyncPoint, since we've already latched the
@@ -1357,9 +1376,10 @@
void Layer::notifyAvailableFrames() {
auto headFrameNumber = getHeadFrameNumber();
+ bool headFenceSignaled = headFenceHasSignaled();
Mutex::Autolock lock(mLocalSyncPointMutex);
for (auto& point : mLocalSyncPoints) {
- if (headFrameNumber >= point->getFrameNumber()) {
+ if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
point->setFrameAvailable();
}
}
@@ -1756,6 +1776,13 @@
return outDirtyRegion;
}
+ // If the head buffer's acquire fence hasn't signaled yet, return and
+ // try again later
+ if (!headFenceHasSignaled()) {
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ }
+
// Capture the old state of the layer for comparisons later
const State& s(getDrawingState());
const bool oldOpacity = isOpaque(s);