blob: b9600549d7c5a324c978932232f232de0d32f7f0 [file] [log] [blame]
Chris Daltonb832ce62020-01-06 19:49:37 -07001/*
2 * Copyright 2019 Google LLC.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Chris Dalton0a22b1e2020-03-26 11:52:15 -06008#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
Chris Daltonb832ce62020-01-06 19:49:37 -07009
Chris Dalton50c3c242021-06-14 16:32:35 -060010#include "include/private/SkVx.h"
Chris Daltonb832ce62020-01-06 19:49:37 -070011#include "src/core/SkPathPriv.h"
12#include "src/gpu/GrClip.h"
13#include "src/gpu/GrMemoryPool.h"
14#include "src/gpu/GrRecordingContextPriv.h"
Chris Dalton50c3c242021-06-14 16:32:35 -060015#include "src/gpu/GrVx.h"
Robert Phillips550de7f2021-07-06 16:28:52 -040016#include "src/gpu/effects/GrDisableColorXP.h"
Michael Ludwig2686d692020-04-17 20:21:37 +000017#include "src/gpu/geometry/GrStyledShape.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070018#include "src/gpu/tessellate/GrPathInnerTriangulateOp.h"
Chris Dalton031d76b2021-06-08 16:32:00 -060019#include "src/gpu/tessellate/GrPathStencilCoverOp.h"
Chris Dalton7ae272f2021-06-10 11:45:14 -060020#include "src/gpu/tessellate/GrPathTessellateOp.h"
Chris Dalton05007df2021-02-04 00:24:52 -070021#include "src/gpu/tessellate/GrStrokeTessellateOp.h"
Robert Phillips4dca8312021-07-28 15:13:20 -040022#include "src/gpu/v1/SurfaceDrawContext_v1.h"
Chris Daltond2dc8dd2020-05-19 16:32:02 -060023
Chris Dalton1413d112020-07-09 11:26:31 -060024bool GrTessellationPathRenderer::IsSupported(const GrCaps& caps) {
Chris Dalton8f282f52021-01-06 11:47:58 -070025 return !caps.avoidStencilBuffers() &&
26 caps.drawInstancedSupport() &&
Chris Daltoneae5c162020-12-29 10:18:21 -070027 !caps.disableTessellationPathRenderer();
Chris Dalton1413d112020-07-09 11:26:31 -060028}
29
Chris Dalton7ae272f2021-06-10 11:45:14 -060030GrPathRenderer::StencilSupport GrTessellationPathRenderer::onGetStencilSupport(
31 const GrStyledShape& shape) const {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060032 if (!shape.style().isSimpleFill() || shape.inverseFilled()) {
33 // Don't bother with stroke stencilling or inverse fills yet. The Skia API doesn't support
34 // clipping by a stroke, and the stencilling code already knows how to invert a fill.
Chris Dalton7ae272f2021-06-10 11:45:14 -060035 return kNoSupport_StencilSupport;
36 }
37 return shape.knownToBeConvex() ? kNoRestriction_StencilSupport : kStencilOnly_StencilSupport;
38}
39
Chris Dalton0a22b1e2020-03-26 11:52:15 -060040GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath(
Chris Daltonb832ce62020-01-06 19:49:37 -070041 const CanDrawPathArgs& args) const {
Chris Dalton1c62a7b2020-06-29 22:01:14 -060042 const GrStyledShape& shape = *args.fShape;
Chris Dalton57ab06c2021-04-22 12:57:28 -060043 if (args.fAAType == GrAAType::kCoverage ||
44 shape.style().hasPathEffect() ||
Chris Dalton06b52ad2020-12-15 10:01:35 -070045 args.fViewMatrix->hasPerspective() ||
46 shape.style().strokeRec().getStyle() == SkStrokeRec::kStrokeAndFill_Style ||
Chris Dalton537293bf2021-05-03 15:54:24 -060047 !args.fProxy->canUseStencil(*args.fCaps)) {
Chris Daltonb832ce62020-01-06 19:49:37 -070048 return CanDrawPath::kNo;
49 }
Chris Daltona05ccc32021-06-29 19:42:13 -060050 if (!shape.style().isSimpleFill()) {
Chris Daltonbb995e62021-07-01 10:58:55 -060051 if (shape.inverseFilled()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060052 return CanDrawPath::kNo;
53 }
54 }
Chris Dalton7ae272f2021-06-10 11:45:14 -060055 if (args.fHasUserStencilSettings) {
56 // Non-convex paths and strokes use the stencil buffer internally, so they can't support
57 // draws with stencil settings.
Chris Daltonbaae2dd2021-06-25 14:52:49 -060058 if (!shape.style().isSimpleFill() || !shape.knownToBeConvex() || shape.inverseFilled()) {
Chris Dalton7ae272f2021-06-10 11:45:14 -060059 return CanDrawPath::kNo;
60 }
61 }
Chris Daltonb832ce62020-01-06 19:49:37 -070062 return CanDrawPath::kYes;
63}
64
Chris Dalton7ae272f2021-06-10 11:45:14 -060065static GrOp::Owner make_non_convex_fill_op(GrRecordingContext* rContext,
66 GrTessellationPathRenderer::PathFlags pathFlags,
Chris Daltonbaae2dd2021-06-25 14:52:49 -060067 GrAAType aaType, const SkRect& drawBounds,
Chris Dalton7ae272f2021-06-10 11:45:14 -060068 const SkMatrix& viewMatrix, const SkPath& path,
69 GrPaint&& paint) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060070 SkASSERT(!path.isConvex() || path.isInverseFillType());
Chris Dalton7ae272f2021-06-10 11:45:14 -060071 int numVerbs = path.countVerbs();
Chris Daltonbaae2dd2021-06-25 14:52:49 -060072 if (numVerbs > 0 && !path.isInverseFillType()) {
Chris Dalton7ae272f2021-06-10 11:45:14 -060073 // Check if the path is large and/or simple enough that we can triangulate the inner fan
74 // on the CPU. This is our fastest approach. It allows us to stencil only the curves,
75 // and then fill the inner fan directly to the final render target, thus drawing the
76 // majority of pixels in a single render pass.
Chris Daltonbaae2dd2021-06-25 14:52:49 -060077 float gpuFragmentWork = drawBounds.height() * drawBounds.width();
Chris Dalton7ae272f2021-06-10 11:45:14 -060078 float cpuTessellationWork = numVerbs * SkNextLog2(numVerbs); // N log N.
79 constexpr static float kCpuWeight = 512;
80 constexpr static float kMinNumPixelsToTriangulate = 256 * 256;
81 if (cpuTessellationWork * kCpuWeight + kMinNumPixelsToTriangulate < gpuFragmentWork) {
82 return GrOp::Make<GrPathInnerTriangulateOp>(rContext, viewMatrix, path,
83 std::move(paint), aaType, pathFlags,
Chris Daltonbaae2dd2021-06-25 14:52:49 -060084 drawBounds);
Chris Dalton70a0d2c2021-01-26 12:01:21 -070085 }
Chris Daltonc2a17462020-12-09 16:46:22 -070086 }
Chris Dalton7ae272f2021-06-10 11:45:14 -060087 return GrOp::Make<GrPathStencilCoverOp>(rContext, viewMatrix, path, std::move(paint), aaType,
Chris Daltonbaae2dd2021-06-25 14:52:49 -060088 pathFlags, drawBounds);
Chris Daltonc2a17462020-12-09 16:46:22 -070089}
90
Chris Dalton0a22b1e2020-03-26 11:52:15 -060091bool GrTessellationPathRenderer::onDrawPath(const DrawPathArgs& args) {
Robert Phillips4dca8312021-07-28 15:13:20 -040092 auto sdc = args.fSurfaceDrawContext;
Chris Daltonb832ce62020-01-06 19:49:37 -070093
Chris Dalton7ae272f2021-06-10 11:45:14 -060094 SkPath path;
95 args.fShape->asPath(&path);
96
97 // Handle strokes first.
98 if (!args.fShape->style().isSimpleFill()) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -060099 SkASSERT(!path.isInverseFillType()); // See onGetStencilSupport().
Chris Dalton7ae272f2021-06-10 11:45:14 -0600100 SkASSERT(args.fUserStencilSettings->isUnused());
101 const SkStrokeRec& stroke = args.fShape->style().strokeRec();
102 SkASSERT(stroke.getStyle() != SkStrokeRec::kStrokeAndFill_Style);
103 auto op = GrOp::Make<GrStrokeTessellateOp>(args.fContext, args.fAAType, *args.fViewMatrix,
104 path, stroke, std::move(args.fPaint));
Robert Phillips4dca8312021-07-28 15:13:20 -0400105 sdc->addDrawOp(args.fClip, std::move(op));
Chris Dalton7ae272f2021-06-10 11:45:14 -0600106 return true;
107 }
108
Chris Daltonc3176002021-07-23 15:33:09 -0600109 // Handle empty paths.
Chris Dalton2346aa02021-07-14 22:55:35 -0600110 const SkRect pathDevBounds = args.fViewMatrix->mapRect(args.fShape->bounds());
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600111 if (pathDevBounds.isEmpty()) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600112 if (path.isInverseFillType()) {
113 args.fSurfaceDrawContext->drawPaint(args.fClip, std::move(args.fPaint),
114 *args.fViewMatrix);
115 }
116 return true;
117 }
Chris Daltonb96995d2020-06-04 16:44:29 -0600118
Chris Daltonc3176002021-07-23 15:33:09 -0600119 // Handle convex paths.
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600120 if (args.fShape->knownToBeConvex() && !path.isInverseFillType()) {
Chris Dalton7ae272f2021-06-10 11:45:14 -0600121 auto op = GrOp::Make<GrPathTessellateOp>(args.fContext, *args.fViewMatrix, path,
122 std::move(args.fPaint), args.fAAType,
123 args.fUserStencilSettings, pathDevBounds);
Robert Phillips4dca8312021-07-28 15:13:20 -0400124 sdc->addDrawOp(args.fClip, std::move(op));
Chris Dalton7ae272f2021-06-10 11:45:14 -0600125 return true;
Chris Daltonb96995d2020-06-04 16:44:29 -0600126 }
Chris Dalton7ae272f2021-06-10 11:45:14 -0600127
128 SkASSERT(args.fUserStencilSettings->isUnused()); // See onGetStencilSupport().
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600129 const SkRect& drawBounds = path.isInverseFillType()
130 ? args.fSurfaceDrawContext->asSurfaceProxy()->backingStoreBoundsRect()
131 : pathDevBounds;
132 auto op = make_non_convex_fill_op(args.fContext, PathFlags::kNone, args.fAAType, drawBounds,
Chris Dalton7ae272f2021-06-10 11:45:14 -0600133 *args.fViewMatrix, path, std::move(args.fPaint));
Robert Phillips4dca8312021-07-28 15:13:20 -0400134 sdc->addDrawOp(args.fClip, std::move(op));
Chris Dalton4e998532020-02-10 11:06:42 -0700135 return true;
136}
137
Chris Dalton7ae272f2021-06-10 11:45:14 -0600138void GrTessellationPathRenderer::onStencilPath(const StencilPathArgs& args) {
139 SkASSERT(args.fShape->style().isSimpleFill()); // See onGetStencilSupport().
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600140 SkASSERT(!args.fShape->inverseFilled()); // See onGetStencilSupport().
Chris Dalton7ae272f2021-06-10 11:45:14 -0600141
Robert Phillips4dca8312021-07-28 15:13:20 -0400142 auto sdc = args.fSurfaceDrawContext;
Chris Dalton7ae272f2021-06-10 11:45:14 -0600143 GrAAType aaType = (GrAA::kYes == args.fDoStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
144
145 SkRect pathDevBounds;
146 args.fViewMatrix->mapRect(&pathDevBounds, args.fShape->bounds());
147
148 SkPath path;
149 args.fShape->asPath(&path);
150
151 if (args.fShape->knownToBeConvex()) {
152 constexpr static GrUserStencilSettings kMarkStencil(
153 GrUserStencilSettings::StaticInit<
154 0x0001,
155 GrUserStencilTest::kAlways,
156 0xffff,
157 GrUserStencilOp::kReplace,
158 GrUserStencilOp::kKeep,
159 0xffff>());
160
161 GrPaint stencilPaint;
162 stencilPaint.setXPFactory(GrDisableColorXPFactory::Get());
163 auto op = GrOp::Make<GrPathTessellateOp>(args.fContext, *args.fViewMatrix, path,
164 std::move(stencilPaint), aaType, &kMarkStencil,
165 pathDevBounds);
Robert Phillips4dca8312021-07-28 15:13:20 -0400166 sdc->addDrawOp(args.fClip, std::move(op));
Chris Dalton7ae272f2021-06-10 11:45:14 -0600167 return;
Chris Daltonb0643342020-12-15 01:04:12 -0700168 }
169
Chris Dalton7ae272f2021-06-10 11:45:14 -0600170 auto op = make_non_convex_fill_op(args.fContext, PathFlags::kStencilOnly, aaType, pathDevBounds,
171 *args.fViewMatrix, path, GrPaint());
Robert Phillips4dca8312021-07-28 15:13:20 -0400172 sdc->addDrawOp(args.fClip, std::move(op));
Chris Dalton7ae272f2021-06-10 11:45:14 -0600173}