diff options
author | bsalomon <bsalomon@google.com> | 2016-05-10 05:57:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-05-10 05:57:27 -0700 |
commit | 33595bdf4b64a745f6340338d307e806e96c587f (patch) | |
tree | e6a4e7abd27df7aa3fdc764d67ec9e3b4cf86868 /src/gpu/batches | |
parent | 82595b6fa4733e1525f357bdcac22db058790550 (diff) |
Replace GrStrokeInfo with GrStyle.
A side effect is that arbitrary path effects can no be pushed deeper into the Ganesh flow for paths. They may be applied by path renderers.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1957363002
Review-Url: https://codereview.chromium.org/1957363002
Diffstat (limited to 'src/gpu/batches')
-rw-r--r-- | src/gpu/batches/GrAAConvexPathRenderer.cpp | 3 | ||||
-rw-r--r-- | src/gpu/batches/GrAADistanceFieldPathRenderer.cpp | 33 | ||||
-rw-r--r-- | src/gpu/batches/GrAAHairLinePathRenderer.cpp | 16 | ||||
-rw-r--r-- | src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp | 26 | ||||
-rw-r--r-- | src/gpu/batches/GrDashLinePathRenderer.cpp | 6 | ||||
-rw-r--r-- | src/gpu/batches/GrDefaultPathRenderer.cpp | 34 | ||||
-rw-r--r-- | src/gpu/batches/GrDefaultPathRenderer.h | 2 | ||||
-rw-r--r-- | src/gpu/batches/GrMSAAPathRenderer.cpp | 43 | ||||
-rw-r--r-- | src/gpu/batches/GrMSAAPathRenderer.h | 1 | ||||
-rw-r--r-- | src/gpu/batches/GrPLSPathRenderer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/batches/GrStencilAndCoverPathRenderer.cpp | 20 | ||||
-rw-r--r-- | src/gpu/batches/GrTessellatingPathRenderer.cpp | 98 |
12 files changed, 154 insertions, 132 deletions
diff --git a/src/gpu/batches/GrAAConvexPathRenderer.cpp b/src/gpu/batches/GrAAConvexPathRenderer.cpp index 8c55de7e79..f557c9b9e9 100644 --- a/src/gpu/batches/GrAAConvexPathRenderer.cpp +++ b/src/gpu/batches/GrAAConvexPathRenderer.cpp @@ -18,7 +18,6 @@ #include "GrPathUtils.h" #include "GrProcessor.h" #include "GrPipelineBuilder.h" -#include "GrStrokeInfo.h" #include "SkGeometry.h" #include "SkPathPriv.h" #include "SkString.h" @@ -682,7 +681,7 @@ const GrGeometryProcessor* QuadEdgeEffect::TestCreate(GrProcessorTestData* d) { bool GrAAConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { return (args.fShaderCaps->shaderDerivativeSupport() && args.fAntiAlias && - args.fStroke->isFillStyle() && !args.fPath->isInverseFillType() && + args.fStyle->isSimpleFill() && !args.fPath->isInverseFillType() && args.fPath->isConvex()); } diff --git a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp index f891b8d1f5..ba52bf9213 100644 --- a/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp +++ b/src/gpu/batches/GrAADistanceFieldPathRenderer.cpp @@ -81,13 +81,14 @@ GrAADistanceFieldPathRenderer::~GrAADistanceFieldPathRenderer() { //////////////////////////////////////////////////////////////////////////////// bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - + // We don't currently apply the dash or factor it into the DF key. (skbug.com/5082) + if (args.fStyle->pathEffect()) { + return false; + } // TODO: Support inverse fill if (!args.fShaderCaps->shaderDerivativeSupport() || !args.fAntiAlias || - SkStrokeRec::kHairline_Style == args.fStroke->getStyle() || - args.fPath->isInverseFillType() || args.fPath->isVolatile() || - // We don't currently apply the dash or factor it into the DF key. (skbug.com/5082) - args.fStroke->isDashed()) { + args.fStyle->isSimpleHairline() || args.fPath->isInverseFillType() || + args.fPath->isVolatile()) { return false; } @@ -100,16 +101,23 @@ bool GrAADistanceFieldPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c // scaled to have bounds within 2.0f*kLargeMIP by 2.0f*kLargeMIP // the goal is to accelerate rendering of lots of small paths that may be scaling SkScalar maxScale = args.fViewMatrix->getMaxScale(); +#if 0 // This is more accurate but changes some GMs. TODO: Standalone change to enable this. + SkRect bounds; + args.fStyle->adjustBounds(&bounds, args.fPath->getBounds()); + SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); +#else const SkRect& bounds = args.fPath->getBounds(); SkScalar maxDim = SkMaxScalar(bounds.width(), bounds.height()); + const SkStrokeRec& stroke = args.fStyle->strokeRec(); // Approximate stroked size by adding the maximum of the stroke width or 2x the miter limit - if (!args.fStroke->isFillStyle()) { - SkScalar extraWidth = args.fStroke->getWidth(); - if (SkPaint::kMiter_Join == args.fStroke->getJoin()) { - extraWidth = SkTMax(extraWidth, 2.0f*args.fStroke->getMiter()); + if (!stroke.isFillStyle()) { + SkScalar extraWidth = stroke.getWidth(); + if (SkPaint::kMiter_Join == stroke.getJoin()) { + extraWidth = SkTMax(extraWidth, 2.0f*stroke.getMiter()); } maxDim += extraWidth; } +#endif return maxDim <= kMediumMIP && maxDim * maxScale <= 2.0f*kLargeMIP; } @@ -552,11 +560,12 @@ bool GrAADistanceFieldPathRenderer::onDrawPath(const DrawPathArgs& args) { } } - AADistanceFieldPathBatch::Geometry geometry(*args.fStroke); - if (SkStrokeRec::kFill_Style == args.fStroke->getStyle()) { + // It's ok to ignore style's path effect because canDrawPath filtered out path effects. + AADistanceFieldPathBatch::Geometry geometry(args.fStyle->strokeRec()); + if (args.fStyle->isSimpleFill()) { geometry.fPath = *args.fPath; } else { - args.fStroke->applyToPath(&geometry.fPath, *args.fPath); + args.fStyle->strokeRec().applyToPath(&geometry.fPath, *args.fPath); } geometry.fColor = args.fColor; geometry.fAntiAlias = args.fAntiAlias; diff --git a/src/gpu/batches/GrAAHairLinePathRenderer.cpp b/src/gpu/batches/GrAAHairLinePathRenderer.cpp index effd8c3b0f..db4bbdfdb3 100644 --- a/src/gpu/batches/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/batches/GrAAHairLinePathRenderer.cpp @@ -618,7 +618,12 @@ bool GrAAHairLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const return false; } - if (!IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullptr)) { + if (!IsStrokeHairlineOrEquivalent(*args.fStyle, *args.fViewMatrix, nullptr)) { + return false; + } + + // We don't currently handle dashing in this class though perhaps we should. + if (args.fStyle->pathEffect()) { return false; } @@ -939,11 +944,11 @@ void AAHairlineBatch::onPrepareDraws(Target* target) const { static GrDrawBatch* create_hairline_batch(GrColor color, const SkMatrix& viewMatrix, const SkPath& path, - const GrStrokeInfo& stroke, + const GrStyle& style, const SkIRect& devClipBounds) { SkScalar hairlineCoverage; uint8_t newCoverage = 0xff; - if (GrPathRenderer::IsStrokeHairlineOrEquivalent(stroke, viewMatrix, &hairlineCoverage)) { + if (GrPathRenderer::IsStrokeHairlineOrEquivalent(style, viewMatrix, &hairlineCoverage)) { newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); } @@ -964,7 +969,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const DrawPathArgs& args) { args.fPipelineBuilder->clip().getConservativeBounds(rt->width(), rt->height(), &devClipBounds); SkAutoTUnref<GrDrawBatch> batch(create_hairline_batch(args.fColor, *args.fViewMatrix, *args.fPath, - *args.fStroke, devClipBounds)); + *args.fStyle, devClipBounds)); args.fTarget->drawBatch(*args.fPipelineBuilder, batch); return true; @@ -977,11 +982,10 @@ bool GrAAHairLinePathRenderer::onDrawPath(const DrawPathArgs& args) { DRAW_BATCH_TEST_DEFINE(AAHairlineBatch) { GrColor color = GrRandomColor(random); SkMatrix viewMatrix = GrTest::TestMatrix(random); - GrStrokeInfo stroke(SkStrokeRec::kHairline_InitStyle); SkPath path = GrTest::TestPath(random); SkIRect devClipBounds; devClipBounds.setEmpty(); - return create_hairline_batch(color, viewMatrix, path, stroke, devClipBounds); + return create_hairline_batch(color, viewMatrix, path, GrStyle::SimpleHairline(), devClipBounds); } #endif diff --git a/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp index 446f67f1c0..91d3338c32 100644 --- a/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp +++ b/src/gpu/batches/GrAALinearizingConvexPathRenderer.cpp @@ -17,7 +17,7 @@ #include "GrPathUtils.h" #include "GrProcessor.h" #include "GrPipelineBuilder.h" -#include "GrStrokeInfo.h" +#include "GrStyle.h" #include "SkGeometry.h" #include "SkString.h" #include "SkTraceEvent.h" @@ -46,16 +46,20 @@ bool GrAALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& arg if (!args.fPath->isConvex()) { return false; } - if (args.fStroke->getStyle() == SkStrokeRec::kStroke_Style) { + if (args.fStyle->pathEffect()) { + return false; + } + const SkStrokeRec& stroke = args.fStyle->strokeRec(); + if (stroke.getStyle() == SkStrokeRec::kStroke_Style) { if (!args.fViewMatrix->isSimilarity()) { return false; } - SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * args.fStroke->getWidth(); - return strokeWidth >= 1.0f && strokeWidth <= kMaxStrokeWidth && !args.fStroke->isDashed() && - SkPathPriv::IsClosedSingleContour(*args.fPath) && - args.fStroke->getJoin() != SkPaint::Join::kRound_Join; + SkScalar strokeWidth = args.fViewMatrix->getMaxScale() * stroke.getWidth(); + return strokeWidth >= 1.0f && strokeWidth <= kMaxStrokeWidth && + SkPathPriv::IsClosedSingleContour(*args.fPath) && + stroke.getJoin() != SkPaint::Join::kRound_Join; } - return args.fStroke->getStyle() == SkStrokeRec::kFill_Style; + return stroke.getStyle() == SkStrokeRec::kFill_Style; } // extract the result vertices and indices from the GrAAConvexTessellator @@ -325,10 +329,10 @@ bool GrAALinearizingConvexPathRenderer::onDrawPath(const DrawPathArgs& args) { geometry.fColor = args.fColor; geometry.fViewMatrix = *args.fViewMatrix; geometry.fPath = *args.fPath; - geometry.fStrokeWidth = args.fStroke->isFillStyle() ? -1.0f : args.fStroke->getWidth(); - geometry.fJoin = args.fStroke->isFillStyle() ? SkPaint::Join::kMiter_Join : - args.fStroke->getJoin(); - geometry.fMiterLimit = args.fStroke->getMiter(); + bool fill = args.fStyle->isSimpleFill(); + geometry.fStrokeWidth = fill ? -1.0f : args.fStyle->strokeRec().getWidth(); + geometry.fJoin = fill ? SkPaint::Join::kMiter_Join : args.fStyle->strokeRec().getJoin(); + geometry.fMiterLimit = args.fStyle->strokeRec().getMiter(); SkAutoTUnref<GrDrawBatch> batch(AAFlatteningConvexPathBatch::Create(geometry)); args.fTarget->drawBatch(*args.fPipelineBuilder, batch); diff --git a/src/gpu/batches/GrDashLinePathRenderer.cpp b/src/gpu/batches/GrDashLinePathRenderer.cpp index 9ee27c78dd..8cb8046af4 100644 --- a/src/gpu/batches/GrDashLinePathRenderer.cpp +++ b/src/gpu/batches/GrDashLinePathRenderer.cpp @@ -12,8 +12,8 @@ bool GrDashLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { SkPoint pts[2]; - if (args.fStroke->isDashed() && args.fPath->isLine(pts)) { - return GrDashingEffect::CanDrawDashLine(pts, *args.fStroke, *args.fViewMatrix); + if (args.fStyle->isDashed() && args.fPath->isLine(pts)) { + return GrDashingEffect::CanDrawDashLine(pts, *args.fStyle, *args.fViewMatrix); } return false; } @@ -28,7 +28,7 @@ bool GrDashLinePathRenderer::onDrawPath(const DrawPathArgs& args) { pts, args.fAntiAlias, msaaIsEnabled, - *args.fStroke)); + *args.fStyle)); if (!batch) { return false; } diff --git a/src/gpu/batches/GrDefaultPathRenderer.cpp b/src/gpu/batches/GrDefaultPathRenderer.cpp index 1de0bf771e..9994b26a1a 100644 --- a/src/gpu/batches/GrDefaultPathRenderer.cpp +++ b/src/gpu/batches/GrDefaultPathRenderer.cpp @@ -422,22 +422,21 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, GrColor color, const SkMatrix& viewMatrix, const SkPath& path, - const GrStrokeInfo& origStroke, + const GrStyle& origStyle, bool stencilOnly) { - SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke); + const GrStyle* style = &origStyle; SkScalar hairlineCoverage; uint8_t newCoverage = 0xff; - if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { + bool isHairline = false; + if (IsStrokeHairlineOrEquivalent(*style, viewMatrix, &hairlineCoverage)) { newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); - - if (!stroke->isHairlineStyle()) { - stroke.writable()->setHairlineStyle(); - } + style = &GrStyle::SimpleHairline(); + isHairline = true; + } else { + SkASSERT(style->isSimpleFill()); } - const bool isHairline = stroke->isHairlineStyle(); - // Save the current xp on the draw state so we can reset it if needed const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory(); SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory)); @@ -460,7 +459,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, style->strokeRec())) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; @@ -596,10 +595,11 @@ bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, } bool GrDefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - // this class can draw any path with any fill but doesn't do any anti-aliasing. - return !args.fAntiAlias && (args.fStroke->isFillStyle() || - IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, - nullptr)); + // this class can draw any path with any simple fill style but doesn't do any anti-aliasing. + return !args.fAntiAlias && + (args.fStyle->isSimpleFill() || IsStrokeHairlineOrEquivalent(*args.fStyle, + *args.fViewMatrix, + nullptr)); } bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) { @@ -609,7 +609,7 @@ bool GrDefaultPathRenderer::onDrawPath(const DrawPathArgs& args) { args.fColor, *args.fViewMatrix, *args.fPath, - *args.fStroke, + *args.fStyle, false); } @@ -618,7 +618,7 @@ void GrDefaultPathRenderer::onStencilPath(const StencilPathArgs& args) { SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType()); SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType()); this->internalDrawPath(args.fTarget, args.fPipelineBuilder, GrColor_WHITE, *args.fViewMatrix, - *args.fPath, GrStrokeInfo::FillInfo(), true); + *args.fPath, GrStyle::SimpleFill(), true); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -631,7 +631,7 @@ DRAW_BATCH_TEST_DEFINE(DefaultPathBatch) { // For now just hairlines because the other types of draws require two batches. // TODO we should figure out a way to combine the stencil and cover steps into one batch - GrStrokeInfo stroke(SkStrokeRec::kHairline_InitStyle); + GrStyle style(SkStrokeRec::kHairline_InitStyle); SkPath path = GrTest::TestPath(random); // Compute srcSpaceTol diff --git a/src/gpu/batches/GrDefaultPathRenderer.h b/src/gpu/batches/GrDefaultPathRenderer.h index 8156462a51..8a74d3a011 100644 --- a/src/gpu/batches/GrDefaultPathRenderer.h +++ b/src/gpu/batches/GrDefaultPathRenderer.h @@ -35,7 +35,7 @@ private: GrColor, const SkMatrix& viewMatrix, const SkPath&, - const GrStrokeInfo&, + const GrStyle&, bool stencilOnly); bool fSeparateStencil; diff --git a/src/gpu/batches/GrMSAAPathRenderer.cpp b/src/gpu/batches/GrMSAAPathRenderer.cpp index a9ba06c5f4..a382c42054 100644 --- a/src/gpu/batches/GrMSAAPathRenderer.cpp +++ b/src/gpu/batches/GrMSAAPathRenderer.cpp @@ -29,7 +29,7 @@ static const float kTolerance = 0.5f; //////////////////////////////////////////////////////////////////////////////// // Helpers for drawPath -static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) { +static inline bool single_pass_path(const SkPath& path) { if (!path.isInverseFillType()) { return path.isConvex(); } @@ -38,7 +38,7 @@ static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& strok GrPathRenderer::StencilSupport GrMSAAPathRenderer::onGetStencilSupport(const SkPath& path) const { - if (single_pass_path(path, SkStrokeRec(SkStrokeRec::kFill_InitStyle))) { + if (single_pass_path(path)) { return GrPathRenderer::kNoRestriction_StencilSupport; } else { return GrPathRenderer::kStencilOnly_StencilSupport; @@ -571,9 +571,7 @@ bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target, GrColor color, const SkMatrix& viewMatrix, const SkPath& path, - const GrStrokeInfo& origStroke, bool stencilOnly) { - SkTCopyOnFirstWrite<GrStrokeInfo> stroke(origStroke); const GrXPFactory* xpFactory = pipelineBuilder->getXPFactory(); SkAutoTUnref<const GrXPFactory> backupXPFactory(SkSafeRef(xpFactory)); @@ -586,7 +584,7 @@ bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target, bool reverse = false; bool lastPassIsBounds; - if (single_pass_path(path, *stroke)) { + if (single_pass_path(path)) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; @@ -703,34 +701,35 @@ bool GrMSAAPathRenderer::internalDrawPath(GrDrawTarget* target, } bool GrMSAAPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullptr) && - !args.fAntiAlias; + // This path renderer does not support hairlines. We defer on anything that could be handled + // as a hairline by another path renderer. Also, arbitrary path effects could produce + // a hairline result. + return !IsStrokeHairlineOrEquivalent(*args.fStyle, *args.fViewMatrix, nullptr) && + !args.fStyle->hasNonDashPathEffect() && !args.fAntiAlias; } bool GrMSAAPathRenderer::onDrawPath(const DrawPathArgs& args) { GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrMSAAPathRenderer::onDrawPath"); - SkPath path; - GrStrokeInfo stroke(*args.fStroke); - if (stroke.isDashed()) { - if (!stroke.applyDashToPath(&path, &stroke, *args.fPath)) { + SkPath tmpPath; + const SkPath* path; + if (args.fStyle->applies()) { + SkStrokeRec::InitStyle fill; + SkScalar styleScale = GrStyle::MatrixToScaleFactor(*args.fViewMatrix); + if (!args.fStyle->applyToPath(&tmpPath, &fill, *args.fPath, styleScale)) { return false; } + // We don't accept styles that are hairlines or have path effects that could produce + // hairlines. + SkASSERT(SkStrokeRec::kFill_InitStyle == fill); + path = &tmpPath; } else { - path = *args.fPath; - } - if (!stroke.isFillStyle()) { - stroke.setResScale(SkScalarAbs(args.fViewMatrix->getMaxScale())); - if (!stroke.applyToPath(&path, path)) { - return false; - } - stroke.setFillStyle(); + path = args.fPath; } return this->internalDrawPath(args.fTarget, args.fPipelineBuilder, args.fColor, *args.fViewMatrix, - path, - stroke, + *path, false); } @@ -739,7 +738,7 @@ void GrMSAAPathRenderer::onStencilPath(const StencilPathArgs& args) { SkASSERT(SkPath::kInverseEvenOdd_FillType != args.fPath->getFillType()); SkASSERT(SkPath::kInverseWinding_FillType != args.fPath->getFillType()); this->internalDrawPath(args.fTarget, args.fPipelineBuilder, GrColor_WHITE, *args.fViewMatrix, - *args.fPath, GrStrokeInfo::FillInfo(), true); + *args.fPath, true); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/batches/GrMSAAPathRenderer.h b/src/gpu/batches/GrMSAAPathRenderer.h index a35536014e..434a962190 100644 --- a/src/gpu/batches/GrMSAAPathRenderer.h +++ b/src/gpu/batches/GrMSAAPathRenderer.h @@ -26,7 +26,6 @@ private: GrColor, const SkMatrix& viewMatrix, const SkPath&, - const GrStrokeInfo&, bool stencilOnly); typedef GrPathRenderer INHERITED; diff --git a/src/gpu/batches/GrPLSPathRenderer.cpp b/src/gpu/batches/GrPLSPathRenderer.cpp index 46993c7f33..c26b4c0243 100644 --- a/src/gpu/batches/GrPLSPathRenderer.cpp +++ b/src/gpu/batches/GrPLSPathRenderer.cpp @@ -23,7 +23,7 @@ #include "GrPathUtils.h" #include "GrProcessor.h" #include "GrPipelineBuilder.h" -#include "GrStrokeInfo.h" +#include "GrStyle.h" #include "GrTessellator.h" #include "batches/GrVertexBatch.h" #include "glsl/GrGLSLGeometryProcessor.h" @@ -778,7 +778,7 @@ bool GrPLSPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { // We have support for even-odd rendering, but are having some troublesome // seams. Disable in the presence of even-odd for now. return args.fShaderCaps->shaderDerivativeSupport() && args.fAntiAlias && - args.fStroke->isFillStyle() && !args.fPath->isInverseFillType() && + args.fStyle->isSimpleFill() && !args.fPath->isInverseFillType() && args.fPath->getFillType() == SkPath::FillType::kWinding_FillType; } diff --git a/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp b/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp index 6933efebe3..9d8d07de84 100644 --- a/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp +++ b/src/gpu/batches/GrStencilAndCoverPathRenderer.cpp @@ -14,7 +14,7 @@ #include "GrPath.h" #include "GrRenderTarget.h" #include "GrResourceProvider.h" -#include "GrStrokeInfo.h" +#include "GrStyle.h" #include "batches/GrRectBatchFactory.h" GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider, @@ -31,7 +31,9 @@ GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider* } bool GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { - if (args.fStroke->isHairlineStyle()) { + // GrPath doesn't support hairline paths. Also, an arbitrary path effect could change + // the style type to hairline. + if (!args.fStyle->hasNonDashPathEffect() || args.fStyle->strokeRec().isHairlineStyle()) { return false; } if (!args.fIsStencilDisabled) { @@ -45,19 +47,19 @@ bool GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) c } static GrPath* get_gr_path(GrResourceProvider* resourceProvider, const SkPath& skPath, - const GrStrokeInfo& stroke) { + const GrStyle& style) { GrUniqueKey key; bool isVolatile; - GrPath::ComputeKey(skPath, stroke, &key, &isVolatile); + GrPath::ComputeKey(skPath, style, &key, &isVolatile); SkAutoTUnref<GrPath> path( static_cast<GrPath*>(resourceProvider->findAndRefResourceByUniqueKey(key))); if (!path) { - path.reset(resourceProvider->createPath(skPath, stroke)); + path.reset(resourceProvider->createPath(skPath, style)); if (!isVolatile) { resourceProvider->assignUniqueKeyToResource(key, path); } } else { - SkASSERT(path->isEqualTo(skPath, stroke)); + SkASSERT(path->isEqualTo(skPath, style)); } return path.release(); } @@ -66,14 +68,14 @@ void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) { GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrStencilAndCoverPathRenderer::onStencilPath"); SkASSERT(!args.fPath->isInverseFillType()); - SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, *args.fPath, GrStrokeInfo::FillInfo())); + SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, *args.fPath, GrStyle::SimpleFill())); args.fTarget->stencilPath(*args.fPipelineBuilder, *args.fViewMatrix, p, p->getFillType()); } bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { GR_AUDIT_TRAIL_AUTO_FRAME(args.fTarget->getAuditTrail(), "GrStencilAndCoverPathRenderer::onDrawPath"); - SkASSERT(!args.fStroke->isHairlineStyle()); + SkASSERT(!args.fStyle->strokeRec().isHairlineStyle()); const SkPath& path = *args.fPath; GrPipelineBuilder* pipelineBuilder = args.fPipelineBuilder; const SkMatrix& viewMatrix = *args.fViewMatrix; @@ -85,7 +87,7 @@ bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) { pipelineBuilder->enableState(GrPipelineBuilder::kHWAntialias_Flag); } - SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, path, *args.fStroke)); + SkAutoTUnref<GrPath> p(get_gr_path(fResourceProvider, path, *args.fStyle)); if (path.isInverseFillType()) { static constexpr GrStencilSettings kInvertedStencilPass( diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp index 2c8520b28a..d2cfb6e9cb 100644 --- a/src/gpu/batches/GrTessellatingPathRenderer.cpp +++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp @@ -105,9 +105,10 @@ GrTessellatingPathRenderer::GrTessellatingPathRenderer() { bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const { // This path renderer can draw all fill styles, all stroke styles except hairlines, but does // not do antialiasing. It can do convex and concave paths, but we'll leave the convex ones to - // simpler algorithms. - return !IsStrokeHairlineOrEquivalent(*args.fStroke, *args.fViewMatrix, nullptr) && - !args.fAntiAlias && !args.fPath->isConvex(); + // simpler algorithms. Similary, we skip the non-hairlines that can be treated as hairline. + // An arbitrary path effect could produce a hairline result so we pass on those. + return !IsStrokeHairlineOrEquivalent(*args.fStyle, *args.fViewMatrix, nullptr) && + !args.fStyle->hasNonDashPathEffect() && !args.fAntiAlias && !args.fPath->isConvex(); } class TessellatingPathBatch : public GrVertexBatch { @@ -116,10 +117,10 @@ public: static GrDrawBatch* Create(const GrColor& color, const SkPath& path, - const GrStrokeInfo& stroke, + const GrStyle& style, const SkMatrix& viewMatrix, SkRect clipBounds) { - return new TessellatingPathBatch(color, path, stroke, viewMatrix, clipBounds); + return new TessellatingPathBatch(color, path, style, viewMatrix, clipBounds); } const char* name() const override { return "TessellatingPathBatch"; } @@ -142,48 +143,51 @@ private: } void draw(Target* target, const GrGeometryProcessor* gp) const { + GrResourceProvider* rp = target->resourceProvider(); + SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; + SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMatrix, + fPath.getBounds()); + + SkScalar styleScale = SK_Scalar1; + if (fStyle.applies()) { + styleScale = GrStyle::MatrixToScaleFactor(fViewMatrix); + } + // construct a cache key from the path's genID and the view matrix static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); GrUniqueKey key; - int clipBoundsSize32 = + int clipBoundsCnt = fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0; - int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); - GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strokeDataSize32); - builder[0] = fPath.getGenerationID(); - builder[1] = fPath.getFillType(); - // For inverse fills, the tessellation is dependent on clip bounds. - if (fPath.isInverseFillType()) { - memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); - } - fStroke.asUniqueKeyFragment(&builder[2 + clipBoundsSize32]); - builder.finish(); - GrResourceProvider* rp = target->resourceProvider(); - SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key)); - int actualCount; - SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; - SkScalar tol = GrPathUtils::scaleToleranceToSrc( - screenSpaceTol, fViewMatrix, fPath.getBounds()); - if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { - this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount); - return; + int styleDataCnt = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec); + if (styleDataCnt >= 0) { + GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsCnt + styleDataCnt); + builder[0] = fPath.getGenerationID(); + builder[1] = fPath.getFillType(); + // For inverse fills, the tessellation is dependent on clip bounds. + if (fPath.isInverseFillType()) { + memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); + } + if (styleDataCnt) { + GrStyle::WriteKey(&builder[2 + clipBoundsCnt], fStyle, + GrStyle::Apply::kPathEffectAndStrokeRec, styleScale); + } + builder.finish(); + SkAutoTUnref<GrBuffer> cachedVertexBuffer(rp->findAndRefTByUniqueKey<GrBuffer>(key)); + int actualCount; + if (cache_match(cachedVertexBuffer.get(), tol, &actualCount)) { + this->drawVertices(target, gp, cachedVertexBuffer.get(), 0, actualCount); + return; + } } SkPath path; - GrStrokeInfo stroke(fStroke); - if (stroke.isDashed()) { - if (!stroke.applyDashToPath(&path, &stroke, fPath)) { - return; - } + if (fStyle.applies()) { + SkStrokeRec::InitStyle fill; + SkAssertResult(fStyle.applyToPath(&path, &fill, fPath, styleScale)); + SkASSERT(SkStrokeRec::kFill_InitStyle == fill); } else { path = fPath; } - if (!stroke.isFillStyle()) { - stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); - if (!stroke.applyToPath(&path, path)) { - return; - } - stroke.setFillStyle(); - } bool isLinear; bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags(); StaticVertexAllocator allocator(rp, canMapVB); @@ -192,7 +196,7 @@ private: return; } this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count); - if (!fPath.isVolatile()) { + if (!fPath.isVolatile() && styleDataCnt >= 0) { TessInfo info; info.fTolerance = isLinear ? 0 : tol; info.fCount = count; @@ -240,13 +244,13 @@ private: TessellatingPathBatch(const GrColor& color, const SkPath& path, - const GrStrokeInfo& stroke, + const GrStyle& style, const SkMatrix& viewMatrix, const SkRect& clipBounds) : INHERITED(ClassID()) , fColor(color) , fPath(path) - , fStroke(stroke) + , fStyle(style) , fViewMatrix(viewMatrix) { const SkRect& pathBounds = path.getBounds(); fClipBounds = clipBounds; @@ -258,14 +262,13 @@ private: } else { fBounds = path.getBounds(); } - SkScalar radius = stroke.getInflationRadius(); - fBounds.outset(radius, radius); + style.adjustBounds(&fBounds, fBounds); viewMatrix.mapRect(&fBounds); } GrColor fColor; SkPath fPath; - GrStrokeInfo fStroke; + GrStyle fStyle; SkMatrix fViewMatrix; SkRect fClipBounds; // in source space GrXPOverridesForBatch fPipelineInfo; @@ -291,7 +294,7 @@ bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) { } vmi.mapRect(&clipBounds); SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fColor, *args.fPath, - *args.fStroke, *args.fViewMatrix, + *args.fStyle, *args.fViewMatrix, clipBounds)); args.fTarget->drawBatch(*args.fPipelineBuilder, batch); @@ -313,8 +316,11 @@ DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) { SkFAIL("Cannot invert matrix\n"); } vmi.mapRect(&clipBounds); - GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); - return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, clipBounds); + GrStyle style; + do { + GrTest::TestStyle(random, &style); + } while (style.strokeRec().isHairlineStyle()); + return TessellatingPathBatch::Create(color, path, style, viewMatrix, clipBounds); } #endif |