| Index: src/gpu/batches/GrTessellatingPathRenderer.cpp
|
| diff --git a/src/gpu/batches/GrTessellatingPathRenderer.cpp b/src/gpu/batches/GrTessellatingPathRenderer.cpp
|
| index 060e3f0adfe1462c479b24585b298f23bb766c50..b17bf1a4d5936f644b9cada12d71e0dc30f100ad 100644
|
| --- a/src/gpu/batches/GrTessellatingPathRenderer.cpp
|
| +++ b/src/gpu/batches/GrTessellatingPathRenderer.cpp
|
| @@ -105,14 +105,13 @@ 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. 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.fShape->style(), *args.fViewMatrix, nullptr) &&
|
| - !args.fShape->style().strokeRec().isHairlineStyle() &&
|
| - !args.fShape->style().hasNonDashPathEffect() && !args.fAntiAlias &&
|
| - !args.fShape->knownToBeConvex();
|
| + // This path renderer can draw fill styles but does not do antialiasing. It can do convex and
|
| + // concave paths, but we'll leave the convex ones to simpler algorithms. We pass on paths that
|
| + // have styles, though they may come back around after applying the styling information to the
|
| + // geometry to create a filled path. We also skip paths that don't have a key since the real
|
| + // advantage of this path renderer comes from caching the tessellated geometry.
|
| + return !args.fShape->style().applies() && args.fShape->style().isSimpleFill() &&
|
| + !args.fAntiAlias && args.fShape->hasUnstyledKey() && !args.fShape->knownToBeConvex();
|
| }
|
|
|
| class TessellatingPathBatch : public GrVertexBatch {
|
| @@ -120,11 +119,10 @@ public:
|
| DEFINE_BATCH_CLASS_ID
|
|
|
| static GrDrawBatch* Create(const GrColor& color,
|
| - const SkPath& path,
|
| - const GrStyle& style,
|
| + const GrShape& shape,
|
| const SkMatrix& viewMatrix,
|
| SkRect clipBounds) {
|
| - return new TessellatingPathBatch(color, path, style, viewMatrix, clipBounds);
|
| + return new TessellatingPathBatch(color, shape, viewMatrix, clipBounds);
|
| }
|
|
|
| const char* name() const override { return "TessellatingPathBatch"; }
|
| @@ -150,48 +148,33 @@ private:
|
| 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);
|
| - }
|
| + fShape.bounds());
|
|
|
| + SkPath path;
|
| + fShape.asPath(&path);
|
| + bool inverseFill = path.isInverseFillType();
|
| // construct a cache key from the path's genID and the view matrix
|
| static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| GrUniqueKey key;
|
| - int clipBoundsCnt =
|
| - fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) : 0;
|
| - 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;
|
| - if (fStyle.applies()) {
|
| - SkStrokeRec::InitStyle fill;
|
| - SkAssertResult(fStyle.applyToPath(&path, &fill, fPath, styleScale));
|
| - SkASSERT(SkStrokeRec::kFill_InitStyle == fill);
|
| + static constexpr int kClipBoundsCnt = sizeof(fClipBounds) / sizeof(uint32_t);
|
| + int shapeKeyDataCnt = fShape.unstyledKeySize();
|
| + SkASSERT(shapeKeyDataCnt >= 0);
|
| + GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt);
|
| + fShape.writeUnstyledKey(&builder[0]);
|
| + // For inverse fills, the tessellation is dependent on clip bounds.
|
| + if (inverseFill) {
|
| + memcpy(&builder[shapeKeyDataCnt], &fClipBounds, sizeof(fClipBounds));
|
| } else {
|
| - path = fPath;
|
| + memset(&builder[shapeKeyDataCnt], 0, sizeof(fClipBounds));
|
| + }
|
| + 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;
|
| }
|
| +
|
| bool isLinear;
|
| bool canMapVB = GrCaps::kNone_MapFlags != target->caps().mapBufferFlags();
|
| StaticVertexAllocator allocator(rp, canMapVB);
|
| @@ -200,15 +183,12 @@ private:
|
| return;
|
| }
|
| this->drawVertices(target, gp, allocator.vertexBuffer(), 0, count);
|
| - if (!fPath.isVolatile() && styleDataCnt >= 0) {
|
| - TessInfo info;
|
| - info.fTolerance = isLinear ? 0 : tol;
|
| - info.fCount = count;
|
| - SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info)));
|
| - key.setCustomData(data.get());
|
| - rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
|
| - SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(key));
|
| - }
|
| + TessInfo info;
|
| + info.fTolerance = isLinear ? 0 : tol;
|
| + info.fCount = count;
|
| + SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info)));
|
| + key.setCustomData(data.get());
|
| + rp->assignUniqueKeyToResource(key, allocator.vertexBuffer());
|
| }
|
|
|
| void onPrepareDraws(Target* target) const override {
|
| @@ -246,32 +226,28 @@ private:
|
| bool onCombineIfPossible(GrBatch*, const GrCaps&) override { return false; }
|
|
|
| TessellatingPathBatch(const GrColor& color,
|
| - const SkPath& path,
|
| - const GrStyle& style,
|
| + const GrShape& shape,
|
| const SkMatrix& viewMatrix,
|
| const SkRect& clipBounds)
|
| : INHERITED(ClassID())
|
| , fColor(color)
|
| - , fPath(path)
|
| - , fStyle(style)
|
| + , fShape(shape)
|
| , fViewMatrix(viewMatrix) {
|
| - const SkRect& pathBounds = path.getBounds();
|
| + const SkRect& pathBounds = shape.bounds();
|
| fClipBounds = clipBounds;
|
| // Because the clip bounds are used to add a contour for inverse fills, they must also
|
| // include the path bounds.
|
| fClipBounds.join(pathBounds);
|
| - if (path.isInverseFillType()) {
|
| + if (shape.inverseFilled()) {
|
| fBounds = fClipBounds;
|
| } else {
|
| - fBounds = path.getBounds();
|
| + fBounds = pathBounds;
|
| }
|
| - style.adjustBounds(&fBounds, fBounds);
|
| viewMatrix.mapRect(&fBounds);
|
| }
|
|
|
| GrColor fColor;
|
| - SkPath fPath;
|
| - GrStyle fStyle;
|
| + GrShape fShape;
|
| SkMatrix fViewMatrix;
|
| SkRect fClipBounds; // in source space
|
| GrXPOverridesForBatch fPipelineInfo;
|
| @@ -295,10 +271,8 @@ bool GrTessellatingPathRenderer::onDrawPath(const DrawPathArgs& args) {
|
| vmi.mapRect(&clipBounds);
|
| SkPath path;
|
| args.fShape->asPath(&path);
|
| - SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fColor, path,
|
| - args.fShape->style(),
|
| - *args.fViewMatrix,
|
| - clipBounds));
|
| + SkAutoTUnref<GrDrawBatch> batch(TessellatingPathBatch::Create(args.fColor, *args.fShape,
|
| + *args.fViewMatrix, clipBounds));
|
|
|
| GrPipelineBuilder pipelineBuilder(*args.fPaint, args.fDrawContext->mustUseHWAA(*args.fPaint));
|
| pipelineBuilder.setUserStencil(args.fUserStencilSettings);
|
| @@ -327,7 +301,8 @@ DRAW_BATCH_TEST_DEFINE(TesselatingPathBatch) {
|
| do {
|
| GrTest::TestStyle(random, &style);
|
| } while (style.strokeRec().isHairlineStyle());
|
| - return TessellatingPathBatch::Create(color, path, style, viewMatrix, clipBounds);
|
| + GrShape shape(path, style);
|
| + return TessellatingPathBatch::Create(color, shape, viewMatrix, clipBounds);
|
| }
|
|
|
| #endif
|
|
|