diff options
| -rw-r--r-- | services/surfaceflinger/BufferLayer.cpp | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 8 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 31 |
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); } |