OSDN Git Service

Update layers based on the dirty region.
authorRomain Guy <romainguy@google.com>
Wed, 2 Feb 2011 06:59:58 +0000 (22:59 -0800)
committerRomain Guy <romainguy@google.com>
Wed, 2 Feb 2011 07:01:43 +0000 (23:01 -0800)
Bug #3413433

This helps Launcher when a widget updates during a scroll, or when interacting
with widgets on the workspace if layers are still turned on.

Change-Id: Ic7a42eb34f74f4ae988039754f815e2efd1d1e4f

core/java/android/view/View.java
core/java/android/view/ViewGroup.java
libs/hwui/LayerRenderer.cpp
libs/hwui/OpenGLRenderer.cpp
libs/hwui/OpenGLRenderer.h

index d3913dc..393412f 100644 (file)
@@ -73,7 +73,6 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.WeakHashMap;
 
 /**
@@ -2375,6 +2374,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     })
     int mLayerType = LAYER_TYPE_NONE;
     Paint mLayerPaint;
+    Rect mLocalDirtyRect;
 
     /**
      * Simple constructor to use when creating a view from code.
@@ -8173,7 +8173,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
         }
 
         mLayerType = layerType;
-        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : (paint == null ? new Paint() : paint);
+        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
+        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
+        mLocalDirtyRect = layerDisabled ? null : new Rect();
 
         invalidateParentCaches();
         invalidate(true);
@@ -8228,8 +8230,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             mAttachInfo.mHardwareCanvas = canvas;
             try {
                 canvas.setViewport(width, height);
-                // TODO: We should pass the dirty rect
-                canvas.onPreDraw(null);
+                canvas.onPreDraw(mLocalDirtyRect);
 
                 final int restoreCount = canvas.save();
 
@@ -8251,6 +8252,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 canvas.onPostDraw();
                 mHardwareLayer.end(currentCanvas);
                 mAttachInfo.mHardwareCanvas = currentCanvas;
+                mLocalDirtyRect.setEmpty();
             }
         }
 
index edfef76..5d5a09a 100644 (file)
@@ -3487,16 +3487,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 if (child.mLayerType != LAYER_TYPE_NONE) {
                     mPrivateFlags |= INVALIDATED;
                     mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                    child.mLocalDirtyRect.setEmpty();
                 }
                 do {
                     View view = null;
                     if (parent instanceof View) {
                         view = (View) parent;
-                        if (view.mLayerType != LAYER_TYPE_NONE &&
-                                view.getParent() instanceof View) {
-                            final View grandParent = (View) view.getParent();
-                            grandParent.mPrivateFlags |= INVALIDATED;
-                            grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                        if (view.mLayerType != LAYER_TYPE_NONE) {
+                            view.mLocalDirtyRect.setEmpty();
+                            if (view.getParent() instanceof View) {
+                                final View grandParent = (View) view.getParent();
+                                grandParent.mPrivateFlags |= INVALIDATED;
+                                grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                            }
                         }
                         if ((view.mPrivateFlags & DIRTY_MASK) != 0) {
                             // already marked dirty - we're done
@@ -3550,7 +3553,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 if (child.mLayerType != LAYER_TYPE_NONE) {
                     mPrivateFlags |= INVALIDATED;
                     mPrivateFlags &= ~DRAWING_CACHE_VALID;
-                }                
+                    child.mLocalDirtyRect.union(dirty);
+                }
+
                 do {
                     View view = null;
                     if (parent instanceof View) {
@@ -3631,6 +3636,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                     location[CHILD_LEFT_INDEX] = left;
                     location[CHILD_TOP_INDEX] = top;
 
+                    if (mLayerType != LAYER_TYPE_NONE) {
+                        mLocalDirtyRect.union(dirty);
+                    }
+                    
                     return mParent;
                 }
             } else {
@@ -3639,8 +3648,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 location[CHILD_LEFT_INDEX] = mLeft;
                 location[CHILD_TOP_INDEX] = mTop;
 
-                dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX],
-                        mBottom - location[CHILD_TOP_INDEX]);
+                dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+
+                if (mLayerType != LAYER_TYPE_NONE) {
+                    mLocalDirtyRect.union(dirty);
+                }
 
                 return mParent;
             }
index 691f649..aebd2b7 100644 (file)
 
 #define LOG_TAG "OpenGLRenderer"
 
+#include <ui/Rect.h>
+
 #include "LayerRenderer.h"
 #include "Properties.h"
+#include "Rect.h"
 
 namespace android {
 namespace uirenderer {
@@ -30,12 +33,24 @@ void LayerRenderer::prepareDirty(float left, float top, float right, float botto
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
 
 #if RENDER_LAYERS_AS_REGIONS
-    mLayer->region.clear();
+    Rect dirty(left, top, right, bottom);
+    if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 &&
+            dirty.right >= mLayer->width && dirty.bottom >= mLayer->height)) {
+        mLayer->region.clear();
+        dirty.set(0.0f, 0.0f, mLayer->width, mLayer->height);
+    } else {
+        android::Rect r(dirty.left, dirty.top, dirty.right, dirty.bottom);
+        mLayer->region.subtractSelf(r);
+    }
 #endif
 
     glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
 
+#if RENDER_LAYERS_AS_REGIONS
+    OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
+#else
     OpenGLRenderer::prepareDirty(0.0f, 0.0f, mLayer->width, mLayer->height, opaque);
+#endif
 }
 
 void LayerRenderer::finish() {
index 2960395..90d6ea1 100644 (file)
@@ -671,25 +671,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
         finishDrawTexture();
 
 #if DEBUG_LAYERS_AS_REGIONS
-        uint32_t colors[] = {
-                0x7fff0000, 0x7f00ff00,
-                0x7f0000ff, 0x7fff00ff,
-        };
-
-        int offset = 0;
-        int32_t top = rects[0].top;
-        int i = 0;
-
-        for (size_t i = 0; i < count; i++) {
-            if (top != rects[i].top) {
-                offset ^= 0x2;
-                top = rects[i].top;
-            }
-
-            Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
-            drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
-                    SkXfermode::kSrcOver_Mode);
-        }
+        drawRegionRects(layer->region);
 #endif
 
         layer->region.clear();
@@ -699,6 +681,32 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
 #endif
 }
 
+void OpenGLRenderer::drawRegionRects(const Region& region) {
+#if DEBUG_LAYERS_AS_REGIONS
+    size_t count;
+    const android::Rect* rects = region.getArray(&count);
+
+    uint32_t colors[] = {
+            0x7fff0000, 0x7f00ff00,
+            0x7f0000ff, 0x7fff00ff,
+    };
+
+    int offset = 0;
+    int32_t top = rects[0].top;
+
+    for (size_t i = 0; i < count; i++) {
+        if (top != rects[i].top) {
+            offset ^= 0x2;
+            top = rects[i].top;
+        }
+
+        Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
+        drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
+                SkXfermode::kSrcOver_Mode);
+    }
+#endif
+}
+
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom, const mat4 transform) {
 #if RENDER_LAYERS_AS_REGIONS
@@ -1626,6 +1634,10 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
                     GL_UNSIGNED_SHORT, layer->meshIndices);
 
             finishDrawTexture();
+
+#if DEBUG_LAYERS_AS_REGIONS
+            drawRegionRects(layer->region);
+#endif
         }
     }
 #else
index 64def03..7bbf034 100644 (file)
@@ -455,6 +455,8 @@ private:
     void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
     void finishDrawTexture();
 
+    void drawRegionRects(const Region& region);
+
     /**
      * Should be invoked every time the glScissor is modified.
      */