diff options
author | 2015-04-26 23:18:49 -0700 | |
---|---|---|
committer | 2015-04-26 23:18:50 -0700 | |
commit | 1899651ffc459f5462aa989cd6d08507947b67e4 (patch) | |
tree | 5f7c2c314e932dd8b7053401819f8d8bcba0436a /src/gpu | |
parent | 5d23c3824fd95785110c37e09eeaef8b3d9b9594 (diff) |
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
Diffstat (limited to 'src/gpu')
25 files changed, 287 insertions, 158 deletions
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 1813803d8a..def69a04b9 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 @@ bool GrAAConvexPathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ bool GrAAConvexPathRenderer::onDrawPath(GrDrawTarget* target, 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 816ccd697c..3abf1ab4f1 100644 --- a/src/gpu/GrAAConvexPathRenderer.h +++ b/src/gpu/GrAAConvexPathRenderer.h @@ -19,7 +19,7 @@ public: const GrPipelineBuilder*, const SkMatrix& viewMatrix, const SkPath&, - const SkStrokeRec&, + const GrStrokeInfo&, bool antiAlias) const override; protected: @@ -28,7 +28,7 @@ protected: 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 510ea0ec9b..95aa3aa6bb 100755 --- a/src/gpu/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/GrAADistanceFieldPathRenderer.cpp @@ -86,13 +86,13 @@ bool GrAADistanceFieldPathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ GrPathRenderer::StencilSupport GrAADistanceFieldPathRenderer::onGetStencilSupport(const GrDrawTarget*, const GrPipelineBuilder*, const SkPath&, - const SkStrokeRec&) const { + const GrStrokeInfo&) const { return GrPathRenderer::kNoSupport_StencilSupport; } @@ -570,7 +570,7 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, 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 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(GrDrawTarget* target, (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 ad296f0aa3..6cbee1f5c9 100755 --- a/src/gpu/GrAADistanceFieldPathRenderer.h +++ b/src/gpu/GrAADistanceFieldPathRenderer.h @@ -27,21 +27,21 @@ public: 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 1cbd93b9f8..a9bc9f2f63 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -637,7 +637,7 @@ bool GrAAHairLinePathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ bool GrAAHairLinePathRenderer::onDrawPath(GrDrawTarget* target, 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 4a24b8dc82..9f8d8aae9e 100644 --- a/src/gpu/GrAAHairLinePathRenderer.h +++ b/src/gpu/GrAAHairLinePathRenderer.h @@ -21,7 +21,7 @@ public: const GrPipelineBuilder*, const SkMatrix& viewMatrix, const SkPath&, - const SkStrokeRec&, + const GrStrokeInfo&, bool antiAlias) const override; typedef SkTArray<SkPoint, true> PtArray; @@ -34,7 +34,7 @@ protected: 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 e60d536720..06e98a98cf 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 078895d7e3..439733b8d4 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 @@ bool path_needs_SW_renderer(GrContext* context, 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 @@ bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder* pipelineBuilder, // 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 @@ bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, 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 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuil 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 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, // 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 43ac464c24..743377d468 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1343,35 +1343,6 @@ void GrContext::drawPath(GrRenderTarget* rt, } 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 @@ void GrContext::drawPath(GrRenderTarget* rt, GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex()); - const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec(); - - bool useCoverageAA = paint.isAntiAlias() && - !pipelineBuilder.getRenderTarget()->isMultisampled(); + if (!strokeInfo.isDashed()) { + const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec(); + 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; + 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); - 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); + if (isOval && !path.isInverseFillType()) { + if (fOvalRenderer->drawOval(target, + &pipelineBuilder, + color, + viewMatrix, + paint.isAntiAlias(), + ovalRect, + strokeRec)) { + return; + } + } } + this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(), + path, strokeInfo); } void GrContext::internalDrawPath(GrDrawTarget* target, @@ -1445,28 +1420,47 @@ void GrContext::internalDrawPath(GrDrawTarget* target, 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 @@ void GrContext::internalDrawPath(GrDrawTarget* target, return; } - pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *stroke, useCoverageAA); + pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA); } //////////////////////////////////////////////////////////////////////////////// @@ -1873,7 +1867,7 @@ GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target, 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 0000000000..bd49a72156 --- /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 0000000000..632f30a898 --- /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 65daa7ca89..88834bb80c 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -170,8 +170,8 @@ GrPathRenderer::StencilSupport 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 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, 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 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, 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 @@ bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ bool GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target, 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 @@ void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, 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 ab2a66b1d6..008eac2e83 100644 --- a/src/gpu/GrDefaultPathRenderer.h +++ b/src/gpu/GrDefaultPathRenderer.h @@ -23,7 +23,7 @@ public: const GrPipelineBuilder*, const SkMatrix& viewMatrix, const SkPath&, - const SkStrokeRec&, + const GrStrokeInfo&, bool antiAlias) const override; private: @@ -31,28 +31,28 @@ private: 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 5144597ab5..a53d51d161 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: // 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 @@ protected: virtual StencilSupport onGetStencilSupport(const GrDrawTarget*, const GrPipelineBuilder*, const SkPath&, - const SkStrokeRec&) const { + const GrStrokeInfo&) const { return kNoRestriction_StencilSupport; } @@ -186,7 +189,7 @@ protected: GrColor, const SkMatrix& viewMatrix, const SkPath&, - const SkStrokeRec&, + const GrStrokeInfo&, bool antiAlias) = 0; /** @@ -197,7 +200,7 @@ protected: 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 d11763bff1..915bdd263f 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -35,7 +35,7 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer(const GrDrawTarget* target, 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 466ad81779..0cc3de7a5e 100644 --- a/src/gpu/GrSoftwarePathRenderer.cpp +++ b/src/gpu/GrSoftwarePathRenderer.cpp @@ -15,12 +15,14 @@ bool GrSoftwarePathRenderer::canDrawPath(const GrDrawTarget*, 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 @@ GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(const GrDrawTarget*, const GrPipelineBuilder*, const SkPath&, - const SkStrokeRec&) const { + const GrStrokeInfo&) const { return GrPathRenderer::kNoSupport_StencilSupport; } @@ -119,9 +121,8 @@ bool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target, 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 @@ bool GrSoftwarePathRenderer::onDrawPath(GrDrawTarget* target, } 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 e7a5a28749..6e2055ad97 100644 --- a/src/gpu/GrSoftwarePathRenderer.h +++ b/src/gpu/GrSoftwarePathRenderer.h @@ -27,20 +27,20 @@ public: 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 aed1743af2..8451e632d3 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 @@ bool GrStencilAndCoverPathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ void GrStencilAndCoverPathRenderer::onStencilPath(GrDrawTarget* target, 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 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(GrDrawTarget* target, 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 a28b6aa8ab..7e3c005f3e 100644 --- a/src/gpu/GrStencilAndCoverPathRenderer.h +++ b/src/gpu/GrStencilAndCoverPathRenderer.h @@ -29,28 +29,28 @@ public: 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 0000000000..30f4b8931e --- /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 2bd056ea3c..dd942c52e9 100644 --- a/src/gpu/GrStrokeInfo.h +++ b/src/gpu/GrStrokeInfo.h @@ -44,6 +44,15 @@ public: 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 @@ public: return (!fStroke.isFillStyle() && SkPathEffect::kDash_DashType == fDashType); } + bool isFillStyle() const { return fStroke.isFillStyle(); } + int32_t dashCount() const { return fDashInfo.fCount; } @@ -83,6 +94,14 @@ public: 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 1c1663dbf3..cc6e2a2609 100644 --- a/src/gpu/GrTessellatingPathRenderer.cpp +++ b/src/gpu/GrTessellatingPathRenderer.cpp @@ -1337,7 +1337,7 @@ GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport( const GrDrawTarget*, const GrPipelineBuilder*, const SkPath&, - const SkStrokeRec&) const { + const GrStrokeInfo&) const { return GrPathRenderer::kNoSupport_StencilSupport; } @@ -1345,7 +1345,7 @@ bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target, 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 @@ bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, 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 977260821f..79cafc99f5 100644 --- a/src/gpu/GrTessellatingPathRenderer.h +++ b/src/gpu/GrTessellatingPathRenderer.h @@ -22,21 +22,21 @@ public: 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 cf729c177e..b6dbbd6e0e 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 @@ private: 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 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, } 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 26b016bcac..999abb23d8 100644 --- a/src/gpu/effects/GrDashingEffect.h +++ b/src/gpu/effects/GrDashingEffect.h @@ -22,8 +22,10 @@ class GrStrokeInfo; 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 |