Merge "surfaceflinger: fix fencing when layers become invisible"
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index fc60002..44e40d5 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -399,6 +399,14 @@
return mVisibleLayersSortedByZ;
}
+void DisplayDevice::setLayersNeedingFences(const Vector< sp<Layer> >& layers) {
+ mLayersNeedingFences = layers;
+}
+
+const Vector< sp<Layer> >& DisplayDevice::getLayersNeedingFences() const {
+ return mLayersNeedingFences;
+}
+
Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
Region dirty;
if (repaintEverything) {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8636e2a..e8a5929 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -124,6 +124,8 @@
void setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
+ void setLayersNeedingFences(const Vector< sp<Layer> >& layers);
+ const Vector< sp<Layer> >& getLayersNeedingFences() const;
Region getDirtyRegion(bool repaintEverything) const;
void setLayerStack(uint32_t stack);
@@ -241,6 +243,8 @@
// list of visible layers on that display
Vector< sp<Layer> > mVisibleLayersSortedByZ;
+ // list of layers needing fences
+ Vector< sp<Layer> > mLayersNeedingFences;
/*
* Transaction state
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1b864fd..1fa3faa 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -208,9 +208,6 @@
#ifdef USE_HWC2
void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
- if (mHwcLayers.empty()) {
- return;
- }
mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
}
#else
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 32f3e18..a60c25d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1674,6 +1674,7 @@
Region opaqueRegion;
Region dirtyRegion;
Vector<sp<Layer>> layersSortedByZ;
+ Vector<sp<Layer>> layersNeedingFences;
const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
const Transform& tr(displayDevice->getTransform());
const Rect bounds(displayDevice->getBounds());
@@ -1681,6 +1682,7 @@
computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
mDrawingState.traverseInZOrder([&](Layer* layer) {
+ bool hwcLayerDestroyed = false;
if (layer->belongsToDisplay(displayDevice->getLayerStack(),
displayDevice->isPrimary())) {
Region drawRegion(tr.transform(
@@ -1691,6 +1693,8 @@
} else {
// Clear out the HWC layer if this layer was
// previously visible, but no longer is
+ hwcLayerDestroyed = layer->hasHwcLayer(
+ displayDevice->getHwcDisplayId());
layer->setHwcLayer(displayDevice->getHwcDisplayId(),
nullptr);
}
@@ -1698,12 +1702,26 @@
// WM changes displayDevice->layerStack upon sleep/awake.
// Here we make sure we delete the HWC layers even if
// WM changed their layer stack.
+ hwcLayerDestroyed = layer->hasHwcLayer(displayDevice->getHwcDisplayId());
layer->setHwcLayer(displayDevice->getHwcDisplayId(),
nullptr);
}
+
+ // If a layer is not going to get a release fence because
+ // it is invisible, but it is also going to release its
+ // old buffer, add it to the list of layers needing
+ // fences.
+ if (hwcLayerDestroyed) {
+ auto found = std::find(mLayersWithQueuedFrames.cbegin(),
+ mLayersWithQueuedFrames.cend(), layer);
+ if (found != mLayersWithQueuedFrames.cend()) {
+ layersNeedingFences.add(layer);
+ }
+ }
});
}
displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
+ displayDevice->setLayersNeedingFences(layersNeedingFences);
displayDevice->undefinedRegion.set(bounds);
displayDevice->undefinedRegion.subtractSelf(
tr.transform(opaqueRegion));
@@ -1942,6 +1960,17 @@
layer->onLayerDisplayed(releaseFence);
}
+
+ // We've got a list of layers needing fences, that are disjoint with
+ // displayDevice->getVisibleLayersSortedByZ. The best we can do is to
+ // supply them with the present fence.
+ if (!displayDevice->getLayersNeedingFences().isEmpty()) {
+ sp<Fence> presentFence = mHwc->getPresentFence(hwcId);
+ for (auto& layer : displayDevice->getLayersNeedingFences()) {
+ layer->onLayerDisplayed(presentFence);
+ }
+ }
+
if (hwcId >= 0) {
mHwc->clearReleaseFences(hwcId);
}