Add a state bit to GrDrawState that forces coverage to be blended.

Use this mode in GrClipMaskManager.

R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6945048

git-svn-id: http://skia.googlecode.com/svn/trunk@6790 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 11b301d..0a64dd1 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -89,7 +89,6 @@
     // TODO: generalize this function so that when
     // a clip gets complex enough it can just be done in SW regardless
     // of whether it would invoke the GrSoftwarePathRenderer.
-    bool useSW = false;
     SkStroke stroke;
     stroke.setDoFill(true);
 
@@ -305,7 +304,10 @@
             // TODO: Do rects directly to the accumulator using a aa-rect GrEffect that covers the
             // entire mask bounds and writes 0 outside the rect.
             if (element->isAA()) {
-                getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu, element->getRect(), true);
+                getContext()->getAARectRenderer()->fillAARect(fGpu,
+                                                              fGpu,
+                                                              element->getRect(),
+                                                              false);
             } else {
                 fGpu->drawSimpleRect(element->getRect(), NULL);
             }
@@ -444,6 +446,9 @@
     // we populate with a rasterization of the clip.
     SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
 
+    // We're drawing a coverage mask and want coverage to be run through the blend function.
+    drawState->enableState(GrDrawState::kCoverageDrawing_StateBit);
+
     // Set the matrix so that rendered clip elements are transformed to mask space from clip space.
     drawState->viewMatrix()->setTranslate(clipToMaskOffset);
 
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 3b0bff9..1208b77 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -44,6 +44,9 @@
      * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
      * GrEffect).
      *
+     * See the documentation of kCoverageDrawing_StateBit for information about disabling the
+     * the color / coverage distinction.
+     *
      * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
      * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
      * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
@@ -715,9 +718,9 @@
          */
         kDither_StateBit        = 0x01,
         /**
-         * Perform HW anti-aliasing. This means either HW FSAA, if supported
-         * by the render target, or smooth-line rendering if a line primitive
-         * is drawn and line smoothing is supported by the 3D API.
+         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
+         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
+         * the 3D API.
          */
         kHWAntialias_StateBit   = 0x02,
         /**
@@ -730,6 +733,16 @@
          */
         kNoColorWrites_StateBit = 0x08,
 
+        /**
+         * Usually coverage is applied after color blending. The color is blended using the coeffs
+         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
+         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
+         * this case there is no distinction between coverage and color and the caller needs direct
+         * control over the blend coeffs. When set, there will be a single blend step controlled by
+         * setBlendFunc() which will use coverage*color as the src color.
+         */
+         kCoverageDrawing_StateBit = 0x10,
+
         // Users of the class may add additional bits to the vector
         kDummyStateBit,
         kLastPublicStateBit = kDummyStateBit-1,
@@ -787,6 +800,10 @@
         return 0 != (fFlagBits & kNoColorWrites_StateBit);
     }
 
+    bool isCoverageDrawing() const {
+        return 0 != (fFlagBits & kCoverageDrawing_StateBit);
+    }
+
     bool isStateFlagEnabled(uint32_t stateBit) const {
         return 0 != (stateBit & fFlagBits);
     }
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 6927895..92b8a03 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -806,14 +806,15 @@
      * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
      * By tweaking the source color's alpha we're replacing S with S'=fS. It's
      * obvious that that first term will always be ok. The second term can be
-     * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
+     * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
      * for Cd we find that only 1, ISA, and ISC produce the correct depth
-     * coeffecient in terms of S' and D.
+     * coefficient in terms of S' and D.
      */
     GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
     return kOne_GrBlendCoeff == dstCoeff ||
            kISA_GrBlendCoeff == dstCoeff ||
-           kISC_GrBlendCoeff == dstCoeff;
+           kISC_GrBlendCoeff == dstCoeff ||
+           this->getDrawState().isCoverageDrawing();
 }
 
 bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
@@ -830,10 +831,20 @@
     if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
         return false;
     }
+    int stageCnt;
+    // Check whether coverage is treated as color
+    if (drawState.isCoverageDrawing()) {
+        if (0xff != GrColorUnpackA(drawState.getCoverage())) {
+            return false;
+        }
+        stageCnt = GrDrawState::kNumStages;
+    } else {
+        stageCnt = drawState.getFirstCoverageStage();
+    }
     // Check if a color stage could create a partial alpha
-    for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
-        if (this->isStageEnabled(s)) {
-            const GrEffect* effect = drawState.getStage(s).getEffect();
+    for (int s = 0; s < stageCnt; ++s) {
+        const GrEffect* effect = drawState.getStage(s).getEffect();
+        if (NULL != effect) {
             // FIXME: The param indicates whether the texture is opaque or not. However, the effect
             // already controls its textures. It really needs to know whether the incoming color
             // (from a uni, per-vertex colors, or previous stage) is opaque or not.
@@ -877,17 +888,6 @@
     }
     *dstCoeff = drawState.getDstBlendCoeff();
 
-    // We don't ever expect source coeffecients to reference the source
-    GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
-             kISA_GrBlendCoeff != *srcCoeff &&
-             kSC_GrBlendCoeff != *srcCoeff &&
-             kISC_GrBlendCoeff != *srcCoeff);
-    // same for dst
-    GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
-             kIDA_GrBlendCoeff != *dstCoeff &&
-             kDC_GrBlendCoeff != *dstCoeff &&
-             kIDC_GrBlendCoeff != *dstCoeff);
-
     if (drawState.isColorWriteDisabled()) {
         *srcCoeff = kZero_GrBlendCoeff;
         *dstCoeff = kOne_GrBlendCoeff;
@@ -899,13 +899,13 @@
     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
 
-
+    bool covIsZero = !drawState.isCoverageDrawing() &&
+                     !(layout & kCoverage_VertexLayoutBit) &&
+                     0 == drawState.getCoverage();
     // When coeffs are (0,1) there is no reason to draw at all, unless
     // stenciling is enabled. Having color writes disabled is effectively
     // (0,1). The same applies when coverage is known to be 0.
-    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
-        (!(layout & kCoverage_VertexLayoutBit) &&
-         0 == drawState.getCoverage())) {
+    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
         if (drawState.getStencil().doesWrite()) {
             return kDisableBlend_BlendOptFlag |
                    kEmitTransBlack_BlendOptFlag;
@@ -941,10 +941,12 @@
                 // or blend, just write transparent black into the dst.
                 *srcCoeff = kOne_GrBlendCoeff;
                 *dstCoeff = kZero_GrBlendCoeff;
-                return kDisableBlend_BlendOptFlag |
-                       kEmitTransBlack_BlendOptFlag;
+                return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
             }
         }
+    } else if (drawState.isCoverageDrawing()) {
+        // we have coverage but we aren't distinguishing it from alpha by request.
+        return kCoverageAsAlpha_BlendOptFlag;
     } else {
         // check whether coverage can be safely rolled into alpha
         // of if we can skip color computation and just emit coverage
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 6e0af43..fb83c1e 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -482,7 +482,19 @@
                           const SkMatrix* matrix,
                           const GrRect* srcRects[],
                           const SkMatrix* srcMatrices[]);
+    /**
+     * Helper for drawRect when the caller doesn't need separate src rects or
+     * matrices.
+     */
+    void drawSimpleRect(const GrRect& rect, const SkMatrix* matrix = NULL) {
+        drawRect(rect, matrix, NULL, NULL);
+    }
+    void drawSimpleRect(const GrIRect& irect, const SkMatrix* matrix = NULL) {
+        SkRect rect = SkRect::MakeFromIRect(irect);
+        this->drawRect(rect, matrix, NULL, NULL);
+    }
 
+    
     /**
      * This call is used to draw multiple instances of some geometry with a
      * given number of vertices (V) and indices (I) per-instance. The indices in
@@ -517,15 +529,6 @@
                                       int indicesPerInstance);
 
     /**
-     * Helper for drawRect when the caller doesn't need separate src rects or
-     * matrices.
-     */
-    void drawSimpleRect(const GrRect& rect,
-                        const SkMatrix* matrix) {
-         drawRect(rect, matrix, NULL, NULL);
-    }
-
-    /**
      * Clear the current render target if one isn't passed in. Ignores the
      * clip and all other draw state (blend mode, stages, etc). Clears the
      * whole thing if rect is NULL, otherwise just the rect.
@@ -886,14 +889,13 @@
     };
     GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
 
-    // Determines what optimizations can be applied based on the blend.
-    // The coeffecients may have to be tweaked in order for the optimization
-    // to work. srcCoeff and dstCoeff are optional params that receive the
-    // tweaked coeffecients.
-    // Normally the function looks at the current state to see if coverage
-    // is enabled. By setting forceCoverage the caller can speculatively
-    // determine the blend optimizations that would be used if there was
-    // partial pixel coverage
+    /** 
+     * Determines what optimizations can be applied based on the blend. The coefficients may have
+     * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
+     * params that receive the tweaked coefficients. Normally the function looks at the current
+     * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
+     * determine the blend optimizations that would be used if there was partial pixel coverage.
+     */
     BlendOptFlags getBlendOpts(bool forceCoverage = false,
                                GrBlendCoeff* srcCoeff = NULL,
                                GrBlendCoeff* dstCoeff = NULL) const;