Always use both a color and coverage attribute in GrAARectRenderer.

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/435743002
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index bf3a81e..a8ba024 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -32,3 +32,20 @@
 ## http://skbug.com/123456 : ignoring failures on gradtext GM test
 ## epoger will rebaseline by 25 Dec 2013
 #gradtext
+
+#bsalomon: https://codereview.chromium.org/435743002
+thinstrokedrects
+thinrects
+drawlooper
+aarectmodes
+mixed_xfermodes
+convex_poly_effect
+rects
+twopointconical
+gradients_2pt_conical_inside
+gradients_local_perspective
+gradient_dirty_laundry
+gradients
+gradients_2pt_conical_edge
+gradients_2pt_conical_outside
+gradients_no_texture
diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h
index c53e4b2..4ab709b 100644
--- a/include/gpu/GrColor.h
+++ b/include/gpu/GrColor.h
@@ -88,6 +88,11 @@
     rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;
 }
 
+/** Determines whether the color is opaque or not. */
+static inline bool GrColorIsOpaque(GrColor color) {
+    return (color & (0xFFU << GrColor_SHIFT_A)) == (0xFFU << GrColor_SHIFT_A);
+}
+
 /**
  * Flags used for bitfields of color components. They are defined so that the bit order reflects the
  * GrColor shift order.
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index 44c16a1..be82d5b 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -256,24 +256,12 @@
 
 namespace {
 
-extern const GrVertexAttrib gAARectCoverageAttribs[] = {
-    {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
+extern const GrVertexAttrib gAARectAttribs[] = {
+    {kVec2f_GrVertexAttribType,  0,                                 kPosition_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                   kColor_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
 };
 
-extern const GrVertexAttrib gAARectColorAttribs[] = {
-    {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
-};
-
-static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) {
-    if (useCoverage) {
-        drawState->setVertexAttribs<gAARectCoverageAttribs>(SK_ARRAY_COUNT(gAARectCoverageAttribs));
-    } else {
-        drawState->setVertexAttribs<gAARectColorAttribs>(SK_ARRAY_COUNT(gAARectColorAttribs));
-    }
-}
-
 static void set_inset_fan(SkPoint* pts, size_t stride,
                           const SkRect& r, SkScalar dx, SkScalar dy) {
     pts->setRectFan(r.fLeft + dx, r.fTop + dy,
@@ -451,11 +439,15 @@
                                           GrDrawTarget* target,
                                           const SkRect& rect,
                                           const SkMatrix& combinedMatrix,
-                                          const SkRect& devRect,
-                                          bool useVertexCoverage) {
+                                          const SkRect& devRect) {
     GrDrawState* drawState = target->drawState();
 
-    set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
+    GrColor color = drawState->getColor();
+
+    drawState->setVertexAttribs<gAARectAttribs>(SK_ARRAY_COUNT(gAARectAttribs));
+    if (GrColorIsOpaque(color)) {
+        drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+    }
 
     GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
     if (!geo.succeeded()) {
@@ -471,7 +463,7 @@
 
     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
     size_t vsize = drawState->getVertexSize();
-    SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
+    SkASSERT(sizeof(SkPoint) + 2 * sizeof(GrColor) == vsize);
 
     SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
     SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
@@ -528,9 +520,11 @@
         *((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1];
     }
 
+    // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
     verts += sizeof(SkPoint);
     for (int i = 0; i < 4; ++i) {
-        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+        *reinterpret_cast<GrColor*>(verts + i * vsize) = color;
+        *reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
     }
 
     int scale;
@@ -541,20 +535,11 @@
         scale = 0xff;
     }
 
-    GrColor innerColor;
-    if (useVertexCoverage) {
-        innerColor = GrColorPackRGBA(scale, scale, scale, scale);
-    } else {
-        if (0xff == scale) {
-            innerColor = target->getDrawState().getColor();
-        } else {
-            innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
-        }
-    }
-
-    verts += 4 * vsize;
+    GrColor innerCoverage;
+    innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);    verts += 4 * vsize;
     for (int i = 0; i < 4; ++i) {
-        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
+        *reinterpret_cast<GrColor*>(verts + i * vsize) = color;
+        *reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = innerCoverage;
     }
 
     target->setIndexSourceToBuffer(indexBuffer);
@@ -723,8 +708,7 @@
                                     const SkRect& rect,
                                     const SkMatrix& combinedMatrix,
                                     const SkRect& devRect,
-                                    const SkStrokeRec& stroke,
-                                    bool useVertexCoverage) {
+                                    const SkStrokeRec& stroke) {
     SkVector devStrokeSize;
     SkScalar width = stroke.getWidth();
     if (width > 0) {
@@ -767,8 +751,7 @@
     }
 
     if (spare <= 0 && miterStroke) {
-        this->fillAARect(gpu, target, devOutside, SkMatrix::I(),
-                         devOutside, useVertexCoverage);
+        this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
         return;
     }
 
@@ -785,8 +768,7 @@
         devOutsideAssist.outset(0, ry);
     }
 
-    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
-                               devInside, useVertexCoverage, miterStroke);
+    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, miterStroke);
 }
 
 void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
@@ -794,11 +776,15 @@
                                             const SkRect& devOutside,
                                             const SkRect& devOutsideAssist,
                                             const SkRect& devInside,
-                                            bool useVertexCoverage,
                                             bool miterStroke) {
     GrDrawState* drawState = target->drawState();
 
-    set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
+    drawState->setVertexAttribs<gAARectAttribs>(SK_ARRAY_COUNT(gAARectAttribs));
+
+    GrColor color = drawState->getColor();
+    if (GrColorIsOpaque(color)) {
+        drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+    }
 
     int innerVertexNum = 4;
     int outerVertexNum = miterStroke ? 4 : 8;
@@ -817,7 +803,6 @@
 
     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
     size_t vsize = drawState->getVertexSize();
-    SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
 
     // We create vertices for four nested rectangles. There are two ramps from 0 to full
     // coverage, one on the exterior of the stroke and the other on the interior.
@@ -866,12 +851,15 @@
         set_inset_fan(fan3Pos, vsize, devInside,   SK_ScalarHalf,  SK_ScalarHalf);
     }
 
+    // Make verts point to vertex color and then set all the color and coverage vertex attrs values.
     // The outermost rect has 0 coverage
     verts += sizeof(SkPoint);
     for (int i = 0; i < outerVertexNum; ++i) {
-        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+        *reinterpret_cast<GrColor*>(verts + i * vsize) = color;
+        *reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
     }
 
+    // scale is the coverage for the the inner two rects.
     int scale;
     if (inset < SK_ScalarHalf) {
         scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
@@ -880,27 +868,18 @@
         scale = 0xff;
     }
 
-    // The inner two rects have full coverage
-    GrColor innerColor;
-    if (useVertexCoverage) {
-        innerColor = GrColorPackRGBA(scale, scale, scale, scale);
-    } else {
-        if (0xff == scale) {
-            innerColor = target->getDrawState().getColor();
-        } else {
-            innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
-        }
-    }
-
     verts += outerVertexNum * vsize;
+    GrColor innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
     for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
-        *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
+        *reinterpret_cast<GrColor*>(verts + i * vsize) = color;
+        *reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = innerCoverage;
     }
 
     // The innermost rect has 0 coverage
     verts += (outerVertexNum + innerVertexNum) * vsize;
     for (int i = 0; i < innerVertexNum; ++i) {
-        *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
+        *reinterpret_cast<GrColor*>(verts + i * vsize) = color;
+        *reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
     }
 
     target->setIndexSourceToBuffer(indexBuffer);
@@ -911,8 +890,7 @@
 void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
                                          GrDrawTarget* target,
                                          const SkRect rects[2],
-                                         const SkMatrix& combinedMatrix,
-                                         bool useVertexCoverage) {
+                                         const SkMatrix& combinedMatrix) {
     SkASSERT(combinedMatrix.rectStaysRect());
     SkASSERT(!rects[1].isEmpty());
 
@@ -922,10 +900,9 @@
     combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
 
     if (devInside.isEmpty()) {
-        this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside, useVertexCoverage);
+        this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
         return;
     }
 
-    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
-                               devInside, useVertexCoverage, true);
+    this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, true);
 }
diff --git a/src/gpu/GrAARectRenderer.h b/src/gpu/GrAARectRenderer.h
index faaf7e2..bfa295b 100644
--- a/src/gpu/GrAARectRenderer.h
+++ b/src/gpu/GrAARectRenderer.h
@@ -43,8 +43,7 @@
                     GrDrawTarget* target,
                     const SkRect& rect,
                     const SkMatrix& combinedMatrix,
-                    const SkRect& devRect,
-                    bool useVertexCoverage) {
+                    const SkRect& devRect) {
 #ifdef SHADER_AA_FILL_RECT
         if (combinedMatrix.rectStaysRect()) {
             this->shaderFillAlignedAARect(gpu, target,
@@ -54,9 +53,7 @@
                                    rect, combinedMatrix);
         }
 #else
-        this->geometryFillAARect(gpu, target,
-                                 rect, combinedMatrix,
-                                 devRect, useVertexCoverage);
+        this->geometryFillAARect(gpu, target, rect, combinedMatrix, devRect);
 #endif
     }
 
@@ -65,15 +62,13 @@
                       const SkRect& rect,
                       const SkMatrix& combinedMatrix,
                       const SkRect& devRect,
-                      const SkStrokeRec& stroke,
-                      bool useVertexCoverage);
+                      const SkStrokeRec& stroke);
 
     // First rect is outer; second rect is inner
     void fillAANestedRects(GrGpu* gpu,
                            GrDrawTarget* target,
                            const SkRect rects[2],
-                           const SkMatrix& combinedMatrix,
-                           bool useVertexCoverage);
+                           const SkMatrix& combinedMatrix);
 
 private:
     GrIndexBuffer*              fAAFillRectIndexBuffer;
@@ -85,14 +80,11 @@
     static int aaStrokeRectIndexCount(bool miterStroke);
     GrIndexBuffer* aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke);
 
-    // TODO: Remove the useVertexCoverage boolean. Just use it all the time
-    // since we now have a coverage vertex attribute
     void geometryFillAARect(GrGpu* gpu,
                             GrDrawTarget* target,
                             const SkRect& rect,
                             const SkMatrix& combinedMatrix,
-                            const SkRect& devRect,
-                            bool useVertexCoverage);
+                            const SkRect& devRect);
 
     void shaderFillAARect(GrGpu* gpu,
                           GrDrawTarget* target,
@@ -109,7 +101,6 @@
                               const SkRect& devOutside,
                               const SkRect& devOutsideAssist,
                               const SkRect& devInside,
-                              bool useVertexCoverage,
                               bool miterStroke);
 
     typedef SkRefCnt INHERITED;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index edd4454..0f79402 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -404,8 +404,7 @@
                                                               fGpu,
                                                               element->getRect(),
                                                               SkMatrix::I(),
-                                                              element->getRect(),
-                                                              false);
+                                                              element->getRect());
             } else {
                 fGpu->drawSimpleRect(element->getRect());
             }
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 96380bd..282d6c4 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -719,35 +719,17 @@
     verts[9] = verts[1];
 }
 
-static bool isIRect(const SkRect& r) {
-    return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
-           SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
-}
-
 static bool apply_aa_to_rect(GrDrawTarget* target,
                              const SkRect& rect,
                              SkScalar strokeWidth,
                              const SkMatrix& combinedMatrix,
-                             SkRect* devBoundRect,
-                             bool* useVertexCoverage) {
-    // we use a simple coverage ramp to do aa on axis-aligned rects
-    // we check if the rect will be axis-aligned, and the rect won't land on
-    // integer coords.
-
-    // we are keeping around the "tweak the alpha" trick because
-    // it is our only hope for the fixed-pipe implementation.
-    // In a shader implementation we can give a separate coverage input
-    // TODO: remove this ugliness when we drop the fixed-pipe impl
-    *useVertexCoverage = false;
-    if (!target->getDrawState().canTweakAlphaForCoverage()) {
-        if (target->shouldDisableCoverageAAForBlend()) {
+                             SkRect* devBoundRect) {
+    if (!target->getDrawState().canTweakAlphaForCoverage() &&
+        target->shouldDisableCoverageAAForBlend()) {
 #ifdef SK_DEBUG
-            //GrPrintf("Turning off AA to correctly apply blend.\n");
+        //GrPrintf("Turning off AA to correctly apply blend.\n");
 #endif
-            return false;
-        } else {
-            *useVertexCoverage = true;
-        }
+        return false;
     }
     const GrDrawState& drawState = target->getDrawState();
     if (drawState.getRenderTarget()->isMultisampled()) {
@@ -771,11 +753,7 @@
 
     combinedMatrix.mapRect(devBoundRect, rect);
 
-    if (strokeWidth < 0) {
-        return !isIRect(*devBoundRect);
-    } else {
-        return true;
-    }
+    return true;
 }
 
 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
@@ -840,11 +818,9 @@
     }
 
     SkRect devBoundRect;
-    bool useVertexCoverage;
     bool needAA = paint.isAntiAlias() &&
                   !target->getDrawState().getRenderTarget()->isMultisampled();
-    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, &devBoundRect,
-                                           &useVertexCoverage);
+    bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, &devBoundRect);
 
     const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
 
@@ -856,12 +832,11 @@
         if (width >= 0) {
             fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
                                           matrix, devBoundRect,
-                                          strokeRec, useVertexCoverage);
+                                          strokeRec);
         } else {
             // filled AA rect
             fAARectRenderer->fillAARect(this->getGpu(), target,
-                                        rect, matrix, devBoundRect,
-                                        useVertexCoverage);
+                                        rect, matrix, devBoundRect);
         }
         return;
     }
@@ -1117,8 +1092,7 @@
 static bool is_nested_rects(GrDrawTarget* target,
                             const SkPath& path,
                             const SkStrokeRec& stroke,
-                            SkRect rects[2],
-                            bool* useVertexCoverage) {
+                            SkRect rects[2]) {
     SkASSERT(stroke.isFillStyle());
 
     if (path.isInverseFillType()) {
@@ -1133,13 +1107,9 @@
         return false;
     }
 
-    *useVertexCoverage = false;
-    if (!target->getDrawState().canTweakAlphaForCoverage()) {
-        if (target->shouldDisableCoverageAAForBlend()) {
-            return false;
-        } else {
-            *useVertexCoverage = true;
-        }
+    if (!target->getDrawState().canTweakAlphaForCoverage() &&
+        target->shouldDisableCoverageAAForBlend()) {
+        return false;
     }
 
     SkPath::Direction dirs[2];
@@ -1233,20 +1203,16 @@
 
     if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
         // Concave AA paths are expensive - try to avoid them for special cases
-        bool useVertexCoverage;
         SkRect rects[2];
 
-        if (is_nested_rects(target, path, strokeRec, rects, &useVertexCoverage)) {
+        if (is_nested_rects(target, path, strokeRec, rects)) {
             SkMatrix origViewMatrix = drawState->getViewMatrix();
             GrDrawState::AutoViewMatrixRestore avmr;
             if (!avmr.setIdentity(target->drawState())) {
                 return;
             }
 
-            fAARectRenderer->fillAANestedRects(this->getGpu(), target,
-                                               rects,
-                                               origViewMatrix,
-                                               useVertexCoverage);
+            fAARectRenderer->fillAANestedRects(this->getGpu(), target, rects, origViewMatrix);
             return;
         }
     }
@@ -1761,6 +1727,9 @@
             are->set(NULL);
             return NULL;
         }
+        // Clear any vertex attributes configured for the previous use of the
+        // GrDrawState which can effect which blend optimizations are in effect.
+        fDrawState->setDefaultVertexAttribs();
     } else {
         fDrawState->reset(fViewMatrix);
         fDrawState->setRenderTarget(fRenderTarget.get());
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index fa4d5b0..249eeeb 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -60,7 +60,8 @@
     /**
      * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
      * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
-     * equivalents are set to default values. Clipping will be enabled.
+     * equivalents are set to default values with the exception of vertex attribute state which
+     * is unmodified by this function and clipping which will be enabled.
      */
     void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);