diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-09-08 16:25:08 -0600 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-09-12 20:04:20 +0000 |
commit | db91c6e7fbfc9d1d8fd203f7e08eefb602e4a0b9 (patch) | |
tree | cb13d0253d2161a7e995bc94fc8cedb85df7dd04 | |
parent | a640c49b7ecf667696542143edec96d10a940592 (diff) |
Improve heuristics for when to use ccpr
Gives the convex and tessellating renderers first claim on larger
paths, and the distance field renderer first claim on complex,
non-volatile paths. This also requires plumbing the clip bounds
through GrPathRenderer::CanDrawPathArgs.
Bug: skia:
Change-Id: I16e1d35ad5ee63251e33f113b1579cbba60456da
Reviewed-on: https://skia-review.googlesource.com/42224
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
-rw-r--r-- | src/gpu/GrClipStackClip.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrClipStackClip.h | 1 | ||||
-rw-r--r-- | src/gpu/GrPathRenderer.h | 44 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.cpp | 12 | ||||
-rw-r--r-- | src/gpu/GrReducedClip.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrRenderTargetContext.cpp | 11 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp | 21 | ||||
-rw-r--r-- | tests/TessellatingPathRendererTests.cpp | 3 |
8 files changed, 64 insertions, 36 deletions
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp index 50732a4cb2..165b442d90 100644 --- a/src/gpu/GrClipStackClip.cpp +++ b/src/gpu/GrClipStackClip.cpp @@ -87,6 +87,7 @@ static std::unique_ptr<GrFragmentProcessor> create_fp_for_mask(sk_sp<GrTexturePr // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set // 'prOut' to the non-SW path renderer that will do the job). bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context, + const SkIRect& scissorRect, bool hasUserStencilSettings, const GrRenderTargetContext* renderTargetContext, const SkMatrix& viewMatrix, @@ -118,6 +119,7 @@ bool GrClipStackClip::PathNeedsSWRenderer(GrContext* context, GrShape shape(path, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; canDrawArgs.fCaps = context->caps(); + canDrawArgs.fClipConservativeBounds = &scissorRect; canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; canDrawArgs.fAAType = GrChooseAAType(GrBoolToAA(element->isAA()), @@ -166,7 +168,7 @@ bool GrClipStackClip::UseSWOnlyPath(GrContext* context, bool needsStencil = invert || kIntersect_SkClipOp == op || kReverseDifference_SkClipOp == op; - if (PathNeedsSWRenderer(context, hasUserStencilSettings, + if (PathNeedsSWRenderer(context, reducedClip.ibounds(), hasUserStencilSettings, renderTargetContext, translate, element, nullptr, needsStencil)) { return true; } diff --git a/src/gpu/GrClipStackClip.h b/src/gpu/GrClipStackClip.h index 97ea8bc252..ae14bb35be 100644 --- a/src/gpu/GrClipStackClip.h +++ b/src/gpu/GrClipStackClip.h @@ -38,6 +38,7 @@ public: private: static bool PathNeedsSWRenderer(GrContext* context, + const SkIRect& scissorRect, bool hasUserStencilSettings, const GrRenderTargetContext*, const SkMatrix& viewMatrix, diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h index cf0ef6effc..4a7fb92e9f 100644 --- a/src/gpu/GrPathRenderer.h +++ b/src/gpu/GrPathRenderer.h @@ -73,16 +73,11 @@ public: kYes }; - /** Args to canDrawPath() - * - * fCaps The context caps - * fPipelineBuilder The pipelineBuilder - * fViewMatrix The viewMatrix - * fShape The shape to draw - * fAntiAlias The type of anti aliasing required. - */ struct CanDrawPathArgs { + SkDEBUGCODE(CanDrawPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation. + const GrCaps* fCaps; + const SkIRect* fClipConservativeBounds; const SkMatrix* fViewMatrix; const GrShape* fShape; GrAAType fAAType; @@ -93,6 +88,7 @@ public: #ifdef SK_DEBUG void validate() const { SkASSERT(fCaps); + SkASSERT(fClipConservativeBounds); SkASSERT(fViewMatrix); SkASSERT(fShape); } @@ -109,25 +105,13 @@ public: return this->onCanDrawPath(args); } - /** - * Args to drawPath() - * - * fTarget The target that the path will be rendered to - * fResourceProvider The resource provider for creating gpu resources to render the path - * fPipelineBuilder The pipelineBuilder - * fClip The clip - * fColor Color to render with - * fViewMatrix The viewMatrix - * fShape The shape to draw - * fAAtype true if anti-aliasing is required. - * fGammaCorrect true if gamma-correct rendering is to be used. - */ struct DrawPathArgs { GrContext* fContext; GrPaint&& fPaint; const GrUserStencilSettings* fUserStencilSettings; GrRenderTargetContext* fRenderTargetContext; const GrClip* fClip; + const SkIRect* fClipConservativeBounds; const SkMatrix* fViewMatrix; const GrShape* fShape; GrAAType fAAType; @@ -138,6 +122,7 @@ public: SkASSERT(fUserStencilSettings); SkASSERT(fRenderTargetContext); SkASSERT(fClip); + SkASSERT(fClipConservativeBounds); SkASSERT(fViewMatrix); SkASSERT(fShape); } @@ -153,9 +138,11 @@ public: #ifdef SK_DEBUG CanDrawPathArgs canArgs; canArgs.fCaps = args.fContext->caps(); + canArgs.fClipConservativeBounds = args.fClipConservativeBounds; canArgs.fViewMatrix = args.fViewMatrix; canArgs.fShape = args.fShape; canArgs.fAAType = args.fAAType; + canArgs.validate(); canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused(); SkASSERT(!(canArgs.fAAType == GrAAType::kMSAA && @@ -173,18 +160,16 @@ public: return this->onDrawPath(args); } - /* Args to stencilPath(). - * - * fResourceProvider The resource provider for creating gpu resources to render the path - * fRenderTargetContext The target of the draws - * fViewMatrix Matrix applied to the path. - * fPath The path to draw. - * fAAType The type of AA, cannot be kCoverage. + /** + * Args to stencilPath(). fAAType cannot be kCoverage. */ struct StencilPathArgs { + SkDEBUGCODE(StencilPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation. + GrContext* fContext; GrRenderTargetContext* fRenderTargetContext; const GrClip* fClip; + const SkIRect* fClipConservativeBounds; const SkMatrix* fViewMatrix; GrAAType fAAType; const GrShape* fShape; @@ -193,6 +178,7 @@ public: void validate() const { SkASSERT(fContext); SkASSERT(fRenderTargetContext); + SkASSERT(fClipConservativeBounds); SkASSERT(fViewMatrix); SkASSERT(fShape); SkASSERT(fShape->style().isSimpleFill()); @@ -275,12 +261,12 @@ private: ); GrPaint paint; - DrawPathArgs drawArgs{args.fContext, std::move(paint), &kIncrementStencil, args.fRenderTargetContext, nullptr, // clip + args.fClipConservativeBounds, args.fViewMatrix, args.fShape, args.fAAType, diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp index 4a39f256fe..466f90a890 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -50,6 +50,12 @@ GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& opti // AA hairline path renderer is very specialized - no other renderer can do this job well fChain.push_back(sk_make_sp<GrAAHairLinePathRenderer>()); + if (options.fGpuPathRenderers & GpuPathRenderers::kCoverageCounting) { + if (auto ccpr = GrCoverageCountingPathRenderer::CreateIfSupported(*context->caps())) { + context->contextPriv().addOnFlushCallbackObject(ccpr.get()); + fChain.push_back(std::move(ccpr)); + } + } if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) { fChain.push_back(sk_make_sp<GrAAConvexPathRenderer>()); } @@ -59,12 +65,6 @@ GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& opti if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) { fChain.push_back(sk_make_sp<GrSmallPathRenderer>()); } - if (options.fGpuPathRenderers & GpuPathRenderers::kCoverageCounting) { - if (auto ccpr = GrCoverageCountingPathRenderer::CreateIfSupported(*context->caps())) { - context->contextPriv().addOnFlushCallbackObject(ccpr.get()); - fChain.push_back(std::move(ccpr)); - } - } if (options.fGpuPathRenderers & GpuPathRenderers::kTessellating) { fChain.push_back(sk_make_sp<GrTessellatingPathRenderer>()); } diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp index ed5ce8a52d..22316c5c0a 100644 --- a/src/gpu/GrReducedClip.cpp +++ b/src/gpu/GrReducedClip.cpp @@ -743,6 +743,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, GrShape shape(clipPath, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; canDrawArgs.fCaps = context->caps(); + canDrawArgs.fClipConservativeBounds = &stencilClip.fixedClip().scissorRect(); canDrawArgs.fViewMatrix = &SkMatrix::I(); canDrawArgs.fShape = &shape; canDrawArgs.fAAType = aaType; @@ -793,6 +794,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, &kDrawToStencil, renderTargetContext, &stencilClip.fixedClip(), + &stencilClip.fixedClip().scissorRect(), &SkMatrix::I(), &shape, aaType, @@ -803,6 +805,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, args.fContext = context; args.fRenderTargetContext = renderTargetContext; args.fClip = &stencilClip.fixedClip(); + args.fClipConservativeBounds = &stencilClip.fixedClip().scissorRect(); args.fViewMatrix = &SkMatrix::I(); args.fAAType = aaType; args.fShape = &shape; @@ -829,6 +832,7 @@ bool GrReducedClip::drawStencilClipMask(GrContext* context, *pass, renderTargetContext, &stencilClip, + &stencilClip.fixedClip().scissorRect(), &SkMatrix::I(), &shape, aaType, diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 8828f274ee..561eaef340 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1607,11 +1607,16 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip, GrAAType aaType = fRenderTargetContext->chooseAAType(aa, GrAllowMixedSamples::kNo); bool hasUserStencilSettings = !ss->isUnused(); + SkIRect clipConservativeBounds; + clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(), + &clipConservativeBounds, nullptr); + GrShape shape(path, GrStyle::SimpleFill()); GrPathRenderer::CanDrawPathArgs canDrawArgs; canDrawArgs.fCaps = fRenderTargetContext->drawingManager()->getContext()->caps(); canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; + canDrawArgs.fClipConservativeBounds = &clipConservativeBounds; canDrawArgs.fAAType = aaType; canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; @@ -1631,6 +1636,7 @@ bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip, ss, fRenderTargetContext, &clip, + &clipConservativeBounds, &viewMatrix, &shape, aaType, @@ -1661,6 +1667,9 @@ void GrRenderTargetContext::internalDrawPath(const GrClip& clip, RETURN_IF_ABANDONED GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext); + SkIRect clipConservativeBounds; + clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr); + SkASSERT(!path.isEmpty()); GrShape shape; // NVPR cannot handle hairlines, so this would get picked up by a different stencil and @@ -1673,6 +1682,7 @@ void GrRenderTargetContext::internalDrawPath(const GrClip& clip, canDrawArgs.fCaps = this->drawingManager()->getContext()->caps(); canDrawArgs.fViewMatrix = &viewMatrix; canDrawArgs.fShape = &shape; + canDrawArgs.fClipConservativeBounds = &clipConservativeBounds; canDrawArgs.fHasUserStencilSettings = false; GrPathRenderer* pr; @@ -1728,6 +1738,7 @@ void GrRenderTargetContext::internalDrawPath(const GrClip& clip, &GrUserStencilSettings::kUnused, this, &clip, + &clipConservativeBounds, &viewMatrix, &shape, aaType, diff --git a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp index 4aff0a918c..0e6198951e 100644 --- a/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp +++ b/src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp @@ -54,6 +54,27 @@ GrCoverageCountingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const return CanDrawPath::kNo; } + SkRect devBounds; + SkIRect devIBounds; + args.fViewMatrix->mapRect(&devBounds, path.getBounds()); + devBounds.roundOut(&devIBounds); + if (!devIBounds.intersect(*args.fClipConservativeBounds)) { + // Path is completely clipped away. Our code will eventually notice this before doing any + // real work. + return CanDrawPath::kYes; + } + + if (devIBounds.height() * devIBounds.width() > 256 * 256) { + // Large paths can blow up the atlas fast. And they are not ideal for a two-pass rendering + // algorithm. Give the simpler direct renderers a chance before we commit to drawing it. + return CanDrawPath::kAsBackup; + } + + if (args.fShape->hasUnstyledKey() && path.countVerbs() > 50) { + // Complex paths do better cached in an SDF, if the renderer will accept them. + return CanDrawPath::kAsBackup; + } + return CanDrawPath::kYes; } diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp index 0ae5d55bda..62bf0595b3 100644 --- a/tests/TessellatingPathRendererTests.cpp +++ b/tests/TessellatingPathRendererTests.cpp @@ -399,6 +399,8 @@ static void test_path(GrContext* ctx, } GrNoClip noClip; + SkIRect clipConservativeBounds = SkIRect::MakeWH(renderTargetContext->width(), + renderTargetContext->height()); GrStyle style(SkStrokeRec::kFill_InitStyle); GrShape shape(path, style); GrPathRenderer::DrawPathArgs args{ctx, @@ -406,6 +408,7 @@ static void test_path(GrContext* ctx, &GrUserStencilSettings::kUnused, renderTargetContext, &noClip, + &clipConservativeBounds, &matrix, &shape, aaType, |