diff options
author | Jesse Hall <jessehall@google.com> | 2012-09-25 13:25:04 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-09-26 14:41:51 -0700 |
commit | a8026d21f3f2f09e3416cbd33c277fbd15d8cf4e (patch) | |
tree | ab34dbb4e229553d34681daa0646e3481ee14852 | |
parent | c4a8daaa998ea524c9aaa9817021ff7c4467c3dd (diff) | |
download | frameworks_native-a8026d21f3f2f09e3416cbd33c277fbd15d8cf4e.zip frameworks_native-a8026d21f3f2f09e3416cbd33c277fbd15d8cf4e.tar.gz frameworks_native-a8026d21f3f2f09e3416cbd33c277fbd15d8cf4e.tar.bz2 |
Stop using transparent region for computing visible regions
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, whiel still allowing the
transparent region hint to save power in the important
fullscreen-video-in-a-SurfaceView case.
Bug: 7179570
Change-Id: I47cf939e12129b167afa344b8b036e8827103ac8
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 10 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 29 |
3 files changed, 35 insertions, 10 deletions
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index d75dddd..db4ef87 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -193,6 +193,12 @@ void LayerBase::setCoveredRegion(const Region& coveredRegion) { this->coveredRegion = coveredRegion; } +void LayerBase::setVisibleNonTransparentRegion(const Region& + setVisibleNonTransparentRegion) { + // always called from main thread + this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; +} + 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 0df41ca..00c4ffe 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -60,6 +60,7 @@ public: // regions below are in window-manager space Region visibleRegion; Region coveredRegion; + Region visibleNonTransparentRegion; int32_t sequence; struct Geometry { @@ -110,7 +111,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); bool setLayerStack(uint32_t layerStack); @@ -177,6 +178,13 @@ public: virtual void setCoveredRegion(const Region& coveredRegion); /** + * setVisibleNonTransparentRegion - called when the visible and + * non-transparent region changes. + */ + virtual void setVisibleNonTransparentRegion(const Region& + visibleNonTransparentRegion); + + /** * latchBuffer - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy * operation, so this should be set only if needed). Typically this is used diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b3650bd..521e14a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -919,9 +919,10 @@ void SurfaceFlinger::rebuildLayerStacks() { const sp<LayerBase>& layer(currentLayers[i]); const Layer::State& s(layer->drawingState()); if (s.layerStack == hw->getLayerStack()) { - Region visibleRegion(tr.transform(layer->visibleRegion)); - visibleRegion.andSelf(bounds); - if (!visibleRegion.isEmpty()) { + Region drawRegion(tr.transform( + layer->visibleNonTransparentRegion)); + drawRegion.andSelf(bounds); + if (!drawRegion.isEmpty()) { layersSortedByZ.add(layer); } } @@ -1294,6 +1295,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(layer->isVisible())) { @@ -1303,21 +1314,19 @@ void SurfaceFlinger::computeVisibleRegions( if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { - Region transparentRegionScreen; const Transform tr(s.transform); if (tr.transformed()) { if (tr.preserveRects()) { // transform the transparent region - transparentRegionScreen = tr.transform(s.transparentRegion); + transparentRegion = tr.transform(s.transparentRegion); } else { // transformation too complex, can't do the // transparent region optimization. - transparentRegionScreen.clear(); + transparentRegion.clear(); } } else { - transparentRegionScreen = s.transparentRegion; + transparentRegion = s.transparentRegion; } - visibleRegion.subtractSelf(transparentRegionScreen); } // compute the opaque region @@ -1373,9 +1382,11 @@ void SurfaceFlinger::computeVisibleRegions( // Update aboveOpaqueLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); - // Store the visible region is screen space + // Store the visible region in screen space layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); + layer->setVisibleNonTransparentRegion( + visibleRegion.subtract(transparentRegion)); } outOpaqueRegion = aboveOpaqueLayers; |