OSDN Git Service

fix [2511580] Window poop on screen - drop down list left some residual when it resized
authorMathias Agopian <mathias@google.com>
Tue, 16 Mar 2010 23:41:46 +0000 (16:41 -0700)
committerMathias Agopian <mathias@google.com>
Wed, 17 Mar 2010 00:54:27 +0000 (17:54 -0700)
Change-Id: Ib9a3622e7a568ba26717a93b5bfa4a191651f4d0

libs/surfaceflinger/LayerBase.cpp
libs/surfaceflinger/LayerBase.h
libs/surfaceflinger/SurfaceFlinger.cpp

index 140f10c..efbc77a 100644 (file)
@@ -214,7 +214,6 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
     if ((front.w != temp.w) || (front.h != temp.h)) {
         // invalidate and recompute the visible regions if needed
         flags |= Layer::eVisibleRegion;
-        this->contentDirty = true;
     }
 
     if (temp.sequence != front.sequence) {
index a6e5644..62ec839 100644 (file)
@@ -157,11 +157,11 @@ public:
     
     /**
      * setCoveredRegion - called when the covered region changes. The covered
-     * region correspond to any area of the surface that is covered 
+     * region corresponds to any area of the surface that is covered
      * (transparently or not) by another surface.
      */
     virtual void setCoveredRegion(const Region& coveredRegion);
-    
+
     /**
      * validateVisibility - cache a bunch of things
      */
index 26ee285..0722fda 100644 (file)
@@ -674,6 +674,8 @@ void SurfaceFlinger::computeVisibleRegions(
 {
     const GraphicPlane& plane(graphicPlane(0));
     const Transform& planeTransform(plane.transform());
+    const DisplayHardware& hw(plane.displayHardware());
+    const Region screenRegion(hw.bounds());
 
     Region aboveOpaqueLayers;
     Region aboveCoveredLayers;
@@ -689,31 +691,56 @@ void SurfaceFlinger::computeVisibleRegions(
         // start with the whole surface at its current location
         const Layer::State& s(layer->drawingState());
 
-        // handle hidden surfaces by setting the visible region to empty
+        /*
+         * opaqueRegion: area of a surface that is fully opaque.
+         */
         Region opaqueRegion;
+
+        /*
+         * visibleRegion: area of a surface that is visible on screen
+         * and not fully transparent. This is essentially the layer's
+         * footprint minus the opaque regions above it.
+         * Areas covered by a translucent surface are considered visible.
+         */
         Region visibleRegion;
+
+        /*
+         * coveredRegion: area of a surface that is covered by all
+         * visible regions above it (which includes the translucent areas).
+         */
         Region coveredRegion;
+
+
+        // handle hidden surfaces by setting the visible region to empty
         if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
             const bool translucent = layer->needsBlending();
             const Rect bounds(layer->visibleBounds());
             visibleRegion.set(bounds);
-            coveredRegion = visibleRegion;
-
-            // Remove the transparent area from the visible region
-            if (translucent) {
-                visibleRegion.subtractSelf(layer->transparentRegionScreen);
-            }
+            visibleRegion.andSelf(screenRegion);
+            if (!visibleRegion.isEmpty()) {
+                // Remove the transparent area from the visible region
+                if (translucent) {
+                    visibleRegion.subtractSelf(layer->transparentRegionScreen);
+                }
 
-            // compute the opaque region
-            if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
-                // the opaque region is the visible region
-                opaqueRegion = visibleRegion;
+                // compute the opaque region
+                const int32_t layerOrientation = layer->getOrientation();
+                if (s.alpha==255 && !translucent &&
+                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
+                    // the opaque region is the layer's footprint
+                    opaqueRegion = visibleRegion;
+                }
             }
         }
 
+        // Clip the covered region to the visible region
+        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
+
+        // Update aboveCoveredLayers for next (lower) layer
+        aboveCoveredLayers.orSelf(visibleRegion);
+
         // subtract the opaque region covered by the layers above us
         visibleRegion.subtractSelf(aboveOpaqueLayers);
-        coveredRegion.andSelf(aboveCoveredLayers);
 
         // compute this layer's dirty region
         if (layer->contentDirty) {
@@ -724,19 +751,30 @@ void SurfaceFlinger::computeVisibleRegions(
             layer->contentDirty = false;
         } else {
             /* compute the exposed region:
-             *    exposed = what's VISIBLE and NOT COVERED now 
-             *    but was COVERED before
+             *   the exposed region consists of two components:
+             *   1) what's VISIBLE now and was COVERED before
+             *   2) what's EXPOSED now less what was EXPOSED before
+             *
+             * note that (1) is conservative, we start with the whole
+             * visible region but only keep what used to be covered by
+             * something -- which mean it may have been exposed.
+             *
+             * (2) handles areas that were not covered by anything but got
+             * exposed because of a resize.
              */
-            dirty = (visibleRegion - coveredRegion) & layer->coveredRegionScreen;
+            const Region newExposed = visibleRegion - coveredRegion;
+            const Region oldVisibleRegion = layer->visibleRegionScreen;
+            const Region oldCoveredRegion = layer->coveredRegionScreen;
+            const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
+            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
         }
         dirty.subtractSelf(aboveOpaqueLayers);
 
         // accumulate to the screen dirty region
         dirtyRegion.orSelf(dirty);
 
-        // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
+        // Update aboveOpaqueLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
-        aboveCoveredLayers.orSelf(visibleRegion);
         
         // Store the visible region is screen space
         layer->setVisibleRegion(visibleRegion);