aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Chris Dalton <csmartdalton@google.com>2017-09-08 16:25:08 -0600
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-09-12 20:04:20 +0000
commitdb91c6e7fbfc9d1d8fd203f7e08eefb602e4a0b9 (patch)
treecb13d0253d2161a7e995bc94fc8cedb85df7dd04
parenta640c49b7ecf667696542143edec96d10a940592 (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.cpp4
-rw-r--r--src/gpu/GrClipStackClip.h1
-rw-r--r--src/gpu/GrPathRenderer.h44
-rw-r--r--src/gpu/GrPathRendererChain.cpp12
-rw-r--r--src/gpu/GrReducedClip.cpp4
-rw-r--r--src/gpu/GrRenderTargetContext.cpp11
-rw-r--r--src/gpu/ccpr/GrCoverageCountingPathRenderer.cpp21
-rw-r--r--tests/TessellatingPathRendererTests.cpp3
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,