diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 283d149b0..23290e345 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -573,9 +573,12 @@ public: reinterpret_cast(getLayer()->sourceCrop) = crop; } virtual void setVisibleRegionScreen(const Region& reg) { - getLayer()->visibleRegionScreen.rects = - reinterpret_cast( - reg.getArray(&getLayer()->visibleRegionScreen.numRects)); + // Region::getSharedBuffer creates a reference to the underlying + // SharedBuffer of this Region, this reference is freed + // in onDisplayed() + hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen; + SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects); + visibleRegion.rects = reinterpret_cast(sb->data()); } virtual void setBuffer(const sp& buffer) { if (buffer == 0 || buffer->handle == 0) { @@ -586,6 +589,16 @@ public: getLayer()->handle = buffer->handle; } } + virtual void onDisplayed() { + hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen; + SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects); + if (sb) { + sb->release(); + // not technically needed but safer + visibleRegion.numRects = 0; + visibleRegion.rects = NULL; + } + } }; /* diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 8852ab6f8..a49a023f8 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -130,6 +130,7 @@ public: virtual void setVisibleRegionScreen(const Region& reg) = 0; virtual void setBuffer(const sp& buffer) = 0; virtual void setAcquireFenceFd(int fenceFd) = 0; + virtual void onDisplayed() = 0; }; /* diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ea1bc54d0..f928805dd 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -72,6 +72,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client) void Layer::onLayerDisplayed(const sp& hw, HWComposer::HWCLayerInterface* layer) { + LayerBaseClient::onLayerDisplayed(hw, layer); if (layer) { mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd()); } diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index a2513a2c0..87dc572aa 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -288,12 +288,16 @@ void LayerBase::setGeometry( // scaling is already applied in transformedBounds layer.setFrame(transformedBounds); layer.setCrop(transformedBounds.getBounds()); - layer.setVisibleRegionScreen(tr.transform(visibleRegion)); } void LayerBase::setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer) { layer.setBuffer(0); + // we have to set the visible region on every frame because + // we currently free it during onLayerDisplayed(), which is called + // after HWComposer::commit() -- every frame. + const Transform& tr = hw->getTransform(); + layer.setVisibleRegionScreen(tr.transform(visibleRegion)); } void LayerBase::setAcquireFence(const sp& hw, @@ -301,6 +305,13 @@ void LayerBase::setAcquireFence(const sp& hw, layer.setAcquireFenceFd(-1); } +void LayerBase::onLayerDisplayed(const sp& hw, + HWComposer::HWCLayerInterface* layer) { + if (layer) { + layer->onDisplayed(); + } +} + void LayerBase::setFiltering(bool filtering) { mFiltering = filtering; diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index c18f397c3..46515178e 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -218,7 +218,7 @@ public: /** called after page-flip */ virtual void onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer) { } + HWComposer::HWCLayerInterface* layer); /** called before composition. * returns true if the layer has pending updates.