From 0de75f3f53ad2e3eb4c6820446c5175191b6631a Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Mon, 8 Oct 2012 10:39:21 -0700 Subject: [PATCH] Stop using transparent region for computing visible regions (DO NOT MERGE) The transparent region hint is computed only from view layout locations, ignoring post-layout translation. If a SurfaceView is layed out with no other views above it, but a view is moved above it post-layout, that view's layout bounds would be subtracted from the window's transparent region instead of its drawing bounds. Prior to this change, the view would not be visible (except where its layout bounds and drawing bounds overlap). With this change, composition uses visible regions computed without regard to the transparent regions. However, if all of a layer's visible region is transparent, it will be removed from the list of layers to composite. This doesn't fix the root problem of incorrect transparent regions, and doesn't prevent bad composition in all cases. But it does avoid it for some existing apps, while still allowing the transparent region hint to save power in the important fullscreen-video-in-a-SurfaceView case. Change-Id: If2d929a10399b80401ef902abb232233a7f3d16d --- services/surfaceflinger/LayerBase.cpp | 6 ++++++ services/surfaceflinger/LayerBase.h | 10 +++++++++- services/surfaceflinger/SurfaceFlinger.cpp | 16 ++++++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 16bac8f79..a4da92f2c 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -196,6 +196,12 @@ void LayerBase::setCoveredRegion(const Region& coveredRegion) { coveredRegionScreen = coveredRegion; } +void LayerBase::setVisibleNonTransparentRegion(const Region& + visibleNonTransparentRegion) { + // always called from main thread + this->visibleNonTransparentRegion = visibleNonTransparentRegion; +} + uint32_t LayerBase::doTransaction(uint32_t flags) { const Layer::State& front(drawingState()); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index c547a4072..94d074abf 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -63,6 +63,7 @@ public: Region visibleRegionScreen; Region transparentRegionScreen; Region coveredRegionScreen; + Region visibleNonTransparentRegion; int32_t sequence; struct Geometry { @@ -98,7 +99,7 @@ public: bool setSize(uint32_t w, uint32_t h); bool setAlpha(uint8_t alpha); bool setMatrix(const layer_state_t::matrix22_t& matrix); - bool setTransparentRegionHint(const Region& opaque); + bool setTransparentRegionHint(const Region& transparent); bool setFlags(uint8_t flags, uint8_t mask); bool setCrop(const Rect& crop); @@ -158,6 +159,13 @@ public: */ virtual void setCoveredRegion(const Region& coveredRegion); + /** + * setVisibleNonTransparentRegion - called when the visible and + * non-transparent region changes. + */ + virtual void setVisibleNonTransparentRegion(const Region& + visibleNonTransparentRegion); + /** * validateVisibility - cache a bunch of things */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 51fcce43e..859db58bc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -620,6 +620,16 @@ void SurfaceFlinger::computeVisibleRegions( */ Region coveredRegion; + /* + * transparentRegion: area of a surface that is hinted to be completely + * transparent. This is only used to tell when the layer has no visible + * non-transparent regions and can be removed from the layer list. It + * does not affect the visibleRegion of this layer or any layers + * beneath it. The hint may not be correct if apps don't respect the + * SurfaceView restrictions (which, sadly, some don't). + */ + Region transparentRegion; + // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) { @@ -630,7 +640,7 @@ void SurfaceFlinger::computeVisibleRegions( if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { - visibleRegion.subtractSelf(layer->transparentRegionScreen); + transparentRegion = layer->transparentRegionScreen; } // compute the opaque region @@ -689,6 +699,8 @@ void SurfaceFlinger::computeVisibleRegions( // Store the visible region is screen space layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); + layer->setVisibleNonTransparentRegion( + visibleRegion.subtract(transparentRegion)); // If a secure layer is partially visible, lock-down the screen! if (layer->isSecure() && !visibleRegion.isEmpty()) { @@ -740,7 +752,7 @@ void SurfaceFlinger::handlePageFlip() mVisibleLayersSortedByZ.clear(); mVisibleLayersSortedByZ.setCapacity(count); for (size_t i=0 ; ivisibleRegionScreen.isEmpty()) + if (!currentLayers[i]->visibleNonTransparentRegion.isEmpty()) mVisibleLayersSortedByZ.add(currentLayers[i]); }