Set empty/wide-open genID on clip stack in more places and fix a bug in GrReduceClipStack.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6847116
git-svn-id: http://skia.googlecode.com/svn/trunk@6579 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp
index 10e1599..891270d 100644
--- a/src/core/SkClipStack.cpp
+++ b/src/core/SkClipStack.cpp
@@ -13,7 +13,8 @@
// 0-2 are reserved for invalid, empty & wide-open
-int32_t SkClipStack::gGenID = 3;
+static const int32_t kFirstUnreservedGenID = 3;
+int32_t SkClipStack::gGenID = kFirstUnreservedGenID;
struct SkClipStack::Rec {
enum State {
@@ -61,7 +62,7 @@
fOp = op;
fState = kRect_State;
fDoAA = doAA;
- // bounding box members are updated in a following updateBound call
+ // bounding box members are updated in a following updateBoundAndGenID call
}
Rec(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA)
@@ -72,7 +73,7 @@
fOp = op;
fState = kPath_State;
fDoAA = doAA;
- // bounding box members are updated in a following updateBound call
+ // bounding box members are updated in a following updateBoundAndGenID call
}
void setEmpty() {
@@ -83,7 +84,7 @@
fGenID = kEmptyGenID;
}
- void checkEmpty() {
+ void checkEmpty() const {
SkASSERT(fFiniteBound.isEmpty());
SkASSERT(kNormal_BoundsType == fFiniteBoundType);
SkASSERT(!fIsIntersectionOfRects);
@@ -196,6 +197,7 @@
// occur w/in the intersection of the two finite bounds
if (!fFiniteBound.intersect(prevFinite)) {
fFiniteBound.setEmpty();
+ fGenID = kEmptyGenID;
}
fFiniteBoundType = kNormal_BoundsType;
break;
@@ -254,6 +256,7 @@
case kInvPrev_InvCur_FillCombo:
if (!fFiniteBound.intersect(prevFinite)) {
fFiniteBound.setEmpty();
+ fGenID = kWideOpenGenID;
}
fFiniteBoundType = kInsideOut_BoundsType;
break;
@@ -299,6 +302,7 @@
case kPrev_Cur_FillCombo:
if (!fFiniteBound.intersect(prevFinite)) {
fFiniteBound.setEmpty();
+ fGenID = kEmptyGenID;
}
break;
default:
@@ -321,6 +325,7 @@
case kInvPrev_Cur_FillCombo:
if (!fFiniteBound.intersect(prevFinite)) {
fFiniteBound.setEmpty();
+ fGenID = kEmptyGenID;
}
fFiniteBoundType = kNormal_BoundsType;
break;
@@ -341,7 +346,10 @@
}
}
- void updateBound(const Rec* prior) {
+ void updateBoundAndGenID(const Rec* prior) {
+ // We set this first here but we may overwrite it later if we determine that the clip is
+ // either wide-open or empty.
+ fGenID = GetNextGenID();
// First, optimistically update the current Rec's bound information
// with the current clip's bound
@@ -588,8 +596,6 @@
void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
- int32_t genID = GetNextGenID();
-
// Use reverse iterator instead of back because Rect path may need previous
SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
Rec* rec = (Rec*) iter.prev();
@@ -609,8 +615,7 @@
rec->fDoAA = doAA;
Rec* prev = (Rec*) iter.prev();
- rec->updateBound(prev);
- rec->fGenID = genID;
+ rec->updateBoundAndGenID(prev);
return;
}
break;
@@ -624,8 +629,7 @@
}
}
new (fDeque.push_back()) Rec(fSaveCount, rect, op, doAA);
- ((Rec*) fDeque.back())->updateBound(rec);
- ((Rec*) fDeque.back())->fGenID = genID;
+ ((Rec*) fDeque.back())->updateBoundAndGenID(rec);
if (rec && rec->fSaveCount == fSaveCount) {
this->purgeClip(rec);
@@ -638,8 +642,6 @@
return this->clipDevRect(alt, op, doAA);
}
- int32_t genID = GetNextGenID();
-
Rec* rec = (Rec*)fDeque.back();
if (rec && rec->canBeIntersectedInPlace(fSaveCount, op)) {
const SkRect& pathBounds = path.getBounds();
@@ -664,8 +666,7 @@
}
}
new (fDeque.push_back()) Rec(fSaveCount, path, op, doAA);
- ((Rec*) fDeque.back())->updateBound(rec);
- ((Rec*) fDeque.back())->fGenID = genID;
+ ((Rec*) fDeque.back())->updateBoundAndGenID(rec);
if (rec && rec->fSaveCount == fSaveCount) {
this->purgeClip(rec);
@@ -693,6 +694,7 @@
if (rec && rec->fSaveCount == fSaveCount) {
this->purgeClip(rec);
}
+ ((Rec*)fDeque.back())->fGenID = kEmptyGenID;
}
bool SkClipStack::isWideOpen() const {
@@ -701,8 +703,8 @@
}
const Rec* back = (const Rec*) fDeque.back();
- return kInsideOut_BoundsType == back->fFiniteBoundType &&
- back->fFiniteBound.isEmpty();
+ return kWideOpenGenID == back->fGenID ||
+ (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty());
}
///////////////////////////////////////////////////////////////////////////////
@@ -760,6 +762,7 @@
case SkClipStack::Rec::kEmpty_State:
fClip.fRect = NULL;
fClip.fPath = NULL;
+ rec->checkEmpty();
break;
case SkClipStack::Rec::kRect_State:
fClip.fRect = &rec->fRect;
@@ -934,6 +937,9 @@
// The clip state represented by 'rec' will never be used again. Purge it.
void SkClipStack::purgeClip(Rec* rec) {
SkASSERT(NULL != rec);
+ if (rec->fGenID >= 0 && rec->fGenID < kFirstUnreservedGenID) {
+ return;
+ }
for (int i = 0; i < fCallbackData.count(); ++i) {
(*fCallbackData[i].fCallback)(rec->fGenID, fCallbackData[i].fData);
@@ -944,6 +950,7 @@
}
int32_t SkClipStack::GetNextGenID() {
+ // TODO: handle overflow.
return sk_atomic_inc(&gGenID);
}