surfaceflinger: fix fencing when layers become invisible
A layer always holds on to a buffer (after the first one is
acquired). When a new buffer comes in, and the layer is visible, it
will
- acquire the new buffer
- present the new buffer to HWC
- get the release fence from HWC
- associate the old buffer with the release fence and release it
But if the layer happens to be becoming invisible, it will go
through
- acquire the new buffer
- destroy the HWC layer and present
- release the old buffer without any fence
The problem here is that the old buffer is still on screen until the
present takes effect (e.g., on next HW vsync). Rendering artifacts
may be seen on screen.
This commit changes the acquire/release process for layer becoming
invisible to
- acquire the new buffer
- destroy the HWC layer and present
- get a fence from HWC
- associate the old buffer with the fence and release it
We do not require HWC getReleaseFences to return fences for
destroyed layers. We can only use the next best fence, the present
fence.
Bug: 68490054
Test: manual
Change-Id: I68bbf392a6681c6512fc0be68a7d17df122f7308
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 50e2c6f..abf25ec 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -217,9 +217,9 @@
return true;
}
-void Layer::destroyHwcLayer(int32_t hwcId) {
+bool Layer::destroyHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
- return;
+ return false;
}
auto& hwcInfo = mHwcLayers[hwcId];
LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
@@ -228,6 +228,8 @@
// The layer destroyed listener should have cleared the entry from
// mHwcLayers. Verify that.
LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Stale layer entry in mHwcLayers");
+
+ return true;
}
void Layer::destroyAllHwcLayers() {