import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.WeakHashMap;
/**
})
int mLayerType = LAYER_TYPE_NONE;
Paint mLayerPaint;
+ Rect mLocalDirtyRect;
/**
* Simple constructor to use when creating a view from code.
}
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);
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();
canvas.onPostDraw();
mHardwareLayer.end(currentCanvas);
mAttachInfo.mHardwareCanvas = currentCanvas;
+ mLocalDirtyRect.setEmpty();
}
}
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
if (child.mLayerType != LAYER_TYPE_NONE) {
mPrivateFlags |= INVALIDATED;
mPrivateFlags &= ~DRAWING_CACHE_VALID;
- }
+ child.mLocalDirtyRect.union(dirty);
+ }
+
do {
View view = null;
if (parent instanceof View) {
location[CHILD_LEFT_INDEX] = left;
location[CHILD_TOP_INDEX] = top;
+ if (mLayerType != LAYER_TYPE_NONE) {
+ mLocalDirtyRect.union(dirty);
+ }
+
return mParent;
}
} else {
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;
}
#define LOG_TAG "OpenGLRenderer"
+#include <ui/Rect.h>
+
#include "LayerRenderer.h"
#include "Properties.h"
+#include "Rect.h"
namespace android {
namespace uirenderer {
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() {
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();
#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
GL_UNSIGNED_SHORT, layer->meshIndices);
finishDrawTexture();
+
+#if DEBUG_LAYERS_AS_REGIONS
+ drawRegionRects(layer->region);
+#endif
}
}
#else
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.
*/