summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2013-04-19 14:54:34 -0700
committerChet Haase <chet@google.com>2013-04-19 15:36:37 -0700
commitdd671599bed9d3ca28e2c744e8c224e1e15bc914 (patch)
treeaef0efadc853003d866f3d3d14621261f05d214c /libs
parent9b3ebb124eba3d9f80ae299e0cbcfcd9c0a8653d (diff)
downloadframeworks_base-dd671599bed9d3ca28e2c744e8c224e1e15bc914.zip
frameworks_base-dd671599bed9d3ca28e2c744e8c224e1e15bc914.tar.gz
frameworks_base-dd671599bed9d3ca28e2c744e8c224e1e15bc914.tar.bz2
Fix quickReject logic to account for setClipChildren() setting
The rendering code optimizes by rejecting drawing operations that lie outside of the bounds of their views. This works in most situations, but breaks down when containers have called setClipChildren(false), because we reject drawing that is outside of that container, but which should be drawn anyway. Fix is to pass in the value of that flag to the DisplayList drawing routines which take that flag into account when deciding whether to quickReject any particular operation. Issue #8659277 animation clipping Change-Id: Ief568e4db01b533a97b3c5ea5ad777c03c0eea71
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/DisplayList.cpp33
-rw-r--r--libs/hwui/DisplayList.h6
-rw-r--r--libs/hwui/DisplayListOp.h42
3 files changed, 46 insertions, 35 deletions
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 26abec2..b7d3d6f 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -231,7 +231,7 @@ void DisplayList::init() {
mTop = 0;
mRight = 0;
mBottom = 0;
- mClipChildren = true;
+ mClipToBounds = true;
mAlpha = 1;
mHasOverlappingRendering = true;
mTranslationX = 0;
@@ -358,7 +358,7 @@ void DisplayList::outputViewProperties(const int level) {
ALOGD("%*sScaleAlpha %.2f", level * 2, "", mAlpha);
} else {
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (mClipChildren) {
+ if (mClipToBounds) {
flags |= SkCanvas::kClipToLayer_SaveFlag;
}
ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
@@ -366,7 +366,7 @@ void DisplayList::outputViewProperties(const int level) {
(int)(mAlpha * 255), flags);
}
}
- if (mClipChildren && !mCaching) {
+ if (mClipToBounds && !mCaching) {
ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f,
(float) mRight - mLeft, (float) mBottom - mTop);
}
@@ -411,16 +411,17 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler,
// have to pass it into this call. In fact, this information might be in the
// location/size info that we store with the new native transform data.
int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (mClipChildren) {
+ if (mClipToBounds) {
saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
}
handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop,
- mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT);
+ mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT,
+ mClipToBounds);
}
}
- if (mClipChildren && !mCaching) {
+ if (mClipToBounds && !mCaching) {
handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op),
- PROPERTY_SAVECOUNT);
+ PROPERTY_SAVECOUNT, mClipToBounds);
}
}
@@ -428,8 +429,8 @@ class DeferOperationHandler {
public:
DeferOperationHandler(DeferStateStruct& deferStruct, int level)
: mDeferStruct(deferStruct), mLevel(level) {}
- inline void operator()(DisplayListOp* operation, int saveCount) {
- operation->defer(mDeferStruct, saveCount, mLevel);
+ inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
+ operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds);
}
private:
DeferStateStruct& mDeferStruct;
@@ -445,11 +446,11 @@ class ReplayOperationHandler {
public:
ReplayOperationHandler(ReplayStateStruct& replayStruct, int level)
: mReplayStruct(replayStruct), mLevel(level) {}
- inline void operator()(DisplayListOp* operation, int saveCount) {
+ inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
mReplayStruct.mRenderer.eventMark(operation->name());
#endif
- operation->replay(mReplayStruct, saveCount, mLevel);
+ operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
}
private:
ReplayStateStruct& mReplayStruct;
@@ -492,16 +493,16 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)
int restoreTo = renderer.getSaveCount();
handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
- PROPERTY_SAVECOUNT);
+ PROPERTY_SAVECOUNT, mClipToBounds);
DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
setViewProperties<T>(renderer, handler, level + 1);
- if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
+ if (mClipToBounds && renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
- handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
+ handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds);
return;
}
@@ -510,12 +511,12 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
DisplayListOp *op = mDisplayListData->displayListOps[i];
- handler(op, saveCount);
+ handler(op, saveCount, mClipToBounds);
logBuffer.writeCommand(level, op->name());
}
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
- handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
+ handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT, mClipToBounds);
renderer.restoreToCount(restoreTo);
renderer.setOverrideLayerAlpha(1.0f);
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 84f20ab..5f84329 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -137,8 +137,8 @@ public:
return mName.string();
}
- void setClipChildren(bool clipChildren) {
- mClipChildren = clipChildren;
+ void setClipToBounds(bool clipToBounds) {
+ mClipToBounds = clipToBounds;
}
void setStaticMatrix(SkMatrix* matrix) {
@@ -498,7 +498,7 @@ private:
String8 mName;
// View properties
- bool mClipChildren;
+ bool mClipToBounds;
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index c277c24..a0290e3 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -78,9 +78,11 @@ public:
kOpLogFlag_JSON = 0x2 // TODO: add?
};
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) = 0;
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) = 0;
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) = 0;
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
+ bool useQuickReject) = 0;
virtual void output(int level, uint32_t logFlags = 0) = 0;
@@ -104,7 +106,8 @@ public:
virtual ~StateOp() {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
// default behavior only affects immediate, deferrable state, issue directly to renderer
applyState(deferStruct.mRenderer, saveCount);
}
@@ -113,7 +116,8 @@ public:
* State operations are applied directly to the renderer, but can cause the deferred drawing op
* list to flush
*/
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
+ bool useQuickReject) {
applyState(replayStruct.mRenderer, saveCount);
}
@@ -126,9 +130,9 @@ public:
DrawOp(SkPaint* paint)
: mPaint(paint), mQuickRejected(false) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
- if (mQuickRejected &&
- CC_LIKELY(deferStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
+ if (mQuickRejected && CC_LIKELY(useQuickReject)) {
return;
}
@@ -140,9 +144,9 @@ public:
deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
}
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
- if (mQuickRejected &&
- CC_LIKELY(replayStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
+ bool useQuickReject) {
+ if (mQuickRejected && CC_LIKELY(useQuickReject)) {
return;
}
@@ -261,7 +265,8 @@ public:
SaveOp(int flags)
: mFlags(flags) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
int newSaveCount = deferStruct.mRenderer.save(mFlags);
deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
}
@@ -293,7 +298,8 @@ public:
RestoreToCountOp(int count)
: mCount(count) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
this, saveCount + mCount);
deferStruct.mRenderer.restoreToCount(saveCount + mCount);
@@ -326,7 +332,8 @@ public:
int alpha, SkXfermode::Mode mode, int flags)
: mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
// NOTE: don't bother with actual saveLayer, instead issuing it at flush time
int newSaveCount = deferStruct.mRenderer.getSaveCount();
deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
@@ -490,7 +497,8 @@ class ClipOp : public StateOp {
public:
ClipOp(SkRegion::Op op) : mOp(op) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
// NOTE: must defer op BEFORE applying state, since it may read clip
deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
@@ -1371,12 +1379,14 @@ public:
: DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
mDisplayList(displayList), mFlags(flags) {}
- virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
+ virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
+ bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable()) {
mDisplayList->defer(deferStruct, level + 1);
}
}
- virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
+ virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
+ bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable()) {
mDisplayList->replay(replayStruct, level + 1);
}