summaryrefslogtreecommitdiff
path: root/libs/hwui/Snapshot.cpp
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2013-01-15 18:51:42 -0800
committer Romain Guy <romainguy@google.com> 2013-01-17 15:39:31 -0800
commit8ce00301a023eecaeb8891ce906f67b513ebb42a (patch)
tree3b14c80a49cbec537aad39aa4bb266cac41102f7 /libs/hwui/Snapshot.cpp
parent0f8d155363c361199a9d9aa5dcdbc4088990f893 (diff)
Implement clipRect with a transform, clipRegion & clipPath
Bug #7146141 When non-rectangular clipping occurs in a layer the render buffer used as the stencil buffer is not cached. If this happens on a View's hardware layer the render buffer will live for as long as the layer is bound to the view. When a stencil buffer is required because of a call to Canvas.saveLayer() it will be allocated on every frame. A future change will address this problem. If "show GPU overdraw" is enabled, non-rectangular clips are not supported anymore and we fall back to rectangular clips instead. This is a limitation imposed by OpenGL ES that cannot be worked around at this time. This change also improves the Matrix4 implementation to easily detect when a rect remains a rect after transform. Change-Id: I0e69fb901792d38bc0c4ca1bf9fdb02d7db415b9
Diffstat (limited to 'libs/hwui/Snapshot.cpp')
-rw-r--r--libs/hwui/Snapshot.cpp44
1 files changed, 16 insertions, 28 deletions
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index d947299114c1..22c7dde602e0 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -31,7 +31,7 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
transform = &mTransformRoot;
clipRect = &mClipRectRoot;
region = NULL;
- clipRegion = NULL;
+ clipRegion = &mClipRegionRoot;
}
/**
@@ -39,12 +39,10 @@ Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
* the previous snapshot.
*/
Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
- flags(0), previous(s), layer(NULL), fbo(s->fbo),
+ flags(0), previous(s), layer(s->layer), fbo(s->fbo),
invisible(s->invisible), empty(false),
viewport(s->viewport), height(s->height), alpha(s->alpha) {
- clipRegion = NULL;
-
if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
mTransformRoot.load(*s->transform);
transform = &mTransformRoot;
@@ -55,17 +53,13 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
if (saveFlags & SkCanvas::kClip_SaveFlag) {
mClipRectRoot.set(*s->clipRect);
clipRect = &mClipRectRoot;
-#if STENCIL_BUFFER_SIZE
- if (s->clipRegion) {
+ if (!s->clipRegion->isEmpty()) {
mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
- clipRegion = &mClipRegionRoot;
}
-#endif
+ clipRegion = &mClipRegionRoot;
} else {
clipRect = s->clipRect;
-#if STENCIL_BUFFER_SIZE
clipRegion = s->clipRegion;
-#endif
}
if (s->flags & Snapshot::kFlagFboTarget) {
@@ -81,41 +75,38 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
///////////////////////////////////////////////////////////////////////////////
void Snapshot::ensureClipRegion() {
-#if STENCIL_BUFFER_SIZE
- if (!clipRegion) {
- clipRegion = &mClipRegionRoot;
+ if (clipRegion->isEmpty()) {
clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
}
-#endif
}
void Snapshot::copyClipRectFromRegion() {
-#if STENCIL_BUFFER_SIZE
if (!clipRegion->isEmpty()) {
const SkIRect& bounds = clipRegion->getBounds();
clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
if (clipRegion->isRect()) {
clipRegion->setEmpty();
- clipRegion = NULL;
}
} else {
clipRect->setEmpty();
- clipRegion = NULL;
}
-#endif
}
bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
-#if STENCIL_BUFFER_SIZE
SkIRect tmp;
tmp.set(left, top, right, bottom);
clipRegion->op(tmp, op);
copyClipRectFromRegion();
return true;
-#else
- return false;
-#endif
+}
+
+bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) {
+ ensureClipRegion();
+ clipRegion->op(region, op);
+ copyClipRectFromRegion();
+ flags |= Snapshot::kFlagClipSet;
+ return true;
}
bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
@@ -129,7 +120,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
switch (op) {
case SkRegion::kIntersect_Op: {
- if (CC_UNLIKELY(clipRegion)) {
+ if (CC_UNLIKELY(!clipRegion->isEmpty())) {
ensureClipRegion();
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
} else {
@@ -142,7 +133,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
break;
}
case SkRegion::kUnion_Op: {
- if (CC_UNLIKELY(clipRegion)) {
+ if (CC_UNLIKELY(!clipRegion->isEmpty())) {
ensureClipRegion();
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
} else {
@@ -171,12 +162,9 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
void Snapshot::setClip(float left, float top, float right, float bottom) {
clipRect->set(left, top, right, bottom);
-#if STENCIL_BUFFER_SIZE
- if (clipRegion) {
+ if (!clipRegion->isEmpty()) {
clipRegion->setEmpty();
- clipRegion = NULL;
}
-#endif
flags |= Snapshot::kFlagClipSet;
}