diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index d75dddd2b..db4ef87d4 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 0df41ca8c..00c4ffecd 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); @@ -176,6 +177,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 diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b3650bdcf..521e14a25 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -919,9 +919,10 @@ void SurfaceFlinger::rebuildLayerStacks() { const sp& 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;