Revert 6351 due to bugs.
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 12 Nov 2012 13:38:57 +0000 (13:38 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 12 Nov 2012 13:38:57 +0000 (13:38 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@6377 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkClipStack.h
src/core/SkClipStack.cpp
src/gpu/GrClipMaskManager.cpp
src/gpu/GrClipMaskManager.h

index a6b5f52..443e6ad 100644 (file)
@@ -138,10 +138,6 @@ public:
              * Gets the bounds of the clip element, either the rect or path bounds.
              */
             const SkRect& getBounds() const;
-            /**
-             * Returns true if the clip element is a path that is inverse filled
-             */
-            bool isInverseFilled() const;
 
             const SkRect*   fRect;  // if non-null, this is a rect clip
             const SkPath*   fPath;  // if non-null, this is a path clip
@@ -178,12 +174,6 @@ public:
         const Clip* skipToTopmost(SkRegion::Op op);
 
         /**
-         * Moves forward to the next clip element that uses op. If no clip with that op is found,
-         * returns NULL.
-         */
-        const Clip* skipToNext(SkRegion::Op op);
-
-        /**
          * Restarts the iterator on a clip stack.
          */
         void reset(const SkClipStack& stack, IterStart startLoc);
index 69b3ba9..38f2580 100644 (file)
@@ -735,10 +735,6 @@ const SkRect& SkClipStack::Iter::Clip::getBounds() const {
     }
 }
 
-bool SkClipStack::Iter::Clip::isInverseFilled() const {
-    return NULL != fPath && fPath->isInverseFillType();
-}
-
 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
     : fStack(&stack) {
     this->reset(stack, startLoc);
@@ -823,18 +819,6 @@ const SkClipStack::Iter::Clip* SkClipStack::Iter::skipToTopmost(SkRegion::Op op)
     return this->next();
 }
 
-const SkClipStack::Iter::Clip* SkClipStack::Iter::skipToNext(SkRegion::Op op) {
-    const SkClipStack::Rec* rec;
-    do {
-        rec = (const SkClipStack::Rec*)fIter.next();
-        if (NULL == rec) {
-            return NULL;
-        }
-    } while (rec->fOp != op);
-    this->updateClip(rec);
-    return &fClip;
-}
-
 const SkClipStack::Iter::Clip* SkClipStack::Iter::nextCombined() {
     const Clip* clip;
 
index 6cd02bb..893bcb1 100644 (file)
@@ -22,6 +22,7 @@
 GR_DEFINE_RESOURCE_CACHE_DOMAIN(GrClipMaskManager, GetAlphaMaskDomain)
 
 #define GR_AA_CLIP 1
+#define GR_SW_CLIP 1
 
 ////////////////////////////////////////////////////////////////////////////////
 namespace {
@@ -157,7 +158,7 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
         return false;
     }
 
-#if GR_AA_CLIP
+#if GR_SW_CLIP
     bool requiresAA = requires_AA(*clipDataIn->fClipStack);
 
     // If MSAA is enabled we can do everything in the stencil buffer.
@@ -181,7 +182,9 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
         // if SW clip mask creation fails fall through to the other
         // two possible methods (bottoming out at stencil clipping)
     }
+#endif // GR_SW_CLIP
 
+#if GR_AA_CLIP
     // If MSAA is enabled use the (faster) stencil path for AA clipping
     // otherwise the alpha clip mask is our only option
     if (0 == rt->numSamples() && requiresAA) {
@@ -343,7 +346,7 @@ const SkClipStack::Iter::Clip* process_initial_clip_elements(
                 break;
             case SkRegion::kReverseDifference_Op:
                 // if all pixels are clearToInside then reverse difference
-                // produces empty set. Otherwise it is same as replace
+                // produces empty set. Otherise it is same as replace
                 if (*clearToInside) {
                     *clearToInside = false;
                 } else {
@@ -398,8 +401,48 @@ void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+bool draw_path_in_software(GrContext* context,
+                           GrGpu* gpu,
+                           const SkPath& path,
+                           GrPathFill fill,
+                           bool doAA,
+                           const GrIRect& resultBounds) {
+
+    SkAutoTUnref<GrTexture> texture(
+                GrSWMaskHelper::DrawPathMaskToTexture(context, path,
+                                                      resultBounds, fill,
+                                                      doAA, NULL));
+    if (NULL == texture) {
+        return false;
+    }
+
+    // The ClipMaskManager accumulates the clip mask in the UL corner
+    GrIRect rect = GrIRect::MakeWH(resultBounds.width(), resultBounds.height());
+
+    GrSWMaskHelper::DrawToTargetWithPathMask(texture, gpu, rect);
+
+    GrAssert(!GrIsFillInverted(fill));
+    return true;
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
+bool draw_path(GrContext* context,
+               GrGpu* gpu,
+               const SkPath& path,
+               GrPathFill fill,
+               bool doAA,
+               const GrIRect& resultBounds) {
+
+    GrPathRenderer* pr = context->getPathRenderer(path, fill, gpu, doAA, false);
+    if (NULL == pr) {
+        return draw_path_in_software(context, gpu, path, fill, doAA, resultBounds);
+    }
+
+    pr->drawPath(path, fill, gpu, doAA);
+    return true;
+}
 
 // 'rect' enters in device coordinates and leaves in canvas coordinates
 void device_to_canvas(SkRect* rect, const SkIPoint& origin) {
@@ -416,19 +459,12 @@ void device_to_canvas(SkRect* rect, const SkIPoint& origin) {
 ////////////////////////////////////////////////////////////////////////////////
 bool GrClipMaskManager::drawClipShape(GrTexture* target,
                                       const SkClipStack::Iter::Clip* clip,
-                                      const SkIRect& clipRect) {
+                                      const GrIRect& resultBounds) {
     GrDrawState* drawState = fGpu->drawState();
     GrAssert(NULL != drawState);
 
     drawState->setRenderTarget(target->asRenderTarget());
 
-    GrDrawTarget::AutoClipRestore acr(fGpu);
-    SkClipStack rectStack(clipRect);
-    GrClipData cd;
-    cd.fClipStack = &rectStack;
-    cd.fOrigin.setZero();
-    fGpu->setClip(&cd);
-
     if (NULL != clip->fRect) {
         if (clip->fDoAA) {
             getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu,
@@ -438,18 +474,11 @@ bool GrClipMaskManager::drawClipShape(GrTexture* target,
             fGpu->drawSimpleRect(*clip->fRect, NULL);
         }
     } else if (NULL != clip->fPath) {
-
-        GrPathRenderer* pr = this->getContext()->getPathRenderer(*clip->fPath,
-                                                                 get_path_fill(*clip->fPath),
-                                                                 fGpu,
-                                                                 clip->fDoAA,
-                                                                 false);
-        if (NULL == pr) {
-            GrAssert(false); // We should have done the whole clip-stack in SW.
-            return false;
-        }
-
-        pr->drawPath(*clip->fPath, get_path_fill(*clip->fPath), fGpu, clip->fDoAA);
+        return draw_path(this->getContext(), fGpu,
+                         *clip->fPath,
+                         get_path_fill(*clip->fPath),
+                         clip->fDoAA,
+                         resultBounds);
     }
     return true;
 }
@@ -535,7 +564,7 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
     clipDataIn.getConservativeBounds(rt, devResultBounds);
 
     // need to outset a pixel since the standard bounding box computation
-    // path doesn't leave any room for anti-aliasing (esp. w.r.t. rects)
+    // path doesn't leave any room for antialiasing (esp. w.r.t. rects)
     devResultBounds->outset(1, 1);
 
     // TODO: make sure we don't outset if bounds are still 0,0 @ min
@@ -550,30 +579,6 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
     return false;
 }
 
-namespace {
-// Does a look-ahead to check whether we can bound earlier mask generation by forthcoming
-// intersections.
-void get_current_mask_bounds(const SkIRect& maskResultBounds,
-                             const SkClipStack::Iter& curr,
-                             const SkVector& clipToMaskOffset,
-                             SkRect* currMaskBounds) {
-    SkClipStack::Iter isectIter(curr);
-    const SkClipStack::Iter::Clip* clip = isectIter.skipToNext(SkRegion::kIntersect_Op);
-    if (NULL != clip) {
-        *currMaskBounds = clip->getBounds();
-        while (NULL != (clip = isectIter.next()) &&
-               SkRegion::kIntersect_Op == clip->fOp &&
-               !clip->isInverseFilled()) {
-            currMaskBounds->intersect(clip->getBounds());
-        }
-        currMaskBounds->offset(clipToMaskOffset);
-        currMaskBounds->intersect(SkRect::MakeFromIRect(maskResultBounds));
-    } else {
-        *currMaskBounds = SkRect::MakeFromIRect(maskResultBounds);
-    }
-}
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Create a 8-bit clip mask in alpha
 bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
@@ -616,9 +621,8 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
     bool clearToInside;
     SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
 
-    SkClipStack::Iter iter(*clipDataIn.fClipStack, SkClipStack::Iter::kBottom_IterStart);
-    iter.skipToTopmost(SkRegion::kReplace_Op);
-
+    SkClipStack::Iter iter(*clipDataIn.fClipStack,
+                           SkClipStack::Iter::kBottom_IterStart);
     const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
                                                               *devResultBounds,
                                                               &clearToInside,
@@ -629,26 +633,10 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
     fGpu->clear(&maskResultBounds,
                 clearToInside ? 0xffffffff : 0x00000000,
                 accum->asRenderTarget());
-    GR_DEBUGCODE(bool accumClearedToZero = !clearToInside;)
-
+    bool accumClearedToZero = !clearToInside;
 
     GrAutoScratchTexture temp;
     bool first = true;
-
-    // We bound mask-generation to both the known bounds of the final result as well as the bounds
-    // of the next run of intersections. This limits the amount of clearing and merging we have
-    // to do and can also allow us to skip intersect-rects entirely.
-    SkRect currMaskBounds;
-    SkIRect currMaskIBounds;
-    get_current_mask_bounds(maskResultBounds, iter, clipToMaskOffset, &currMaskBounds);
-    // currMaskBounds is used to reduce the number of pixels touched. It also allows us to skip
-    // non-AA intersect rects since we've clipped earlier elements to those rects already.
-    // We round out here which is consistent with how non-AA rects are handled.
-    currMaskBounds.roundOut(&currMaskIBounds);
-
-    // used to know when we're through with a run of intersect ops.
-    SkRegion::Op prevOp = SkRegion::kReplace_Op;
-
     // walk through each clip element and perform its set op
     for ( ; NULL != clip; clip = iter.nextCombined()) {
 
@@ -658,33 +646,18 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
             op = firstOp;
         }
 
-        if (op == SkRegion::kIntersect_Op) {
-            // When we encounter an intersect we may have already fully accounted for it by applying
-            // currMaskBounds to the accumulated mask.
-            if (NULL != clip->fRect &&
-                (!clip->fDoAA || clip->fRect->contains(currMaskBounds))) {
-                prevOp = SkRegion::kIntersect_Op;
-                continue;
+        if (SkRegion::kReplace_Op == op) {
+            // clear the accumulator and draw the new object directly into it
+            if (!accumClearedToZero) {
+                fGpu->clear(&maskResultBounds, 0x00000000, accum->asRenderTarget());
             }
-        } else if (prevOp == SkRegion::kIntersect_Op) {
-            // We've finished a run of intersects, update currMaskBounds based on the next run.
-            get_current_mask_bounds(maskResultBounds, iter, clipToMaskOffset, &currMaskBounds);
-            currMaskBounds.roundOut(&currMaskIBounds);
-        }
 
-        prevOp = op;
-
-        if (SkRegion::kReplace_Op == op) {
-            // The accumulator should already be cleared. There can only be one replace since we
-            // skip to the last one. Moreover, process_initial_clip_elements will have set
-            // clearToInside to false before the initial clear.
-            GrAssert(accumClearedToZero);
             setup_boolean_blendcoeffs(drawState, op);
-            this->drawClipShape(accum, clip, currMaskIBounds);
+            this->drawClipShape(accum, clip, *devResultBounds);
 
         } else if (SkRegion::kReverseDifference_Op == op ||
                    SkRegion::kIntersect_Op == op) {
-            // There is no point in intersecting a screen filling rectangle.
+            // there is no point in intersecting a screen filling rectangle.
             if (SkRegion::kIntersect_Op == op && NULL != clip->fRect &&
                 contains(*clip->fRect, *devResultBounds, clipDataIn.fOrigin)) {
                 continue;
@@ -696,32 +669,31 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
                 return false;
             }
 
-            // This is the bounds of the clip element in the space of the alpha-mask. The temporary
+            // this is the bounds of the clip element in the space of the alpha-mask. The temporary
             // mask buffer can be substantially larger than the actually clip stack element. We
             // touch the minimum number of pixels necessary and use decal mode to combine it with
-            // the accumulator.
+            // the accumulator
             GrRect elementMaskBounds = clip->getBounds();
             elementMaskBounds.offset(clipToMaskOffset);
-            elementMaskBounds.intersect(currMaskBounds);
             GrIRect elementMaskIBounds;
             elementMaskBounds.roundOut(&elementMaskIBounds);
 
-            // Clear the temp target & draw into it
+            // clear the temp target & draw into it
             fGpu->clear(&elementMaskIBounds, 0x00000000, temp.texture()->asRenderTarget());
 
             setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
-            this->drawClipShape(temp.texture(), clip, currMaskIBounds);
+            this->drawClipShape(temp.texture(), clip, elementMaskIBounds);
 
-            // Now draw into the accumulator using the real operation and the temp buffer as a
-            // texture
+            // Now draw into the accumulator using the real operation
+            // and the temp buffer as a texture
             this->mergeMask(accum, temp.texture(), op, maskResultBounds, elementMaskIBounds);
         } else {
             // all the remaining ops can just be directly draw into
             // the accumulation buffer
             setup_boolean_blendcoeffs(drawState, op);
-            this->drawClipShape(accum, clip, currMaskIBounds);
+            this->drawClipShape(accum, clip, *devResultBounds);
         }
-        GR_DEBUGCODE(accumClearedToZero = false;)
+        accumClearedToZero = false;
     }
 
     *result = accum;
index eaaa2e3..89b1ef8 100644 (file)
@@ -126,7 +126,7 @@ private:
 
     bool drawClipShape(GrTexture* target,
                        const SkClipStack::Iter::Clip* clip,
-                       const SkIRect& clipRect);
+                       const GrIRect& resultBounds);
 
     void mergeMask(GrTexture* dstMask,
                    GrTexture* srcMask,