Extract gpu line dashing to GrDashLinePathRenderer

Move line dashing logic from GrContext::drawPath to
GrDashLinePathRenderer. This makes it possible to let path renderers render arbitrary dashed paths.

End goal is to implement dashing in GrStencilAndCoverPathRenderer.

Review URL: https://codereview.chromium.org/1100073003
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 1813803..def69a0 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -18,9 +18,9 @@
 #include "GrPathUtils.h"
 #include "GrProcessor.h"
 #include "GrPipelineBuilder.h"
+#include "GrStrokeInfo.h"
 #include "SkGeometry.h"
 #include "SkString.h"
-#include "SkStrokeRec.h"
 #include "SkTraceEvent.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
@@ -682,7 +682,7 @@
                                          const GrPipelineBuilder*,
                                          const SkMatrix& viewMatrix,
                                          const SkPath& path,
-                                         const SkStrokeRec& stroke,
+                                         const GrStrokeInfo& stroke,
                                          bool antiAlias) const {
     return (target->caps()->shaderDerivativeSupport() && antiAlias &&
             stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
@@ -869,7 +869,7 @@
                                         GrColor color,
                                         const SkMatrix& vm,
                                         const SkPath& path,
-                                        const SkStrokeRec&,
+                                        const GrStrokeInfo&,
                                         bool antiAlias) {
     if (path.isEmpty()) {
         return true;
diff --git a/src/gpu/GrAAConvexPathRenderer.h b/src/gpu/GrAAConvexPathRenderer.h
index 816ccd6..3abf1ab 100644
--- a/src/gpu/GrAAConvexPathRenderer.h
+++ b/src/gpu/GrAAConvexPathRenderer.h
@@ -19,7 +19,7 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 
 protected:
@@ -28,7 +28,7 @@
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 };
 
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.cpp b/src/gpu/GrAADistanceFieldPathRenderer.cpp
index 510ea0e..95aa3aa 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.cpp
+++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp
@@ -86,13 +86,13 @@
                                                 const GrPipelineBuilder* pipelineBuilder,
                                                 const SkMatrix& viewMatrix,
                                                 const SkPath& path,
-                                                const SkStrokeRec& stroke,
+                                                const GrStrokeInfo& stroke,
                                                 bool antiAlias) const {
     
     // TODO: Support inverse fill
     // TODO: Support strokes
     if (!target->caps()->shaderDerivativeSupport() || !antiAlias || path.isInverseFillType()
-        || path.isVolatile() || SkStrokeRec::kFill_Style != stroke.getStyle()) {
+        || path.isVolatile() || !stroke.isFillStyle()) {
         return false;
     }
 
@@ -114,7 +114,7 @@
 GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*,
                                                    const GrPipelineBuilder*,
                                                    const SkPath&,
-                                                   const SkStrokeRec&) const {
+                                                   const GrStrokeInfo&) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
 
@@ -570,7 +570,7 @@
                                                GrColor color,
                                                const SkMatrix& viewMatrix,
                                                const SkPath& path,
-                                               const SkStrokeRec& stroke,
+                                               const GrStrokeInfo& stroke,
                                                bool antiAlias) {
     // we've already bailed on inverse filled paths, so this is safe
     if (path.isEmpty()) {
@@ -600,7 +600,7 @@
                                          (void*)this);
     }
 
-    AADistanceFieldPathBatch::Geometry geometry(stroke);
+    AADistanceFieldPathBatch::Geometry geometry(stroke.getStrokeRec());
     geometry.fPath = path;
     geometry.fAntiAlias = antiAlias;
 
diff --git a/src/gpu/GrAADistanceFieldPathRenderer.h b/src/gpu/GrAADistanceFieldPathRenderer.h
index ad296f0..6cbee1f 100755
--- a/src/gpu/GrAADistanceFieldPathRenderer.h
+++ b/src/gpu/GrAADistanceFieldPathRenderer.h
@@ -27,21 +27,21 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 
 protected:
     virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                                const GrPipelineBuilder*,
                                                const SkPath&,
-                                               const SkStrokeRec&) const override;
+                                               const GrStrokeInfo&) const override;
     
     virtual bool onDrawPath(GrDrawTarget*,
                             GrPipelineBuilder*,
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 
 private:
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 1cbd93b..a9bc9f2 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -637,7 +637,7 @@
                                            const GrPipelineBuilder* pipelineBuilder,
                                            const SkMatrix& viewMatrix,
                                            const SkPath& path,
-                                           const SkStrokeRec& stroke,
+                                           const GrStrokeInfo& stroke,
                                            bool antiAlias) const {
     if (!antiAlias) {
         return false;
@@ -1029,7 +1029,7 @@
                                           GrColor color,
                                           const SkMatrix& viewMatrix,
                                           const SkPath& path,
-                                          const SkStrokeRec& stroke,
+                                          const GrStrokeInfo& stroke,
                                           bool) {
     if (!fLinesIndexBuffer || !fQuadsIndexBuffer) {
         SkDebugf("unable to allocate indices\n");
diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h
index 4a24b8d..9f8d8aa 100644
--- a/src/gpu/GrAAHairLinePathRenderer.h
+++ b/src/gpu/GrAAHairLinePathRenderer.h
@@ -21,7 +21,7 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 
     typedef SkTArray<SkPoint, true> PtArray;
@@ -34,7 +34,7 @@
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 
 private:
diff --git a/src/gpu/GrAddPathRenderers_default.cpp b/src/gpu/GrAddPathRenderers_default.cpp
index e60d536..06e98a9 100644
--- a/src/gpu/GrAddPathRenderers_default.cpp
+++ b/src/gpu/GrAddPathRenderers_default.cpp
@@ -11,6 +11,7 @@
 #include "GrAAHairLinePathRenderer.h"
 #include "GrAAConvexPathRenderer.h"
 #include "GrAADistanceFieldPathRenderer.h"
+#include "GrDashLinePathRenderer.h"
 #include "GrTessellatingPathRenderer.h"
 #if GR_STROKE_PATH_RENDERING
 #include "../../experimental/StrokePathRenderer/GrStrokePathRenderer.h"
@@ -24,6 +25,8 @@
 #endif
 
 void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
+    chain->addPathRenderer(SkNEW_ARGS(GrDashLinePathRenderer, (ctx)))->unref();
+
 #if GR_STROKE_PATH_RENDERING
     chain->addPathRenderer(SkNEW(GrStrokePathRenderer))->unref();
 #endif
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 078895d..439733b 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -17,7 +17,6 @@
 #include "GrStencilAttachment.h"
 #include "GrSWMaskHelper.h"
 #include "SkRasterClip.h"
-#include "SkStrokeRec.h"
 #include "SkTLazy.h"
 #include "effects/GrConvexPolyEffect.h"
 #include "effects/GrPorterDuffXferProcessor.h"
@@ -60,7 +59,7 @@
                             const GrPipelineBuilder* pipelineBuilder,
                             const SkMatrix& viewMatrix,
                             const SkPath& origPath,
-                            const SkStrokeRec& stroke,
+                            const GrStrokeInfo& stroke,
                             bool doAA) {
     // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
     SkTCopyOnFirstWrite<SkPath> path(origPath);
@@ -88,7 +87,7 @@
     // 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.
-    SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+    GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
 
     // Set the matrix so that rendered clip elements are transformed to mask space from clip
     // space.
@@ -413,7 +412,7 @@
             if (path.isInverseFillType()) {
                 path.toggleInverseFillType();
             }
-            SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+            GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
             if (NULL == pr) {
                 GrPathRendererChain::DrawType type;
                 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
@@ -449,7 +448,7 @@
         if (path.isInverseFillType()) {
             path.toggleInverseFillType();
         }
-        SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+        GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
         GrPathRendererChain::DrawType type = element->isAA() ?
             GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
             GrPathRendererChain::kStencilAndColor_DrawType;
@@ -758,7 +757,7 @@
             // stencil with arbitrary stencil settings.
             GrPathRenderer::StencilSupport stencilSupport;
 
-            SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+            GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
             SkRegion::Op op = element->getOp();
 
             GrPathRenderer* pr = NULL;
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 43ac464..743377d 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1343,35 +1343,6 @@
     }
 
     GrColor color = paint.getColor();
-    if (strokeInfo.isDashed()) {
-        SkPoint pts[2];
-        if (path.isLine(pts)) {
-            AutoCheckFlush acf(this);
-            GrPipelineBuilder pipelineBuilder;
-            GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
-            if (NULL == target) {
-                return;
-            }
-
-            if (GrDashingEffect::DrawDashLine(fGpu, target, &pipelineBuilder, color, viewMatrix,
-                                              pts, paint, strokeInfo)) {
-                return;
-            }
-        }
-
-        // Filter dashed path into new path with the dashing applied
-        const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
-        SkTLazy<SkPath> effectPath;
-        GrStrokeInfo newStrokeInfo(strokeInfo, false);
-        SkStrokeRec* stroke = newStrokeInfo.getStrokeRecPtr();
-        if (SkDashPath::FilterDashPath(effectPath.init(), path, stroke, NULL, info)) {
-            this->drawPath(rt, clip, paint, viewMatrix, *effectPath.get(), newStrokeInfo);
-            return;
-        }
-
-        this->drawPath(rt, clip, paint, viewMatrix, path, newStrokeInfo);
-        return;
-    }
 
     // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
     // Scratch textures can be recycled after they are returned to the texture
@@ -1387,35 +1358,39 @@
 
     GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex());
 
-    const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+    if (!strokeInfo.isDashed()) {
+        const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
+        bool useCoverageAA = paint.isAntiAlias() &&
+                !pipelineBuilder.getRenderTarget()->isMultisampled();
 
-    bool useCoverageAA = paint.isAntiAlias() &&
-        !pipelineBuilder.getRenderTarget()->isMultisampled();
+        if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
+            // Concave AA paths are expensive - try to avoid them for special cases
+            SkRect rects[2];
 
-    if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
-        // Concave AA paths are expensive - try to avoid them for special cases
-        SkRect rects[2];
+            if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeRec,
+                                rects)) {
+                fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix,
+                                                   rects);
+                return;
+            }
+        }
+        SkRect ovalRect;
+        bool isOval = path.isOval(&ovalRect);
 
-        if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeRec, rects)) {
-            fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix, rects);
-            return;
+        if (isOval && !path.isInverseFillType()) {
+            if (fOvalRenderer->drawOval(target,
+                                        &pipelineBuilder,
+                                        color,
+                                        viewMatrix,
+                                        paint.isAntiAlias(),
+                                        ovalRect,
+                                        strokeRec)) {
+                return;
+            }
         }
     }
-
-    SkRect ovalRect;
-    bool isOval = path.isOval(&ovalRect);
-
-    if (!isOval || path.isInverseFillType() ||
-        !fOvalRenderer->drawOval(target,
-                                 &pipelineBuilder,
-                                 color,
-                                 viewMatrix,
-                                 paint.isAntiAlias(),
-                                 ovalRect,
-                                 strokeRec)) {
-        this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
-                               path, strokeInfo);
-    }
+    this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
+                           path, strokeInfo);
 }
 
 void GrContext::internalDrawPath(GrDrawTarget* target,
@@ -1445,28 +1420,47 @@
 
     const SkPath* pathPtr = &path;
     SkTLazy<SkPath> tmpPath;
-    SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec());
+    const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
 
     // Try a 1st time without stroking the path and without allowing the SW renderer
     GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr,
-                                               *stroke, false, type);
+                                               *strokeInfoPtr, false, type);
+
+    GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
+    if (NULL == pr && strokeInfo.isDashed()) {
+        // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
+        if (strokeInfo.applyDash(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
+            pathPtr = tmpPath.get();
+            if (pathPtr->isEmpty()) {
+                return;
+            }
+            strokeInfoPtr = &dashlessStrokeInfo;
+        }
+        pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
+                                   false, type);
+    }
 
     if (NULL == pr) {
-        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, NULL)) {
-            // It didn't work the 1st time, so try again with the stroked path
-            stroke.writable()->setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
-            if (stroke->applyToPath(tmpPath.init(), *pathPtr)) {
+        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, NULL)) {
+            // It didn't work above, so try again with stroke converted to a fill.
+            if (!tmpPath.isValid()) {
+                tmpPath.init();
+            }
+            SkStrokeRec* strokeRec = dashlessStrokeInfo.getStrokeRecPtr();
+            strokeRec->setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
+            if (strokeRec->applyToPath(tmpPath.get(), *pathPtr)) {
                 pathPtr = tmpPath.get();
-                stroke.writable()->setFillStyle();
                 if (pathPtr->isEmpty()) {
                     return;
                 }
+                strokeRec->setFillStyle();
+                strokeInfoPtr = &dashlessStrokeInfo;
             }
         }
 
         // This time, allow SW renderer
-        pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *stroke, true,
-                                   type);
+        pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
+                                   true, type);
     }
 
     if (NULL == pr) {
@@ -1476,7 +1470,7 @@
         return;
     }
 
-    pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *stroke, useCoverageAA);
+    pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1873,7 +1867,7 @@
                                            const GrPipelineBuilder* pipelineBuilder,
                                            const SkMatrix& viewMatrix,
                                            const SkPath& path,
-                                           const SkStrokeRec& stroke,
+                                           const GrStrokeInfo& stroke,
                                            bool allowSW,
                                            GrPathRendererChain::DrawType drawType,
                                            GrPathRendererChain::StencilSupport* stencilSupport) {
diff --git a/src/gpu/GrDashLinePathRenderer.cpp b/src/gpu/GrDashLinePathRenderer.cpp
new file mode 100644
index 0000000..bd49a72
--- /dev/null
+++ b/src/gpu/GrDashLinePathRenderer.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDashLinePathRenderer.h"
+
+#include "GrGpu.h"
+#include "effects/GrDashingEffect.h"
+
+GrDashLinePathRenderer::GrDashLinePathRenderer(GrContext* context)
+        : fGpu(SkRef(context->getGpu())) {
+}
+
+GrDashLinePathRenderer::~GrDashLinePathRenderer() {
+}
+
+bool GrDashLinePathRenderer::canDrawPath(const GrDrawTarget* target,
+                                         const GrPipelineBuilder* pipelineBuilder,
+                                         const SkMatrix& viewMatrix,
+                                         const SkPath& path,
+                                         const GrStrokeInfo& stroke,
+                                         bool antiAlias) const {
+    SkPoint pts[2];
+    if (stroke.isDashed() && path.isLine(pts)) {
+        return GrDashingEffect::CanDrawDashLine(pts, stroke, viewMatrix);
+    }
+    return false;
+}
+
+bool GrDashLinePathRenderer::onDrawPath(GrDrawTarget* target,
+                                        GrPipelineBuilder* pipelineBuilder,
+                                        GrColor color,
+                                        const SkMatrix& viewMatrix,
+                                        const SkPath& path,
+                                        const GrStrokeInfo& stroke,
+                                        bool useAA) {
+    SkPoint pts[2];
+    SkAssertResult(path.isLine(pts));
+    return GrDashingEffect::DrawDashLine(fGpu, target, pipelineBuilder, color,
+                                         viewMatrix, pts, useAA, stroke);
+}
diff --git a/src/gpu/GrDashLinePathRenderer.h b/src/gpu/GrDashLinePathRenderer.h
new file mode 100644
index 0000000..632f30a
--- /dev/null
+++ b/src/gpu/GrDashLinePathRenderer.h
@@ -0,0 +1,46 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDashLinePathRenderer_DEFINED
+#define GrDashLinePathRenderer_DEFINED
+
+#include "GrPathRenderer.h"
+
+class GrDashLinePathRenderer : public GrPathRenderer {
+public:
+    GrDashLinePathRenderer(GrContext*);
+    ~GrDashLinePathRenderer();
+
+    bool canDrawPath(const GrDrawTarget*,
+                     const GrPipelineBuilder*,
+                     const SkMatrix& viewMatrix,
+                     const SkPath&,
+                     const GrStrokeInfo&,
+                     bool antiAlias) const override;
+
+protected:
+    StencilSupport onGetStencilSupport(const GrDrawTarget*,
+                                       const GrPipelineBuilder*,
+                                       const SkPath&,
+                                       const GrStrokeInfo&) const override {
+      return kNoSupport_StencilSupport;
+    }
+
+    bool onDrawPath(GrDrawTarget*,
+                    GrPipelineBuilder*,
+                    GrColor,
+                    const SkMatrix& viewMatrix,
+                    const SkPath&,
+                    const GrStrokeInfo&,
+                    bool antiAlias) override;
+    SkAutoTUnref<GrGpu> fGpu;
+    typedef GrPathRenderer INHERITED;
+};
+
+
+#endif
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index 65daa7c..88834bb 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -170,8 +170,8 @@
 GrDefaultPathRenderer::onGetStencilSupport(const GrDrawTarget*,
                                            const GrPipelineBuilder*,
                                            const SkPath& path,
-                                           const SkStrokeRec& stroke) const {
-    if (single_pass_path(path, stroke)) {
+                                           const GrStrokeInfo& stroke) const {
+    if (single_pass_path(path, stroke.getStrokeRec())) {
         return GrPathRenderer::kNoRestriction_StencilSupport;
     } else {
         return GrPathRenderer::kStencilOnly_StencilSupport;
@@ -545,21 +545,21 @@
                                              GrColor color,
                                              const SkMatrix& viewMatrix,
                                              const SkPath& path,
-                                             const SkStrokeRec& origStroke,
+                                             const GrStrokeInfo& origStroke,
                                              bool stencilOnly) {
-    SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
+    SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke);
 
     SkScalar hairlineCoverage;
     uint8_t newCoverage = 0xff;
     if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) {
         newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff);
 
-        if (!stroke->isHairlineStyle()) {
-            stroke.writable()->setHairlineStyle();
+        if (!stroke->getStrokeRec().isHairlineStyle()) {
+            stroke.writable()->getStrokeRecPtr()->setHairlineStyle();
         }
     }
 
-    const bool isHairline = stroke->isHairlineStyle();
+    const bool isHairline = stroke->getStrokeRec().isHairlineStyle();
 
     // Save the current xp on the draw state so we can reset it if needed
     SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXPFactory()));
@@ -582,7 +582,7 @@
         lastPassIsBounds = false;
         drawFace[0] = GrPipelineBuilder::kBoth_DrawFace;
     } else {
-        if (single_pass_path(path, *stroke)) {
+        if (single_pass_path(path, stroke->getStrokeRec())) {
             passCount = 1;
             if (stencilOnly) {
                 passes[0] = &gDirectToStencil;
@@ -719,7 +719,7 @@
                                         const GrPipelineBuilder* pipelineBuilder,
                                         const SkMatrix& viewMatrix,
                                         const SkPath& path,
-                                        const SkStrokeRec& stroke,
+                                        const GrStrokeInfo& stroke,
                                         bool antiAlias) const {
     // this class can draw any path with any fill but doesn't do any anti-aliasing.
     return !antiAlias && (stroke.isFillStyle() || IsStrokeHairlineOrEquivalent(stroke,
@@ -732,7 +732,7 @@
                                        GrColor color,
                                        const SkMatrix& viewMatrix,
                                        const SkPath& path,
-                                       const SkStrokeRec& stroke,
+                                       const GrStrokeInfo& stroke,
                                        bool antiAlias) {
     return this->internalDrawPath(target,
                                   pipelineBuilder,
@@ -747,7 +747,7 @@
                                           GrPipelineBuilder* pipelineBuilder,
                                           const SkMatrix& viewMatrix,
                                           const SkPath& path,
-                                          const SkStrokeRec& stroke) {
+                                          const GrStrokeInfo& stroke) {
     SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType());
     SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType());
     this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, path, stroke, true);
diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h
index ab2a66b..008eac2 100644
--- a/src/gpu/GrDefaultPathRenderer.h
+++ b/src/gpu/GrDefaultPathRenderer.h
@@ -23,7 +23,7 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 
 private:
@@ -31,28 +31,28 @@
     virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                                const GrPipelineBuilder*,
                                                const SkPath&,
-                                               const SkStrokeRec&) const override;
+                                               const GrStrokeInfo&) const override;
 
     virtual bool onDrawPath(GrDrawTarget*,
                             GrPipelineBuilder*,
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 
     virtual void onStencilPath(GrDrawTarget*,
                                GrPipelineBuilder*,
                                const SkMatrix& viewMatrix,
                                const SkPath&,
-                               const SkStrokeRec&) override;
+                               const GrStrokeInfo&) override;
 
     bool internalDrawPath(GrDrawTarget*,
                           GrPipelineBuilder*,
                           GrColor,
                           const SkMatrix& viewMatrix,
                           const SkPath&,
-                          const SkStrokeRec&,
+                          const GrStrokeInfo&,
                           bool stencilOnly);
 
     bool    fSeparateStencil;
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index 5144597..a53d51d 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -12,9 +12,9 @@
 #include "GrDrawTarget.h"
 #include "GrPathRendererChain.h"
 #include "GrStencil.h"
+#include "GrStrokeInfo.h"
 
 #include "SkDrawProcs.h"
-#include "SkStrokeRec.h"
 #include "SkTArray.h"
 
 class SkPath;
@@ -84,7 +84,7 @@
     StencilSupport getStencilSupport(const GrDrawTarget* target,
                                      const GrPipelineBuilder* pipelineBuilder,
                                      const SkPath& path,
-                                     const SkStrokeRec& stroke) const {
+                                     const GrStrokeInfo& stroke) const {
         SkASSERT(!path.isInverseFillType());
         return this->onGetStencilSupport(target, pipelineBuilder, path, stroke);
     }
@@ -107,7 +107,7 @@
                              const GrPipelineBuilder* pipelineBuilder,
                              const SkMatrix& viewMatrix,
                              const SkPath& path,
-                             const SkStrokeRec& rec,
+                             const GrStrokeInfo& rec,
                              bool antiAlias) const = 0;
     /**
      * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
@@ -125,7 +125,7 @@
                   GrColor color,
                   const SkMatrix& viewMatrix,
                   const SkPath& path,
-                  const SkStrokeRec& stroke,
+                  const GrStrokeInfo& stroke,
                   bool antiAlias) {
         SkASSERT(!path.isEmpty());
         SkASSERT(this->canDrawPath(target, ds, viewMatrix, path, stroke, antiAlias));
@@ -147,7 +147,7 @@
                      GrPipelineBuilder* ds,
                      const SkMatrix& viewMatrix,
                      const SkPath& path,
-                     const SkStrokeRec& stroke) {
+                     const GrStrokeInfo& stroke) {
         SkASSERT(!path.isEmpty());
         SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(target, ds, path, stroke));
         this->onStencilPath(target, ds, viewMatrix, path, stroke);
@@ -155,16 +155,19 @@
 
     // Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
     // If we can, we draw lots faster (raster device does this same test).
-    static bool IsStrokeHairlineOrEquivalent(const SkStrokeRec& stroke, const SkMatrix& matrix,
+    static bool IsStrokeHairlineOrEquivalent(const GrStrokeInfo& stroke, const SkMatrix& matrix,
                                              SkScalar* outCoverage) {
-        if (stroke.isHairlineStyle()) {
+        if (stroke.isDashed()) {
+            return false;
+        }
+        if (stroke.getStrokeRec().isHairlineStyle()) {
             if (outCoverage) {
                 *outCoverage = SK_Scalar1;
             }
             return true;
         }
-        return stroke.getStyle() == SkStrokeRec::kStroke_Style &&
-            SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage);
+        return stroke.getStrokeRec().getStyle() == SkStrokeRec::kStroke_Style &&
+            SkDrawTreatAAStrokeAsHairline(stroke.getStrokeRec().getWidth(), matrix, outCoverage);
     }
 
 protected:
@@ -174,7 +177,7 @@
     virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                                const GrPipelineBuilder*,
                                                const SkPath&,
-                                               const SkStrokeRec&) const {
+                                               const GrStrokeInfo&) const {
         return kNoRestriction_StencilSupport;
     }
 
@@ -186,7 +189,7 @@
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) = 0;
 
     /**
@@ -197,7 +200,7 @@
                                GrPipelineBuilder* pipelineBuilder,
                                const SkMatrix& viewMatrix,
                                const SkPath& path,
-                               const SkStrokeRec& stroke) {
+                               const GrStrokeInfo& stroke) {
         GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,
                                      kReplace_StencilOp,
                                      kReplace_StencilOp,
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index d11763b..915bdd2 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -35,7 +35,7 @@
                                                      const GrPipelineBuilder* pipelineBuilder,
                                                      const SkMatrix& viewMatrix,
                                                      const SkPath& path,
-                                                     const SkStrokeRec& stroke,
+                                                     const GrStrokeInfo& stroke,
                                                      DrawType drawType,
                                                      StencilSupport* stencilSupport) {
     if (!fInit) {
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 466ad81..0cc3de7 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -15,12 +15,14 @@
                                          const GrPipelineBuilder*,
                                          const SkMatrix& viewMatrix,
                                          const SkPath&,
-                                         const SkStrokeRec&,
+                                         const GrStrokeInfo& stroke,
                                          bool antiAlias) const {
     if (NULL == fContext) {
         return false;
     }
-
+    if (stroke.isDashed()) {
+        return false;
+    }
     return true;
 }
 
@@ -28,7 +30,7 @@
 GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*,
                                             const GrPipelineBuilder*,
                                             const SkPath&,
-                                            const SkStrokeRec&) const {
+                                            const GrStrokeInfo&) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
 
@@ -119,9 +121,8 @@
                                         GrColor color,
                                         const SkMatrix& viewMatrix,
                                         const SkPath& path,
-                                        const SkStrokeRec& stroke,
+                                        const GrStrokeInfo& stroke,
                                         bool antiAlias) {
-
     if (NULL == fContext) {
         return false;
     }
@@ -137,7 +138,7 @@
     }
 
     SkAutoTUnref<GrTexture> texture(
-            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
+            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke.getStrokeRec(),
                                                   devPathBounds,
                                                   antiAlias, &viewMatrix));
     if (NULL == texture) {
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index e7a5a28..6e2055a 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -27,20 +27,20 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 protected:
     virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                                const GrPipelineBuilder*,
                                                const SkPath&,
-                                               const SkStrokeRec&) const override;
+                                               const GrStrokeInfo&) const override;
 
     virtual bool onDrawPath(GrDrawTarget*,
                             GrPipelineBuilder*,
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 
 private:
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index aed1743..8451e63 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -14,7 +14,7 @@
 #include "GrPath.h"
 #include "GrRenderTarget.h"
 #include "GrRenderTargetPriv.h"
-#include "SkStrokeRec.h"
+#include "GrStrokeInfo.h"
 
 /*
  * For now paths only natively support winding and even odd fill types
@@ -56,18 +56,19 @@
                                                 const GrPipelineBuilder* pipelineBuilder,
                                                 const SkMatrix& viewMatrix,
                                                 const SkPath& path,
-                                                const SkStrokeRec& stroke,
+                                                const GrStrokeInfo& stroke,
                                                 bool antiAlias) const {
-    return !stroke.isHairlineStyle() &&
-           !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
-           pipelineBuilder->getStencil().isDisabled();
+    return !stroke.getStrokeRec().isHairlineStyle() &&
+        !stroke.isDashed() &&
+        !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
+        pipelineBuilder->getStencil().isDisabled();
 }
 
 GrPathRenderer::StencilSupport
 GrStencilAndCoverPathRenderer::onGetStencilSupport(const GrDrawTarget*,
                                                    const GrPipelineBuilder*,
                                                    const SkPath&,
-                                                   const SkStrokeRec&) const {
+                                                   const GrStrokeInfo&) const {
     return GrPathRenderer::kStencilOnly_StencilSupport;
 }
 
@@ -87,10 +88,10 @@
                                                   GrPipelineBuilder* pipelineBuilder,
                                                   const SkMatrix& viewMatrix,
                                                   const SkPath& path,
-                                                  const SkStrokeRec& stroke) {
+                                                  const GrStrokeInfo& stroke) {
     SkASSERT(!path.isInverseFillType());
     SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(GrColor_WHITE, viewMatrix));
-    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
+    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke.getStrokeRec()));
     target->stencilPath(pipelineBuilder, pp, p, convert_skpath_filltype(path.getFillType()));
 }
 
@@ -99,14 +100,14 @@
                                                GrColor color,
                                                const SkMatrix& viewMatrix,
                                                const SkPath& path,
-                                               const SkStrokeRec& stroke,
+                                               const GrStrokeInfo& stroke,
                                                bool antiAlias) {
     SkASSERT(!antiAlias);
-    SkASSERT(!stroke.isHairlineStyle());
-
+    SkASSERT(!stroke.getStrokeRec().isHairlineStyle());
+    SkASSERT(!stroke.isDashed());
     SkASSERT(pipelineBuilder->getStencil().isDisabled());
 
-    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke));
+    SkAutoTUnref<GrPath> p(get_gr_path(fGpu, path, stroke.getStrokeRec()));
 
     if (path.isInverseFillType()) {
         GR_STATIC_CONST_SAME_STENCIL(kInvertedStencilPass,
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h
index a28b6aa..7e3c005 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.h
+++ b/src/gpu/GrStencilAndCoverPathRenderer.h
@@ -29,28 +29,28 @@
                              const GrPipelineBuilder*,
                              const SkMatrix& viewMatrix,
                              const SkPath&,
-                             const SkStrokeRec&,
+                             const GrStrokeInfo&,
                              bool antiAlias) const override;
 
 protected:
     virtual StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                                const GrPipelineBuilder*,
                                                const SkPath&,
-                                               const SkStrokeRec&) const override;
+                                               const GrStrokeInfo&) const override;
 
     virtual bool onDrawPath(GrDrawTarget*,
                             GrPipelineBuilder*,
                             GrColor,
                             const SkMatrix& viewMatrix,
                             const SkPath&,
-                            const SkStrokeRec&,
+                            const GrStrokeInfo&,
                             bool antiAlias) override;
 
     virtual void onStencilPath(GrDrawTarget*,
                                GrPipelineBuilder*,
                                const SkMatrix& viewMatrix,
                                const SkPath&,
-                               const SkStrokeRec&) override;
+                               const GrStrokeInfo&) override;
 
 private:
     GrStencilAndCoverPathRenderer(GrGpu*);
diff --git a/src/gpu/GrStrokeInfo.cpp b/src/gpu/GrStrokeInfo.cpp
new file mode 100644
index 0000000..30f4b89
--- /dev/null
+++ b/src/gpu/GrStrokeInfo.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrStrokeInfo.h"
+
+#include "SkDashPathPriv.h"
+
+bool GrStrokeInfo::applyDash(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const {
+    if (this->isDashed()) {
+        const SkPathEffect::DashInfo& info = this->getDashInfo();
+        SkStrokeRec strokeRec = fStroke;
+        if (SkDashPath::FilterDashPath(dst, src, &strokeRec, NULL, info)) {
+            dstStrokeInfo->fStroke = strokeRec;
+            dstStrokeInfo->removeDash();
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/src/gpu/GrStrokeInfo.h b/src/gpu/GrStrokeInfo.h
index 2bd056e..dd942c5 100644
--- a/src/gpu/GrStrokeInfo.h
+++ b/src/gpu/GrStrokeInfo.h
@@ -44,6 +44,15 @@
         this->init(paint);
     }
 
+    GrStrokeInfo& operator=(const GrStrokeInfo& other) {
+        fStroke = other.fStroke;
+        fDashInfo = other.fDashInfo;
+        fDashType = other.fDashType;
+        fIntervals.reset(other.dashCount());
+        memcpy(fIntervals.get(), other.fIntervals.get(), other.dashCount() * sizeof(SkScalar));
+        return *this;
+    }
+
     const SkStrokeRec& getStrokeRec() const { return fStroke; }
 
     SkStrokeRec* getStrokeRecPtr() { return &fStroke; }
@@ -73,6 +82,8 @@
         return (!fStroke.isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
     }
 
+    bool isFillStyle() const { return fStroke.isFillStyle(); }
+
     int32_t dashCount() const {
         return fDashInfo.fCount;
     }
@@ -83,6 +94,14 @@
     
     const SkPathEffect::DashInfo& getDashInfo() const { return fDashInfo; }
 
+    /** Applies the dash to a path, if the stroke info has dashing.
+     * @return true if the dash ingwas applied (dst and dstStrokeInfo will be modified).
+     *         false if the stroke info did not have dashing. The dst and dstStrokeInfo
+     *               will be unmodified. The stroking in the SkStrokeRec might still
+     *               be applicable.
+     */
+    bool applyDash(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const;
+
 private:
 
     void init(const SkPaint& paint) {
diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp
index 1c1663d..cc6e2a2 100644
--- a/src/gpu/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/GrTessellatingPathRenderer.cpp
@@ -1337,7 +1337,7 @@
                                                             const GrDrawTarget*,
                                                             const GrPipelineBuilder*,
                                                             const SkPath&,
-                                                            const SkStrokeRec&) const {
+                                                            const GrStrokeInfo&) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
 
@@ -1345,7 +1345,7 @@
                                              const GrPipelineBuilder* pipelineBuilder,
                                              const SkMatrix& viewMatrix,
                                              const SkPath& path,
-                                             const SkStrokeRec& stroke,
+                                             const GrStrokeInfo& stroke,
                                              bool antiAlias) const {
     // This path renderer can draw all fill styles, but does not do antialiasing. It can do convex
     // and concave paths, but we'll leave the convex ones to simpler algorithms.
@@ -1498,7 +1498,7 @@
                                             GrColor color,
                                             const SkMatrix& viewM,
                                             const SkPath& path,
-                                            const SkStrokeRec& stroke,
+                                            const GrStrokeInfo&,
                                             bool antiAlias) {
     SkASSERT(!antiAlias);
     const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
diff --git a/src/gpu/GrTessellatingPathRenderer.h b/src/gpu/GrTessellatingPathRenderer.h
index 9772608..79cafc9 100644
--- a/src/gpu/GrTessellatingPathRenderer.h
+++ b/src/gpu/GrTessellatingPathRenderer.h
@@ -22,21 +22,21 @@
                      const GrPipelineBuilder*,
                      const SkMatrix&,
                      const SkPath&,
-                     const SkStrokeRec&,
+                     const GrStrokeInfo&,
                      bool antiAlias) const override;
 protected:
 
     StencilSupport onGetStencilSupport(const GrDrawTarget*,
                                        const GrPipelineBuilder*,
                                        const SkPath&,
-                                       const SkStrokeRec&) const override;
+                                       const GrStrokeInfo&) const override;
 
     bool onDrawPath(GrDrawTarget*,
                     GrPipelineBuilder*,
                     GrColor,
                     const SkMatrix& viewMatrix,
                     const SkPath&,
-                    const SkStrokeRec&,
+                    const GrStrokeInfo&,
                     bool antiAlias) override;
 
     typedef GrPathRenderer INHERITED;
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index cf729c1..b6dbbd6 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -28,9 +28,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 // Returns whether or not the gpu can fast path the dash line effect.
-static bool can_fast_path_dash(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
-                               const GrDrawTarget& target, const GrPipelineBuilder& pipelineBuilder,
-                               const SkMatrix& viewMatrix) {
+bool GrDashingEffect::CanDrawDashLine(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
+                                      const SkMatrix& viewMatrix) {
     // Pts must be either horizontal or vertical in src space
     if (pts[0].fX != pts[1].fX && pts[0].fY != pts[1].fY) {
         return false;
@@ -703,11 +702,7 @@
 bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target,
                                    GrPipelineBuilder* pipelineBuilder, GrColor color,
                                    const SkMatrix& viewMatrix, const SkPoint pts[2],
-                                   const GrPaint& paint, const GrStrokeInfo& strokeInfo) {
-    if (!can_fast_path_dash(pts, strokeInfo, *target, *pipelineBuilder, viewMatrix)) {
-        return false;
-    }
-
+                                   bool useAA, const GrStrokeInfo& strokeInfo) {
     const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
 
     SkPaint::Cap cap = strokeInfo.getStrokeRec().getCap();
@@ -744,8 +739,7 @@
     }
 
     DashAAMode aaMode = pipelineBuilder->getRenderTarget()->isMultisampled() ? kMSAA_DashAAMode :
-                        paint.isAntiAlias() ? kEdgeAA_DashAAMode :
-                                              kBW_DashAAMode;
+                        useAA ? kEdgeAA_DashAAMode : kBW_DashAAMode;
 
     // TODO we can do a real rect call if not using fulldash(ie no off interval, not using AA)
     bool fullDash = offInterval > 0.f || aaMode != kBW_DashAAMode;
diff --git a/src/gpu/effects/GrDashingEffect.h b/src/gpu/effects/GrDashingEffect.h
index 26b016b..999abb2 100644
--- a/src/gpu/effects/GrDashingEffect.h
+++ b/src/gpu/effects/GrDashingEffect.h
@@ -22,8 +22,10 @@
 
 namespace GrDashingEffect {
     bool DrawDashLine(GrGpu*, GrDrawTarget*, GrPipelineBuilder*, GrColor,
-                      const SkMatrix& viewMatrix, const SkPoint pts[2], const GrPaint& paint,
+                      const SkMatrix& viewMatrix, const SkPoint pts[2], bool useAA,
                       const GrStrokeInfo& strokeInfo);
+    bool CanDrawDashLine(const SkPoint pts[2], const GrStrokeInfo& strokeInfo,
+                         const SkMatrix& viewMatrix);
 }
 
 #endif