From 3a3133d876caf60ebff2176ad75c3dcf0259148d Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 1 Feb 2011 22:59:58 -0800 Subject: [PATCH] Update layers based on the dirty region. 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 | 10 ++++--- core/java/android/view/ViewGroup.java | 28 ++++++++++++++------ libs/hwui/LayerRenderer.cpp | 17 +++++++++++- libs/hwui/OpenGLRenderer.cpp | 50 ++++++++++++++++++++++------------- libs/hwui/OpenGLRenderer.h | 2 ++ 5 files changed, 75 insertions(+), 32 deletions(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d3913dcb29cb..393412f0e6a0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -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(); } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index edfef7694a12..5d5a09a484d2 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -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; } diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 691f6497f641..aebd2b7c696d 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -16,8 +16,11 @@ #define LOG_TAG "OpenGLRenderer" +#include + #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() { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 29603955b30a..90d6ea1bc1f0 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -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 diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 64def03d9ede..7bbf034c8497 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -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. */ -- 2.11.0