OSDN Git Service

get rid of global regions that should be tracked per display
authorMathias Agopian <mathias@google.com>
Tue, 31 Jul 2012 19:38:26 +0000 (12:38 -0700)
committerMathias Agopian <mathias@google.com>
Fri, 3 Aug 2012 05:24:12 +0000 (22:24 -0700)
Change-Id: I3b871860cc29f1b2fdcc22b0c577a6eae65d9296

services/surfaceflinger/DisplayHardware.cpp
services/surfaceflinger/DisplayHardware.h
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h

index 4b5d8ab..7e4aa83 100644 (file)
@@ -108,7 +108,8 @@ DisplayHardware::DisplayHardware(
       mDisplayId(display),
       mNativeWindow(surface),
       mFlags(0),
-      mSecureLayerVisible(false)
+      mSecureLayerVisible(false),
+      mLayerStack(0)
 {
     init(config);
 }
index 98579b4..80d20cb 100644 (file)
@@ -45,10 +45,16 @@ class SurfaceTextureClient;
 class DisplayHardware : public DisplayHardwareBase
 {
 public:
+    // region in layer-stack space
+    mutable Region dirtyRegion;
+    // region in screen space
+    mutable Region swapRegion;
+    // region in screen space
+    Region undefinedRegion;
 
     enum {
-        PARTIAL_UPDATES             = 0x00020000,   // video driver feature
-        SWAP_RECTANGLE              = 0x00080000,
+        PARTIAL_UPDATES = 0x00020000, // video driver feature
+        SWAP_RECTANGLE  = 0x00080000,
     };
 
     DisplayHardware(
@@ -86,6 +92,8 @@ public:
     status_t                setOrientation(int orientation);
     int                     getOrientation() const { return mOrientation; }
     const Transform&        getTransform() const { return mGlobalTransform; }
+    uint32_t                getLayerStack() const { return mLayerStack; }
+
 
     uint32_t getPageFlipCount() const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
@@ -144,6 +152,9 @@ private:
     Transform mGlobalTransform;
     int mOrientation;
 
+    uint32_t mLayerStack;
+
+
     /*
      *  protected by mLock
      */
index 6cf1128..c344870 100644 (file)
@@ -132,7 +132,6 @@ void SurfaceFlinger::onFirstRef()
 
 SurfaceFlinger::~SurfaceFlinger()
 {
-    glDeleteTextures(1, &mWormholeTexName);
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(display);
@@ -308,18 +307,6 @@ void SurfaceFlinger::initializeGL(EGLDisplay display, EGLSurface surface) {
         }
     } pack565;
 
-    const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
-    const uint16_t g1 = pack565(0x17,0x2f,0x17);
-    const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 };
-    glGenTextures(1, &mWormholeTexName);
-    glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
-            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, wormholeTexData);
-
     const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
     glGenTextures(1, &mProtectedTexName);
     glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
@@ -579,89 +566,91 @@ void SurfaceFlinger::handleMessageTransaction() {
     const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
     uint32_t transactionFlags = peekTransactionFlags(mask);
     if (transactionFlags) {
-        Region dirtyRegion;
-        dirtyRegion = handleTransaction(transactionFlags);
-        // XXX: dirtyRegion should be per screen
-        mDirtyRegion |= dirtyRegion;
+        handleTransaction(transactionFlags);
     }
 }
 
 void SurfaceFlinger::handleMessageInvalidate() {
-    Region dirtyRegion;
-    dirtyRegion = handlePageFlip();
-    // XXX: dirtyRegion should be per screen
-    mDirtyRegion |= dirtyRegion;
+    handlePageFlip();
 }
 
 void SurfaceFlinger::handleMessageRefresh() {
     handleRefresh();
 
     if (mVisibleRegionsDirty) {
-        Region opaqueRegion;
-        Region dirtyRegion;
-        const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
-        computeVisibleRegions(currentLayers, dirtyRegion, opaqueRegion);
-        mDirtyRegion.orSelf(dirtyRegion);
+        mVisibleRegionsDirty = false;
+        invalidateHwcGeometry();
 
         /*
          *  rebuild the visible layer list per screen
          */
 
+        const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
         // TODO: iterate through all displays
-        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
+        {
+            DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
 
-        Vector< sp<LayerBase> > layersSortedByZ;
-        const size_t count = currentLayers.size();
-        for (size_t i=0 ; i<count ; i++) {
-            if (!currentLayers[i]->visibleRegion.isEmpty()) {
-                // TODO: also check that this layer is associated to this display
-                layersSortedByZ.add(currentLayers[i]);
+            Region opaqueRegion;
+            Region dirtyRegion;
+            computeVisibleRegions(currentLayers,
+                    hw.getLayerStack(), dirtyRegion, opaqueRegion);
+            hw.dirtyRegion.orSelf(dirtyRegion);
+
+            Vector< sp<LayerBase> > layersSortedByZ;
+            const size_t count = currentLayers.size();
+            for (size_t i=0 ; i<count ; i++) {
+                const Layer::State& s(currentLayers[i]->drawingState());
+                if (s.layerStack == hw.getLayerStack()) {
+                    if (!currentLayers[i]->visibleRegion.isEmpty()) {
+                        layersSortedByZ.add(currentLayers[i]);
+                    }
+                }
             }
+            hw.setVisibleLayersSortedByZ(layersSortedByZ);
+            hw.undefinedRegion.set(hw.getBounds());
+            hw.undefinedRegion.subtractSelf(hw.getTransform().transform(opaqueRegion));
         }
-        hw.setVisibleLayersSortedByZ(layersSortedByZ);
-
-
-        // FIXME: mWormholeRegion needs to be calculated per screen
-        //const DisplayHardware& hw(getDefaultDisplayHardware()); // XXX: we can't keep that here
-        mWormholeRegion = Region(hw.getBounds()).subtract(
-                hw.getTransform().transform(opaqueRegion) );
-        mVisibleRegionsDirty = false;
-        invalidateHwcGeometry();
     }
 
-
-    // XXX: dirtyRegion should be per screen, we should check all of them
-    if (mDirtyRegion.isEmpty()) {
-        return;
-    }
+    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
 
     // TODO: iterate through all displays
-    const DisplayHardware& hw(getDisplayHardware(0));
-
-    // XXX: dirtyRegion should be per screen
-    // transform the dirty region into this screen's coordinate space
-    const Transform& planeTransform(hw.getTransform());
-    mDirtyRegion = planeTransform.transform(mDirtyRegion);
-    mDirtyRegion.orSelf(getAndClearInvalidateRegion());
-    mDirtyRegion.andSelf(hw.bounds());
+    for (int dpy=0 ; dpy<1 ; dpy++) {
+        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
+        if (hw.dirtyRegion.isEmpty()) {
+            continue;
+        }
 
+        // transform the dirty region into this screen's coordinate space
+        const Transform& planeTransform(hw.getTransform());
+        Region dirtyRegion;
+        if (repaintEverything) {
+            dirtyRegion = planeTransform.transform(hw.dirtyRegion);
+            dirtyRegion.andSelf(hw.bounds());
+        } else {
+            dirtyRegion.set(hw.bounds());
+        }
+        hw.dirtyRegion.clear();
 
-    if (CC_UNLIKELY(mHwWorkListDirty)) {
         // build the h/w work list
-        handleWorkList(hw);
-    }
+        if (CC_UNLIKELY(mHwWorkListDirty)) {
+            handleWorkList(hw);
+        }
 
-    if (CC_LIKELY(hw.canDraw())) {
-        // repaint the framebuffer (if needed)
-        handleRepaint(hw);
-        // inform the h/w that we're done compositing
-        hw.compositionComplete();
-        postFramebuffer();
-    } else {
-        // pretend we did the post
-        hw.compositionComplete();
+        if (CC_LIKELY(hw.canDraw())) {
+            // repaint the framebuffer (if needed)
+            handleRepaint(hw, dirtyRegion);
+            // inform the h/w that we're done compositing
+            hw.compositionComplete();
+            postFramebuffer();
+        } else {
+            // pretend we did the post
+            hw.compositionComplete();
+        }
     }
 
+
+#if 0
     // render to the external display if we have one
     EGLSurface externalDisplaySurface = getExternalDisplaySurface();
     if (externalDisplaySurface != EGL_NO_SURFACE) {
@@ -699,6 +688,7 @@ void SurfaceFlinger::handleMessageRefresh() {
 
         ALOGE_IF(!success, "eglMakeCurrent -> internal failed");
     }
+#endif
 
 }
 
@@ -729,7 +719,8 @@ void SurfaceFlinger::postFramebuffer()
         }
     }
 
-    hw.flip(mSwapRegion);
+    hw.flip(hw.swapRegion);
+    hw.swapRegion.clear();
 
     if (hwc.initCheck() == NO_ERROR) {
         hwc.commit(mEGLDisplay, hw.getEGLSurface());
@@ -747,15 +738,12 @@ void SurfaceFlinger::postFramebuffer()
 
     mLastSwapBufferTime = systemTime() - now;
     mDebugInSwapBuffers = 0;
-    mSwapRegion.clear();
 }
 
-Region SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
+void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
     ATRACE_CALL();
 
-    Region dirtyRegion;
-
     Mutex::Autolock _l(mStateLock);
     const nsecs_t now = systemTime();
     mDebugInTransaction = now;
@@ -768,19 +756,16 @@ Region SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 
     const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
     transactionFlags = getTransactionFlags(mask);
-    dirtyRegion = handleTransactionLocked(transactionFlags);
+    handleTransactionLocked(transactionFlags);
 
     mLastTransactionTime = systemTime() - now;
     mDebugInTransaction = 0;
     invalidateHwcGeometry();
     // here the transaction has been committed
-
-    return dirtyRegion;
 }
 
-Region SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
 {
-    Region dirtyRegion;
     const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
 
@@ -811,13 +796,12 @@ Region SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
             // the orientation has changed, recompute all visible regions
             // and invalidate everything.
 
-            const int dpy = 0; // TODO: should be a parameter
+            const int dpy = 0; // FIXME: should be a parameter
             DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));
             hw.setOrientation(mCurrentState.orientation);
+            hw.dirtyRegion.set(hw.bounds());
 
-            // FIXME: mVisibleRegionsDirty & mDirtyRegion should this be per DisplayHardware?
             mVisibleRegionsDirty = true;
-            mDirtyRegion.set(hw.bounds());
         }
 
         if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
@@ -834,21 +818,21 @@ Region SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
             const size_t count = previousLayers.size();
             for (size_t i=0 ; i<count ; i++) {
                 const sp<LayerBase>& layer(previousLayers[i]);
-                if (currentLayers.indexOf( layer ) < 0) {
+                if (currentLayers.indexOf(layer) < 0) {
                     // this layer is not visible anymore
-                    // TODO: we could traverse the tree from front to back and compute the actual visible region
+                    // TODO: we could traverse the tree from front to back and
+                    //       compute the actual visible region
                     // TODO: we could cache the transformed region
                     Layer::State front(layer->drawingState());
                     Region visibleReg = front.transform.transform(
                             Region(Rect(front.active.w, front.active.h)));
-                    dirtyRegion.orSelf(visibleReg);
+                    invalidateLayerStack(front.layerStack, visibleReg);
                 }
             }
         }
     }
 
     commitTransaction();
-    return dirtyRegion;
 }
 
 void SurfaceFlinger::commitTransaction()
@@ -867,7 +851,8 @@ void SurfaceFlinger::commitTransaction()
 }
 
 void SurfaceFlinger::computeVisibleRegions(
-    const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
+        const LayerVector& currentLayers, uint32_t layerStack,
+        Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
 
@@ -875,7 +860,7 @@ void SurfaceFlinger::computeVisibleRegions(
     Region aboveCoveredLayers;
     Region dirty;
 
-    dirtyRegion.clear();
+    outDirtyRegion.clear();
 
     size_t i = currentLayers.size();
     while (i--) {
@@ -884,6 +869,10 @@ void SurfaceFlinger::computeVisibleRegions(
         // start with the whole surface at its current location
         const Layer::State& s(layer->drawingState());
 
+        // only consider the layers on the given later stack
+        if (s.layerStack != layerStack)
+            continue;
+
         /*
          * opaqueRegion: area of a surface that is fully opaque.
          */
@@ -977,7 +966,7 @@ void SurfaceFlinger::computeVisibleRegions(
         dirty.subtractSelf(aboveOpaqueLayers);
 
         // accumulate to the screen dirty region
-        dirtyRegion.orSelf(dirty);
+        outDirtyRegion.orSelf(dirty);
 
         // Update aboveOpaqueLayers for next (lower) layer
         aboveOpaqueLayers.orSelf(opaqueRegion);
@@ -987,10 +976,18 @@ void SurfaceFlinger::computeVisibleRegions(
         layer->setCoveredRegion(coveredRegion);
     }
 
-    opaqueRegion = aboveOpaqueLayers;
+    outOpaqueRegion = aboveOpaqueLayers;
 }
 
-Region SurfaceFlinger::handlePageFlip()
+void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
+        const Region& dirty) {
+    // FIXME: update the dirty region of all displays
+    // presenting this layer's layer stack.
+    DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
+    hw.dirtyRegion.orSelf(dirty);
+}
+
+void SurfaceFlinger::handlePageFlip()
 {
     ATRACE_CALL();
     Region dirtyRegion;
@@ -1002,12 +999,12 @@ Region SurfaceFlinger::handlePageFlip()
     sp<LayerBase> const* layers = currentLayers.array();
     for (size_t i=0 ; i<count ; i++) {
         const sp<LayerBase>& layer(layers[i]);
-        dirtyRegion.orSelf( layer->latchBuffer(visibleRegions) );
+        const Region dirty(layer->latchBuffer(visibleRegions));
+        Layer::State s(layer->drawingState());
+        invalidateLayerStack(s.layerStack, dirty);
     }
 
     mVisibleRegionsDirty |= visibleRegions;
-
-    return dirtyRegion;
 }
 
 void SurfaceFlinger::invalidateHwcGeometry()
@@ -1052,15 +1049,18 @@ void SurfaceFlinger::handleWorkList(const DisplayHardware& hw)
     }
 }
 
-void SurfaceFlinger::handleRepaint(const DisplayHardware& hw)
+void SurfaceFlinger::handleRepaint(const DisplayHardware& hw,
+        const Region& inDirtyRegion)
 {
     ATRACE_CALL();
 
+    Region dirtyRegion(inDirtyRegion);
+
     // compute the invalid region
-    mSwapRegion.orSelf(mDirtyRegion);
+    hw.swapRegion.orSelf(dirtyRegion);
 
     if (CC_UNLIKELY(mDebugRegion)) {
-        debugFlashRegions(hw);
+        debugFlashRegions(hw, dirtyRegion);
     }
 
     // set the frame buffer
@@ -1072,27 +1072,26 @@ void SurfaceFlinger::handleRepaint(const DisplayHardware& hw)
         // we can redraw only what's dirty, but since SWAP_RECTANGLE only
         // takes a rectangle, we must make sure to update that whole
         // rectangle in that case
-        mDirtyRegion.set(mSwapRegion.bounds());
+        dirtyRegion.set(hw.swapRegion.bounds());
     } else {
         if (flags & DisplayHardware::PARTIAL_UPDATES) {
             // We need to redraw the rectangle that will be updated
             // (pushed to the framebuffer).
             // This is needed because PARTIAL_UPDATES only takes one
             // rectangle instead of a region (see DisplayHardware::flip())
-            mDirtyRegion.set(mSwapRegion.bounds());
+            dirtyRegion.set(hw.swapRegion.bounds());
         } else {
             // we need to redraw everything (the whole screen)
-            mDirtyRegion.set(hw.bounds());
-            mSwapRegion = mDirtyRegion;
+            dirtyRegion.set(hw.bounds());
+            hw.swapRegion = dirtyRegion;
         }
     }
 
     setupHardwareComposer(hw);
-    composeSurfaces(hw, mDirtyRegion);
+    composeSurfaces(hw, dirtyRegion);
 
     // update the swap region and clear the dirty region
-    mSwapRegion.orSelf(mDirtyRegion);
-    mDirtyRegion.clear();
+    hw.swapRegion.orSelf(dirtyRegion);
 }
 
 void SurfaceFlinger::setupHardwareComposer(const DisplayHardware& hw)
@@ -1147,10 +1146,11 @@ void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& di
             glClearColor(0, 0, 0, 0);
             glClear(GL_COLOR_BUFFER_BIT);
         } else {
+            const Region region(hw.undefinedRegion.intersect(dirty));
             // screen is already cleared here
-            if (!mWormholeRegion.isEmpty()) {
+            if (!region.isEmpty()) {
                 // can happen with SurfaceView
-                drawWormhole();
+                drawWormhole(region);
             }
         }
 
@@ -1185,17 +1185,18 @@ void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& di
     }
 }
 
-void SurfaceFlinger::debugFlashRegions(const DisplayHardware& hw)
+void SurfaceFlinger::debugFlashRegions(const DisplayHardware& hw,
+        const Region& dirtyRegion)
 {
     const uint32_t flags = hw.getFlags();
     const int32_t height = hw.getHeight();
-    if (mSwapRegion.isEmpty()) {
+    if (hw.swapRegion.isEmpty()) {
         return;
     }
 
     if (!(flags & DisplayHardware::SWAP_RECTANGLE)) {
         const Region repaint((flags & DisplayHardware::PARTIAL_UPDATES) ?
-                mDirtyRegion.bounds() : hw.bounds());
+                dirtyRegion.bounds() : hw.bounds());
         composeSurfaces(hw, repaint);
     }
 
@@ -1211,8 +1212,8 @@ void SurfaceFlinger::debugFlashRegions(const DisplayHardware& hw)
         glColor4f(1, 1, 0, 1);
     }
 
-    Region::const_iterator it = mDirtyRegion.begin();
-    Region::const_iterator const end = mDirtyRegion.end();
+    Region::const_iterator it = dirtyRegion.begin();
+    Region::const_iterator const end = dirtyRegion.end();
     while (it != end) {
         const Rect& r = *it++;
         GLfloat vertices[][2] = {
@@ -1225,18 +1226,14 @@ void SurfaceFlinger::debugFlashRegions(const DisplayHardware& hw)
         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
 
-    hw.flip(mSwapRegion);
+    hw.flip(hw.swapRegion);
 
     if (mDebugRegion > 1)
         usleep(mDebugRegion * 1000);
 }
 
-void SurfaceFlinger::drawWormhole() const
+void SurfaceFlinger::drawWormhole(const Region& region) const
 {
-    const Region region(mWormholeRegion.intersect(mDirtyRegion));
-    if (region.isEmpty())
-        return;
-
     glDisable(GL_TEXTURE_EXTERNAL_OES);
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_BLEND);
@@ -1814,7 +1811,7 @@ void SurfaceFlinger::dumpAllLocked(
     snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
     result.append(buffer);
 
-    mWormholeRegion.dump(result, "WormholeRegion");
+    hw.undefinedRegion.dump(result, "undefinedRegion");
     snprintf(buffer, SIZE,
             "  orientation=%d, canDraw=%d\n",
             mCurrentState.orientation, hw.canDraw());
@@ -1975,24 +1972,10 @@ status_t SurfaceFlinger::onTransact(
 }
 
 void SurfaceFlinger::repaintEverything() {
-    const DisplayHardware& hw(getDefaultDisplayHardware()); // FIXME: this cannot be bound the default display
-    const Rect bounds(hw.getBounds());
-    setInvalidateRegion(Region(bounds));
+    android_atomic_or(1, &mRepaintEverything);
     signalTransaction();
 }
 
-void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
-    Mutex::Autolock _l(mInvalidateLock);
-    mInvalidateRegion = reg;
-}
-
-Region SurfaceFlinger::getAndClearInvalidateRegion() {
-    Mutex::Autolock _l(mInvalidateLock);
-    Region reg(mInvalidateRegion);
-    mInvalidateRegion.clear();
-    return reg;
-}
-
 // ---------------------------------------------------------------------------
 
 status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
@@ -2503,7 +2486,7 @@ status_t SurfaceFlinger::turnElectronBeamOnImplLocked(int32_t mode)
     }
 
     // make sure to redraw the whole screen when the animation is done
-    mDirtyRegion.set(hw.bounds());
+    hw.dirtyRegion.set(hw.bounds());
     signalTransaction();
 
     return NO_ERROR;
index a3d8538..d46ceca 100644 (file)
@@ -228,21 +228,17 @@ private:
     void handleMessageInvalidate();
     void handleMessageRefresh();
 
-    Region handleTransaction(uint32_t transactionFlags);
-    Region handleTransactionLocked(uint32_t transactionFlags);
+    void handleTransaction(uint32_t transactionFlags);
+    void handleTransactionLocked(uint32_t transactionFlags);
 
     /* handlePageFilp: this is were we latch a new buffer
      * if available and compute the dirty region.
-     * The return value is the dirty region expressed in the
-     * window manager's coordinate space (or the layer's state
-     * space, which is the same thing), in particular the dirty
-     * region is independent from a specific display's orientation.
      */
-    Region handlePageFlip();
+    void handlePageFlip();
 
     void handleRefresh();
     void handleWorkList(const DisplayHardware& hw);
-    void handleRepaint(const DisplayHardware& hw);
+    void handleRepaint(const DisplayHardware& hw, const Region& dirtyRegion);
 
     /* ------------------------------------------------------------------------
      * Transactions
@@ -319,12 +315,16 @@ private:
     uint32_t getMaxViewportDims() const;
 
     /* ------------------------------------------------------------------------
-     * Display management
+     * Display and layer stack management
      */
     const DisplayHardware& getDisplayHardware(DisplayID dpy) const {
         return *mDisplayHardwares[dpy];
     }
 
+    // mark a region of a layer stack dirty. this updates the dirty
+    // region of all screens presenting this layer stack.
+    void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
+
     /* ------------------------------------------------------------------------
      * H/W composer
      */
@@ -336,13 +336,12 @@ private:
      */
     void invalidateHwcGeometry();
     void computeVisibleRegions(const LayerVector& currentLayers,
-        Region& dirtyRegion, Region& wormholeRegion);
+            uint32_t layerStack,
+            Region& dirtyRegion, Region& opaqueRegion);
     void postFramebuffer();
     void setupHardwareComposer(const DisplayHardware& hw);
     void composeSurfaces(const DisplayHardware& hw, const Region& dirty);
-    void setInvalidateRegion(const Region& reg);
-    Region getAndClearInvalidateRegion();
-    void drawWormhole() const;
+    void drawWormhole(const Region& region) const;
     GLuint getProtectedTexName() const {
         return mProtectedTexName;
     }
@@ -350,7 +349,7 @@ private:
     /* ------------------------------------------------------------------------
      * Debugging & dumpsys
      */
-    void debugFlashRegions(const DisplayHardware& hw);
+    void debugFlashRegions(const DisplayHardware& hw, const Region& dirtyReg);
     void listLayersLocked(const Vector<String16>& args, size_t& index,
         String8& result, char* buffer, size_t SIZE) const;
     void dumpStatsLocked(const Vector<String16>& args, size_t& index,
@@ -377,12 +376,10 @@ private:
     bool mLayersRemoved;
 
     // access must be protected by mInvalidateLock
-    mutable Mutex mInvalidateLock;
-    Region mInvalidateRegion;
+    volatile int32_t mRepaintEverything;
 
     // constant members (no synchronization needed for access)
     HWComposer* mHwc;
-    GLuint mWormholeTexName;
     GLuint mProtectedTexName;
     nsecs_t mBootTime;
     sp<EventThread> mEventThread;
@@ -395,10 +392,6 @@ private:
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState;
-    Region mDirtyRegion;
-    Region mDirtyRegionRemovedLayer;
-    Region mSwapRegion;
-    Region mWormholeRegion;
     bool mVisibleRegionsDirty;
     bool mHwWorkListDirty;
     int32_t mElectronBeamAnimationMode;