Chromium Code Reviews| Index: src/gpu/batches/GrTessellatingPathRenderer.cpp |
| diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp |
| index 2c8520b28aeb9764ad2d603fb417af8ca9487ae6..686e360bf107b96b213b1fbf7540ef9b3ae9bdf1 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); |
|
robertphillips
2016/05/09 20:05:28
stray ';' ?
bsalomon
2016/05/09 20:38:55
Done.
|
| + }; |
| + |
| // construct a cache key from the path's genID and the view matrix |
| static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain(); |
| GrUniqueKey key; |
| int clipBoundsSize32 = |
| fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0; |
|
robertphillips
2016/05/09 20:05:28
can we rm the 32 suffix ?
bsalomon
2016/05/09 20:38:55
Done.
|
| - 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 styleDataSize32 = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec); |
| + if (styleDataSize32 >= 0) { |
| + GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + styleDataSize32); |
| + 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 (styleDataSize32) { |
| + GrStyle::WriteKey(&builder[2 + clipBoundsSize32], 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() && styleDataSize32 >= 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 |