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