summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/surfaceflinger/BufferLayer.cpp3
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp8
-rw-r--r--services/surfaceflinger/DisplayDevice.h4
-rw-r--r--services/surfaceflinger/Layer.cpp6
-rw-r--r--services/surfaceflinger/Layer.h2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp31
6 files changed, 46 insertions, 8 deletions
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index c477a3b190..4e214d1b74 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -262,9 +262,6 @@ void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
}
void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
- if (mHwcLayers.empty()) {
- return;
- }
mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index ef7d482f28..6d6781e4d4 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -325,6 +325,14 @@ const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
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 50e30b2571..e388a5b2c3 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -113,6 +113,8 @@ public:
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);
@@ -214,6 +216,8 @@ private:
// 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 50e2c6f55c..abf25ec117 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -217,9 +217,9 @@ bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
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 @@ void Layer::destroyHwcLayer(int32_t hwcId) {
// 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() {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0fc5ad55d2..44b178a71b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -414,7 +414,7 @@ public:
// -----------------------------------------------------------------------
bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
- void destroyHwcLayer(int32_t hwcId);
+ bool destroyHwcLayer(int32_t hwcId);
void destroyAllHwcLayers();
bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1237ee4320..4e73bfa6b7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1781,6 +1781,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
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());
@@ -1788,6 +1789,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
mDrawingState.traverseInZOrder([&](Layer* layer) {
+ bool hwcLayerDestroyed = false;
if (layer->belongsToDisplay(displayDevice->getLayerStack(),
displayDevice->isPrimary())) {
Region drawRegion(tr.transform(
@@ -1798,18 +1800,32 @@ void SurfaceFlinger::rebuildLayerStacks() {
} else {
// Clear out the HWC layer if this layer was
// previously visible, but no longer is
- layer->destroyHwcLayer(
+ hwcLayerDestroyed = layer->destroyHwcLayer(
displayDevice->getHwcDisplayId());
}
} else {
// WM changes displayDevice->layerStack upon sleep/awake.
// Here we make sure we delete the HWC layers even if
// WM changed their layer stack.
- layer->destroyHwcLayer(displayDevice->getHwcDisplayId());
+ hwcLayerDestroyed = layer->destroyHwcLayer(
+ displayDevice->getHwcDisplayId());
+ }
+
+ // 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));
@@ -2046,6 +2062,17 @@ void SurfaceFlinger::postFramebuffer()
}
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);
}