am d51eaa64: Merge "Update layers based on the dirty region. Bug #3413433" into honeycomb
* commit 'd51eaa64e3f2d9684b2dd18ebd67734f4e0e7801':
Update layers based on the dirty region. Bug #3413433
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d3913dc..393412f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -73,7 +73,6 @@
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 @@
})
int mLayerType = LAYER_TYPE_NONE;
Paint mLayerPaint;
+ Rect mLocalDirtyRect;
/**
* Simple constructor to use when creating a view from code.
@@ -8173,7 +8173,9 @@
}
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 @@
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 @@
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 edfef769..5d5a09a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3487,16 +3487,19 @@
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 @@
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 @@
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 @@
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 691f649..aebd2b7 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -16,8 +16,11 @@
#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 @@
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 2960395..90d6ea1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -671,25 +671,7 @@
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 @@
#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 @@
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 64def03..7bbf034 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -455,6 +455,8 @@
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.
*/