Set empty/wide-open genID on clip stack in more places and fix a bug in GrReduceClipS...
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 28 Nov 2012 14:42:41 +0000 (14:42 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 28 Nov 2012 14:42:41 +0000 (14:42 +0000)
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

src/core/SkClipStack.cpp
src/gpu/GrClipMaskManager.cpp
tests/ClipStackTest.cpp

index 10e15992d153740853ef80cae94f4a72a54a98aa..891270d37a1b4c2285569a0832a1969b21f81b90 100644 (file)
@@ -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 @@ struct SkClipStack::Rec {
         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 @@ struct SkClipStack::Rec {
         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 @@ struct SkClipStack::Rec {
         fGenID = kEmptyGenID;
     }
 
-    void checkEmpty() {
+    void checkEmpty() const {
         SkASSERT(fFiniteBound.isEmpty());
         SkASSERT(kNormal_BoundsType == fFiniteBoundType);
         SkASSERT(!fIsIntersectionOfRects);
@@ -196,6 +197,7 @@ struct SkClipStack::Rec {
                 // 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 @@ struct SkClipStack::Rec {
             case kInvPrev_InvCur_FillCombo:
                 if (!fFiniteBound.intersect(prevFinite)) {
                     fFiniteBound.setEmpty();
+                    fGenID = kWideOpenGenID;
                 }
                 fFiniteBoundType = kInsideOut_BoundsType;
                 break;
@@ -299,6 +302,7 @@ struct SkClipStack::Rec {
             case kPrev_Cur_FillCombo:
                 if (!fFiniteBound.intersect(prevFinite)) {
                     fFiniteBound.setEmpty();
+                    fGenID = kEmptyGenID;
                 }
                 break;
             default:
@@ -321,6 +325,7 @@ struct SkClipStack::Rec {
             case kInvPrev_Cur_FillCombo:
                 if (!fFiniteBound.intersect(prevFinite)) {
                     fFiniteBound.setEmpty();
+                    fGenID = kEmptyGenID;
                 }
                 fFiniteBoundType = kNormal_BoundsType;
                 break;
@@ -341,7 +346,10 @@ struct SkClipStack::Rec {
         }
     }
 
-    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 @@ bool SkClipStack::intersectRectWithClip(SkRect* rect) const {
 
 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 @@ void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
 
                     rec->fDoAA = doAA;
                     Rec* prev = (Rec*) iter.prev();
-                    rec->updateBound(prev);
-                    rec->fGenID = genID;
+                    rec->updateBoundAndGenID(prev);
                     return;
                 }
                 break;
@@ -624,8 +629,7 @@ void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
         }
     }
     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 @@ void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
         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 @@ void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
         }
     }
     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 @@ void SkClipStack::clipEmpty() {
     if (rec && rec->fSaveCount == fSaveCount) {
         this->purgeClip(rec);
     }
+    ((Rec*)fDeque.back())->fGenID = kEmptyGenID;
 }
 
 bool SkClipStack::isWideOpen() const {
@@ -701,8 +703,8 @@ bool SkClipStack::isWideOpen() const {
     }
 
     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 @@ const SkClipStack::Iter::Clip* SkClipStack::Iter::updateClip(
         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 @@ void SkClipStack::removePurgeClipCallback(PFPurgeClipCB callback, void* data) co
 // 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 @@ void SkClipStack::purgeClip(Rec* rec) {
 }
 
 int32_t SkClipStack::GetNextGenID() {
+    // TODO: handle overflow.
     return sk_atomic_inc(&gGenID);
 }
 
index 0808b5e3b3bb5de1f93fd0c50003adbe5f09dafc..9190bdc6a65a4d6ce080362e643001bbfc429a52 100644 (file)
@@ -90,11 +90,11 @@ void GrReduceClipStack(const SkClipStack& stack,
             *initialState = kAllIn_InitialState;
             break;
         }
-        if (!embiggens && SkClipStack::kEmptyGenID == clip->fGenID) {
+        if (SkClipStack::kEmptyGenID == clip->fGenID) {
             *initialState = kAllOut_InitialState;
             break;
         }
-        if (!emsmallens && SkClipStack::kWideOpenGenID == clip->fGenID) {
+        if (SkClipStack::kWideOpenGenID == clip->fGenID) {
             *initialState = kAllIn_InitialState;
             break;
         }
index 2707e4047ee72c38eb1937ce61a35b80951d18f2..8eb1102de89a7bcbd071fe12cbf2b104213e0821 100644 (file)
@@ -903,7 +903,7 @@ static void TestClipStack(skiatest::Reporter* reporter) {
     test_rect_merging(reporter);
     test_iter_rect_merging(reporter);
 #if SK_SUPPORT_GPU
-    //test_reduced_clip_stack(reporter);
+    test_reduced_clip_stack(reporter);
 #endif
 }