Merge "Recompute visible regions more vigorously" into jb-mr1-dev
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 @@
     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 @@
             // regions below are in window-manager space
             Region      visibleRegion;
             Region      coveredRegion;
+            Region      visibleNonTransparentRegion;
             int32_t     sequence;
             
             struct Geometry {
@@ -110,7 +111,7 @@
             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 @@
     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 @@
                     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 @@
          */
         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 @@
             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 @@
         // 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;