Revert "Do not apply hairline optimization for paths if nv_path_rendering is used"

This reverts commit r12185.

Review URL: https://codereview.chromium.org/66813002

git-svn-id: http://skia.googlecode.com/svn/trunk@12187 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 50d7764..02c4419 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -759,7 +759,7 @@
     }
     devBounds->set(lines.begin(), lines.count());
     for (int i = 0; i < lineCnt; ++i) {
-        add_line(&lines[2*i], toSrc, drawState->getCoverageColor(), &verts);
+        add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts);
     }
     // All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points.
     static const SkScalar kSqrtOfOneAndAQuarter = SkFloatToScalar(1.118f);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 5eee243..b0d34fd 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -25,7 +25,6 @@
 #include "GrSoftwarePathRenderer.h"
 #include "GrStencilBuffer.h"
 #include "GrTextStrike.h"
-#include "SkDrawProcs.h"
 #include "SkRTConf.h"
 #include "SkRRect.h"
 #include "SkStrokeRec.h"
@@ -44,6 +43,10 @@
 
 #define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw)
 
+// When we're using coverage AA but the blend is incompatible (given gpu
+// limitations) should we disable AA or draw wrong?
+#define DISABLE_COVERAGE_AA_FOR_BLEND 1
+
 #ifdef SK_DEBUG
     // change this to a 1 to see notifications when partial coverage fails
     #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
@@ -692,6 +695,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+namespace {
+inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
+    return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 /*  create a triangle strip that strokes the specified triangle. There are 8
  unique vertices, but we repreat the last 2 to close up. Alternatively we
  could use an indices array, and then only send 8 verts, but not sure that
@@ -735,7 +746,7 @@
     // TODO: remove this ugliness when we drop the fixed-pipe impl
     *useVertexCoverage = false;
     if (!target->getDrawState().canTweakAlphaForCoverage()) {
-        if (target->shouldDisableCoverageAAForBlend()) {
+        if (disable_coverage_aa_for_blend(target)) {
 #ifdef SK_DEBUG
             //GrPrintf("Turning off AA to correctly apply blend.\n");
 #endif
@@ -1023,10 +1034,14 @@
     AutoCheckFlush acf(this);
     GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
-    if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
+    bool useAA = paint.isAntiAlias() &&
+                 !target->getDrawState().getRenderTarget()->isMultisampled() &&
+                 !disable_coverage_aa_for_blend(target);
+
+    if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) {
         SkPath path;
         path.addRRect(rect);
-        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+        this->internalDrawPath(target, useAA, path, stroke);
     }
 }
 
@@ -1043,10 +1058,14 @@
     AutoCheckFlush acf(this);
     GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
 
-    if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) {
+    bool useAA = paint.isAntiAlias() &&
+                 !target->getDrawState().getRenderTarget()->isMultisampled() &&
+                 !disable_coverage_aa_for_blend(target);
+
+    if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) {
         SkPath path;
         path.addOval(oval);
-        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+        this->internalDrawPath(target, useAA, path, stroke);
     }
 }
 
@@ -1072,7 +1091,7 @@
 
     *useVertexCoverage = false;
     if (!target->getDrawState().canTweakAlphaForCoverage()) {
-        if (target->shouldDisableCoverageAAForBlend()) {
+        if (disable_coverage_aa_for_blend(target)) {
             return false;
         } else {
             *useVertexCoverage = true;
@@ -1122,17 +1141,15 @@
     AutoRestoreEffects are;
     AutoCheckFlush acf(this);
     GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
-    GrDrawState* drawState = target->drawState();
 
-    bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
-
-    if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
+    bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
+    if (useAA && stroke.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, stroke, rects, &useVertexCoverage)) {
-            SkMatrix origViewMatrix = drawState->getViewMatrix();
+            SkMatrix origViewMatrix = target->getDrawState().getViewMatrix();
             GrDrawState::AutoViewMatrixRestore avmr;
             if (!avmr.setIdentity(target->drawState())) {
                 return;
@@ -1150,73 +1167,42 @@
     bool isOval = path.isOval(&ovalRect);
 
     if (!isOval || path.isInverseFillType()
-        || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
-        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
+        || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) {
+        this->internalDrawPath(target, useAA, path, stroke);
     }
 }
 
-namespace {
-// See also: SkDrawTreatAsHairline.
-static inline bool should_convert_to_hairline(bool useAA, const SkStrokeRec& stroke,
-                                              const SkMatrix& matrix, SkScalar* coverage) {
-
-    if (stroke.getStyle() != SkStrokeRec::kStroke_Style) {
-        return false;
-    }
-
-    SkASSERT(0 != stroke.getWidth());
-
-    if (!useAA) {
-        return false;
-    }
-
-    return SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, coverage);
-}
-}
-
-
-void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
-                                 const SkPath& path, const SkStrokeRec& origStroke) {
+void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
+                                 const SkStrokeRec& stroke) {
     SkASSERT(!path.isEmpty());
 
     // An Assumption here is that path renderer would use some form of tweaking
     // the src color (either the input alpha or in the frag shader) to implement
     // aa. If we have some future driver-mojo path AA that can do the right
     // thing WRT to the blend then we'll need some query on the PR.
-    bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
-
-    SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
-    // Can we treat a thin stroke as a hairline w/ coverage? If we can, we draw lots faster (raster
-    // device does this same test).
-
-    // Do not do this if gpu supports path rendering natively and we might be using the support
-    // (useCoverageAA == false). Hairline renderer is likely to be slow due to program switches.
-    if (!useCoverageAA || !fGpu->caps()->pathRenderingSupport()) {
-        SkScalar hairlineCoverage;
-        if (should_convert_to_hairline(useAA, *stroke, this->getMatrix(), &hairlineCoverage)) {
-            target->drawState()->setCoverage(SkScalarRoundToInt(hairlineCoverage * target->getDrawState().getCoverage()));
-            stroke.writable()->setHairlineStyle();
-        }
+    if (disable_coverage_aa_for_blend(target)) {
+#ifdef SK_DEBUG
+        //GrPrintf("Turning off AA to correctly apply blend.\n");
+#endif
+        useAA = false;
     }
 
-    GrPathRendererChain::DrawType type =
-        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
-                           GrPathRendererChain::kColor_DrawType;
+    GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
+                                                 GrPathRendererChain::kColor_DrawType;
 
     const SkPath* pathPtr = &path;
     SkPath tmpPath;
+    SkStrokeRec strokeRec(stroke);
 
     // Try a 1st time without stroking the path and without allowing the SW renderer
-    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
+    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
 
     if (NULL == pr) {
-        if (!stroke->isHairlineStyle()) {
+        if (!strokeRec.isHairlineStyle()) {
             // It didn't work the 1st time, so try again with the stroked path
-            if (stroke->applyToPath(&tmpPath, *pathPtr)) {
+            if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
                 pathPtr = &tmpPath;
-                stroke.writable()->setFillStyle();
+                strokeRec.setFillStyle();
             }
         }
         if (pathPtr->isEmpty()) {
@@ -1224,7 +1210,7 @@
         }
 
         // This time, allow SW renderer
-        pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
+        pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
     }
 
     if (NULL == pr) {
@@ -1234,7 +1220,7 @@
         return;
     }
 
-    pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
+    pr->drawPath(*pathPtr, strokeRec, target, useAA);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 1bbcc26..1743604 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -54,6 +54,7 @@
     this->enableState(GrDrawState::kClip_StateBit);
 
     this->setColor(paint.getColor());
+    this->setCoverage4(paint.getCoverage());
     this->setState(GrDrawState::kDither_StateBit, paint.isDither());
     this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
 
@@ -219,7 +220,7 @@
 
     // Check whether coverage is treated as color. If so we run through the coverage computation.
     if (this->isCoverageDrawing()) {
-        GrColor coverageColor = this->getCoverageColor();
+        GrColor coverageColor = this->getCoverage();
         GrColor oldColor = color;
         color = 0;
         for (int c = 0; c < 4; ++c) {
@@ -311,7 +312,7 @@
 
     bool covIsZero = !this->isCoverageDrawing() &&
                      !this->hasCoverageVertexAttribute() &&
-                     0 == this->getCoverageColor();
+                     0 == this->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.
@@ -326,7 +327,7 @@
 
     // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
     bool hasCoverage = forceCoverage ||
-                       0xffffffff != this->getCoverageColor() ||
+                       0xffffffff != this->getCoverage() ||
                        this->hasCoverageVertexAttribute() ||
                        fCoverageStages.count() > 0;
 
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 3de0b12..2e4d7f8 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -311,11 +311,15 @@
         fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
     }
 
-    uint8_t getCoverage() const {
-        return GrColorUnpackR(fCommon.fCoverage);
+    /**
+     * Version of above that specifies 4 channel per-vertex color. The value
+     * should be premultiplied.
+     */
+    void setCoverage4(GrColor coverage) {
+        fCommon.fCoverage = coverage;
     }
 
-    GrColor getCoverageColor() const {
+    GrColor getCoverage() const {
         return fCommon.fCoverage;
     }
 
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index c505869..266dc07 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -100,15 +100,6 @@
      */
     bool canApplyCoverage() const;
 
-    /** When we're using coverage AA but the blend is incompatible (given gpu
-     * limitations) we should disable AA. */
-    bool shouldDisableCoverageAAForBlend() {
-        // Enable below if we should draw with AA even when it produces
-        // incorrect blending.
-        // return false;
-        return !this->canApplyCoverage();
-    }
-
     /**
      * Given the current draw state and hw support, will HW AA lines be used (if
      * a line primitive type is drawn)?
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index 8f078db..aeeb85d 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -460,11 +460,7 @@
 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
                               const SkRect& oval, const SkStrokeRec& stroke)
 {
-    bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
-
-    if (!useCoverageAA) {
+    if (!useAA) {
         return false;
     }
 
@@ -473,13 +469,13 @@
     // we can draw circles
     if (SkScalarNearlyEqual(oval.width(), oval.height())
         && circle_stays_circle(vm)) {
-        this->drawCircle(target, useCoverageAA, oval, stroke);
+        this->drawCircle(target, useAA, oval, stroke);
     // if we have shader derivative support, render as device-independent
     } else if (target->caps()->shaderDerivativeSupport()) {
-        return this->drawDIEllipse(target, useCoverageAA, oval, stroke);
+        return this->drawDIEllipse(target, useAA, oval, stroke);
     // otherwise axis-aligned ellipses only
     } else if (vm.rectStaysRect()) {
-        return this->drawEllipse(target, useCoverageAA, oval, stroke);
+        return this->drawEllipse(target, useAA, oval, stroke);
     } else {
         return false;
     }
@@ -496,7 +492,7 @@
 };
 
 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
-                                bool useCoverageAA,
+                                bool useAA,
                                 const SkRect& circle,
                                 const SkStrokeRec& stroke)
 {
@@ -601,7 +597,7 @@
 };
 
 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
-                                 bool useCoverageAA,
+                                 bool useAA,
                                  const SkRect& ellipse,
                                  const SkStrokeRec& stroke)
 {
@@ -610,7 +606,7 @@
     {
         // we should have checked for this previously
         bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
-        SkASSERT(useCoverageAA && isAxisAlignedEllipse);
+        SkASSERT(useAA && isAxisAlignedEllipse);
     }
 #endif
 
@@ -733,7 +729,7 @@
 }
 
 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
-                                   bool useCoverageAA,
+                                   bool useAA,
                                    const SkRect& ellipse,
                                    const SkStrokeRec& stroke)
 {
@@ -886,12 +882,8 @@
 bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
                                      const SkRRect& rrect, const SkStrokeRec& stroke)
 {
-    bool useCoverageAA = useAA &&
-        !target->getDrawState().getRenderTarget()->isMultisampled() &&
-        !target->shouldDisableCoverageAAForBlend();
-
     // only anti-aliased rrects for now
-    if (!useCoverageAA) {
+    if (!useAA) {
         return false;
     }
 
@@ -899,7 +891,7 @@
 #ifdef SK_DEBUG
     {
         // we should have checked for this previously
-        SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple());
+        SkASSERT(useAA && vm.rectStaysRect() && rrect.isSimple());
     }
 #endif
 
diff --git a/src/gpu/GrOvalRenderer.h b/src/gpu/GrOvalRenderer.h
index 9653fcc..b58abb7 100644
--- a/src/gpu/GrOvalRenderer.h
+++ b/src/gpu/GrOvalRenderer.h
@@ -37,13 +37,13 @@
                          const SkRRect& rrect, const SkStrokeRec& stroke);
 
 private:
-    bool drawEllipse(GrDrawTarget* target, bool useCoverageAA,
+    bool drawEllipse(GrDrawTarget* target, bool useAA,
                      const SkRect& ellipse,
                      const SkStrokeRec& stroke);
-    bool drawDIEllipse(GrDrawTarget* target, bool useCoverageAA,
+    bool drawDIEllipse(GrDrawTarget* target, bool useAA,
                        const SkRect& ellipse,
                        const SkStrokeRec& stroke);
-    void drawCircle(GrDrawTarget* target, bool useCoverageAA,
+    void drawCircle(GrDrawTarget* target, bool useAA,
                     const SkRect& circle,
                     const SkStrokeRec& stroke);
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 52dc5a7..ca86b84 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -12,8 +12,7 @@
 
 #include "GrContext.h"
 #include "GrBitmapTextContext.h"
-#include "GrGpu.h"
-#include "GrDrawTargetCaps.h"
+
 #include "SkGrTexturePixelRef.h"
 
 #include "SkColorFilter.h"
@@ -851,6 +850,14 @@
         return;
     }
 
+    // can we cheat, and treat a thin stroke as a hairline w/ coverage
+    // if we can, we draw lots faster (raster device does this same test)
+    SkScalar hairlineCoverage;
+    bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage);
+    if (doHairLine) {
+        grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
+    }
+
     // If we have a prematrix, apply it to the path, optimizing for the case
     // where the original path can in fact be modified in place (even though
     // its parameter type is const).
@@ -880,6 +887,10 @@
         pathPtr = &effectPath;
     }
 
+    if (!pathEffect && doHairLine) {
+        stroke.setHairlineStyle();
+    }
+
     if (paint.getMaskFilter()) {
         if (!stroke.isHairlineStyle()) {
             if (stroke.applyToPath(&tmpPath, *pathPtr)) {
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 5b030fa..accaf88 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -207,10 +207,10 @@
         coverage = 0;
     } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
         color = 0xffffffff;
-        coverage = drawState.getCoverageColor();
+        coverage = drawState.getCoverage();
     } else {
         color = drawState.getColor();
-        coverage = drawState.getCoverageColor();
+        coverage = drawState.getCoverage();
     }
 
     this->setColor(drawState, color, sharedState);
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 6e9d8a4..d958742 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -156,7 +156,7 @@
         header->fHasVertexCode = true;
     }
 
-    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
+    bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
 
     if (skipCoverage) {
         header->fCoverageInput = kTransBlack_ColorInput;