blob: 0a69e0a9edc3346fb52f9c8f0cf276faa61c3b38 [file] [log] [blame]
Chris Daltonebb37e72021-01-27 17:59:45 -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
8#include "src/gpu/tessellate/GrPathInnerTriangulateOp.h"
9
10#include "src/gpu/GrEagerVertexAllocator.h"
Chris Daltond9bdc322021-06-01 19:22:05 -060011#include "src/gpu/GrGpu.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070012#include "src/gpu/GrInnerFanTriangulator.h"
13#include "src/gpu/GrOpFlushState.h"
14#include "src/gpu/GrRecordingContextPriv.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040015#include "src/gpu/GrResourceProvider.h"
Chris Dalton2f733ec2021-06-01 12:11:57 -060016#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
Chris Daltond9bdc322021-06-01 19:22:05 -060017#include "src/gpu/tessellate/GrPathCurveTessellator.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070018#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
Chris Dalton3b412782021-06-01 13:40:03 -060019#include "src/gpu/tessellate/shaders/GrPathTessellationShader.h"
Chris Daltonebb37e72021-01-27 17:59:45 -070020
Chris Dalton917f9192021-06-08 14:32:37 -060021using PathFlags = GrTessellationPathRenderer::PathFlags;
Chris Daltonebb37e72021-01-27 17:59:45 -070022
Chris Dalton2f733ec2021-06-01 12:11:57 -060023namespace {
24
25// Fills an array of convex hulls surrounding 4-point cubic or conic instances. This shader is used
Chris Dalton031d76b2021-06-08 16:32:00 -060026// for the "cover" pass after the curves have been fully stencilled.
Chris Dalton2f733ec2021-06-01 12:11:57 -060027class HullShader : public GrPathTessellationShader {
28public:
Chris Daltona05ccc32021-06-29 19:42:13 -060029 HullShader(const SkMatrix& viewMatrix, SkPMColor4f color, const GrShaderCaps& shaderCaps)
Chris Dalton2f733ec2021-06-01 12:11:57 -060030 : GrPathTessellationShader(kTessellate_HullShader_ClassID,
31 GrPrimitiveType::kTriangleStrip, 0, viewMatrix, color) {
32 constexpr static Attribute kPtsAttribs[] = {
Chris Dalton202441f2021-06-30 22:48:30 -060033 {"p01", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
34 {"p23", kFloat4_GrVertexAttribType, kFloat4_GrSLType}};
Chris Dalton2f733ec2021-06-01 12:11:57 -060035 this->setInstanceAttributes(kPtsAttribs, SK_ARRAY_COUNT(kPtsAttribs));
Chris Daltona05ccc32021-06-29 19:42:13 -060036 if (!shaderCaps.vertexIDSupport()) {
37 constexpr static Attribute kVertexIdxAttrib("vertexidx", kFloat_GrVertexAttribType,
38 kFloat_GrSLType);
39 this->setVertexAttributes(&kVertexIdxAttrib, 1);
40 }
Chris Dalton2f733ec2021-06-01 12:11:57 -060041 }
42
43private:
Chris Daltonb63711a2021-06-01 14:52:02 -060044 const char* name() const final { return "tessellate_HullShader"; }
Chris Dalton2f733ec2021-06-01 12:11:57 -060045 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const final {}
46 GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const final;
47};
48
49GrGLSLGeometryProcessor* HullShader::createGLSLInstance(const GrShaderCaps&) const {
50 class Impl : public GrPathTessellationShader::Impl {
Chris Dalton69043032021-07-01 11:17:53 -060051 void emitVertexCode(const GrShaderCaps& shaderCaps, const GrPathTessellationShader&,
52 GrGLSLVertexBuilder* v, GrGPArgs* gpArgs) override {
Chris Dalton2f733ec2021-06-01 12:11:57 -060053 v->codeAppend(R"(
Chris Dalton202441f2021-06-30 22:48:30 -060054 float2 p0=p01.xy, p1=p01.zw, p2=p23.xy, p3=p23.zw;
Chris Dalton3febc612021-07-14 13:47:07 -060055 if (isinf(p3.y)) { // Is the curve a conic?
Chris Dalton202441f2021-06-30 22:48:30 -060056 float w = p3.x;
57 p3 = p2;
Chris Dalton528673a2021-07-16 15:59:18 -060058 // A conic with w=Inf is an exact triangle.
59 // NOTE: "isinf == false" works on Mac Radeon GLSL. "!isinf" gets the wrong answer.
60 if (isinf(w) == false) {
Chris Dalton2f733ec2021-06-01 12:11:57 -060061 // Convert the points to a trapeziodal hull that circumcscribes the conic.
Chris Dalton202441f2021-06-30 22:48:30 -060062 float2 p1w = p1 * w;
Chris Dalton2f733ec2021-06-01 12:11:57 -060063 float T = .51; // Bias outward a bit to ensure we cover the outermost samples.
Chris Dalton202441f2021-06-30 22:48:30 -060064 float2 c1 = mix(p0, p1w, T);
65 float2 c2 = mix(p2, p1w, T);
Chris Dalton2f733ec2021-06-01 12:11:57 -060066 float iw = 1 / mix(1, w, T);
Chris Dalton202441f2021-06-30 22:48:30 -060067 p2 = c2 * iw;
68 p1 = c1 * iw;
Chris Dalton2f733ec2021-06-01 12:11:57 -060069 }
70 }
71
72 // Translate the points to v0..3 where v0=0.
Chris Dalton202441f2021-06-30 22:48:30 -060073 float2 v1 = p1 - p0;
74 float2 v2 = p2 - p0;
75 float2 v3 = p3 - p0;
Chris Dalton2f733ec2021-06-01 12:11:57 -060076
77 // Reorder the points so v2 bisects v1 and v3.
Chris Dalton202441f2021-06-30 22:48:30 -060078 if (sign(cross(v2, v1)) == sign(cross(v2, v3))) {
79 float2 tmp = p2;
80 if (sign(cross(v1, v2)) != sign(cross(v1, v3))) {
81 p2 = p1; // swap(p2, p1)
82 p1 = tmp;
Chris Dalton2f733ec2021-06-01 12:11:57 -060083 } else {
Chris Dalton202441f2021-06-30 22:48:30 -060084 p2 = p3; // swap(p2, p3)
85 p3 = tmp;
Chris Dalton2f733ec2021-06-01 12:11:57 -060086 }
Chris Daltona05ccc32021-06-29 19:42:13 -060087 })");
88
Chris Dalton69043032021-07-01 11:17:53 -060089 if (shaderCaps.vertexIDSupport()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060090 // If we don't have sk_VertexID support then "vertexidx" already came in as a
91 // vertex attrib.
92 v->codeAppend(R"(
93 // sk_VertexID comes in fan order. Convert to strip order.
94 int vertexidx = sk_VertexID;
95 vertexidx ^= vertexidx >> 1;)");
Chris Dalton2f733ec2021-06-01 12:11:57 -060096 }
97
Chris Daltona05ccc32021-06-29 19:42:13 -060098 v->codeAppend(R"(
Chris Dalton2f733ec2021-06-01 12:11:57 -060099 // Find the "turn direction" of each corner and net turn direction.
100 float vertexdir = 0;
101 float netdir = 0;
Chris Daltona05ccc32021-06-29 19:42:13 -0600102 float2 prev, next;
103 float dir;
104 float2 localcoord;
105 float2 nextcoord;)");
106
Chris Dalton2f733ec2021-06-01 12:11:57 -0600107 for (int i = 0; i < 4; ++i) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600108 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600109 prev = p%i - p%i;)", i, (i + 3) % 4);
Chris Daltona05ccc32021-06-29 19:42:13 -0600110 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600111 next = p%i - p%i;)", (i + 1) % 4, i);
Chris Daltona05ccc32021-06-29 19:42:13 -0600112 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600113 dir = sign(cross(prev, next));
Chris Daltona05ccc32021-06-29 19:42:13 -0600114 if (vertexidx == %i) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600115 vertexdir = dir;
Chris Dalton202441f2021-06-30 22:48:30 -0600116 localcoord = p%i;
117 nextcoord = p%i;
Chris Dalton2f733ec2021-06-01 12:11:57 -0600118 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600119 netdir += dir;)", i, i, (i + 1) % 4);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600120 }
121
Chris Daltona05ccc32021-06-29 19:42:13 -0600122 v->codeAppend(R"(
Chris Dalton2f733ec2021-06-01 12:11:57 -0600123 // Remove the non-convex vertex, if any.
124 if (vertexdir != sign(netdir)) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600125 localcoord = nextcoord;
Chris Dalton2f733ec2021-06-01 12:11:57 -0600126 }
127
Chris Dalton2f733ec2021-06-01 12:11:57 -0600128 float2 vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;)");
129 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
130 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
131 }
132 };
133 return new Impl;
134}
135
136} // namespace
137
Robert Phillips294723d2021-06-17 09:23:58 -0400138void GrPathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const {
Chris Daltonebb37e72021-01-27 17:59:45 -0700139 if (fPipelineForFills) {
Robert Phillips294723d2021-06-17 09:23:58 -0400140 fPipelineForFills->visitProxies(func);
Chris Daltonebb37e72021-01-27 17:59:45 -0700141 } else {
Robert Phillips294723d2021-06-17 09:23:58 -0400142 fProcessors.visitProxies(func);
Chris Daltonebb37e72021-01-27 17:59:45 -0700143 }
144}
145
146GrDrawOp::FixedFunctionFlags GrPathInnerTriangulateOp::fixedFunctionFlags() const {
147 auto flags = FixedFunctionFlags::kUsesStencil;
148 if (GrAAType::kNone != fAAType) {
149 flags |= FixedFunctionFlags::kUsesHWAA;
150 }
151 return flags;
152}
153
154GrProcessorSet::Analysis GrPathInnerTriangulateOp::finalize(const GrCaps& caps,
155 const GrAppliedClip* clip,
Chris Daltonebb37e72021-01-27 17:59:45 -0700156 GrClampType clampType) {
Chris Dalton57ab06c2021-04-22 12:57:28 -0600157 return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
158 clampType, &fColor);
Chris Daltonebb37e72021-01-27 17:59:45 -0700159}
160
Chris Dalton2f733ec2021-06-01 12:11:57 -0600161void GrPathInnerTriangulateOp::pushFanStencilProgram(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700162 const GrPipeline* pipelineForStencils,
163 const GrUserStencilSettings* stencil) {
164 SkASSERT(pipelineForStencils);
Chris Daltonb63711a2021-06-01 14:52:02 -0600165 auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
166 SK_PMColor4fTRANSPARENT);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600167 fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, pipelineForStencils,
168 stencil)); }
Chris Daltonebb37e72021-01-27 17:59:45 -0700169
Chris Dalton2f733ec2021-06-01 12:11:57 -0600170void GrPathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700171 const GrUserStencilSettings* stencil) {
172 SkASSERT(fPipelineForFills);
Chris Daltonb63711a2021-06-01 14:52:02 -0600173 auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
174 fColor);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600175 fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, fPipelineForFills,
176 stencil));
Chris Daltonebb37e72021-01-27 17:59:45 -0700177}
178
Chris Dalton2f733ec2021-06-01 12:11:57 -0600179void GrPathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700180 GrAppliedClip&& appliedClip) {
181 SkASSERT(!fFanTriangulator);
182 SkASSERT(!fFanPolys);
183 SkASSERT(!fPipelineForFills);
184 SkASSERT(!fTessellator);
185 SkASSERT(!fStencilCurvesProgram);
186 SkASSERT(fFanPrograms.empty());
Chris Dalton031d76b2021-06-08 16:32:00 -0600187 SkASSERT(!fCoverHullsProgram);
Chris Daltonebb37e72021-01-27 17:59:45 -0700188
189 if (fPath.countVerbs() <= 0) {
190 return;
191 }
192
Chris Dalton031d76b2021-06-08 16:32:00 -0600193 // If using wireframe, we have to fall back on a standard Redbook "stencil then cover" algorithm
Chris Dalton57ab06c2021-04-22 12:57:28 -0600194 // instead of bypassing the stencil buffer to fill the fan directly.
Chris Dalton917f9192021-06-08 14:32:37 -0600195 bool forceRedbookStencilPass = (fPathFlags & (PathFlags::kStencilOnly | PathFlags::kWireframe));
196 bool doFill = !(fPathFlags & PathFlags::kStencilOnly);
Chris Daltonebb37e72021-01-27 17:59:45 -0700197
198 bool isLinear;
199 fFanTriangulator = args.fArena->make<GrInnerFanTriangulator>(fPath, args.fArena);
200 fFanPolys = fFanTriangulator->pathToPolys(&fFanBreadcrumbs, &isLinear);
201
202 // Create a pipeline for stencil passes if needed.
203 const GrPipeline* pipelineForStencils = nullptr;
204 if (forceRedbookStencilPass || !isLinear) { // Curves always get stencilled.
Chris Dalton2f733ec2021-06-01 12:11:57 -0600205 pipelineForStencils = GrPathTessellationShader::MakeStencilOnlyPipeline(
Chris Dalton917f9192021-06-08 14:32:37 -0600206 args, fAAType, fPathFlags, appliedClip.hardClip());
Chris Daltonebb37e72021-01-27 17:59:45 -0700207 }
208
209 // Create a pipeline for fill passes if needed.
210 if (doFill) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600211 fPipelineForFills = GrTessellationShader::MakePipeline(args, fAAType,
212 std::move(appliedClip),
213 std::move(fProcessors));
Chris Daltonebb37e72021-01-27 17:59:45 -0700214 }
215
216 // Pass 1: Tessellate the outer curves into the stencil buffer.
217 if (!isLinear) {
Chris Dalton26666bd2021-06-08 16:25:46 -0600218 fTessellator = GrPathCurveTessellator::Make(args.fArena, fViewMatrix,
219 SK_PMColor4fTRANSPARENT,
Chris Daltond2b8ba32021-06-09 00:12:59 -0600220 GrPathCurveTessellator::DrawInnerFan::kNo,
Chris Dalton198ac152021-06-09 13:49:43 -0600221 fPath.countVerbs(), *pipelineForStencils,
222 *args.fCaps);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600223 const GrUserStencilSettings* stencilPathSettings =
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600224 GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
Chris Dalton2f733ec2021-06-01 12:11:57 -0600225 fStencilCurvesProgram = GrTessellationShader::MakeProgram(args, fTessellator->shader(),
226 pipelineForStencils,
227 stencilPathSettings);
Chris Daltonebb37e72021-01-27 17:59:45 -0700228 }
229
230 // Pass 2: Fill the path's inner fan with a stencil test against the curves.
231 if (fFanPolys) {
232 if (forceRedbookStencilPass) {
Chris Dalton031d76b2021-06-08 16:32:00 -0600233 // Use a standard Redbook "stencil then cover" algorithm instead of bypassing the
234 // stencil buffer to fill the fan directly.
Chris Dalton2f733ec2021-06-01 12:11:57 -0600235 const GrUserStencilSettings* stencilPathSettings =
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600236 GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
Chris Dalton2f733ec2021-06-01 12:11:57 -0600237 this->pushFanStencilProgram(args, pipelineForStencils, stencilPathSettings);
Chris Daltonebb37e72021-01-27 17:59:45 -0700238 if (doFill) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600239 this->pushFanFillProgram(args,
240 GrPathTessellationShader::TestAndResetStencilSettings());
Chris Daltonebb37e72021-01-27 17:59:45 -0700241 }
242 } else if (isLinear) {
243 // There are no outer curves! Ignore stencil and fill the path directly.
244 SkASSERT(!pipelineForStencils);
245 this->pushFanFillProgram(args, &GrUserStencilSettings::kUnused);
246 } else if (!fPipelineForFills->hasStencilClip()) {
247 // These are a twist on the standard Redbook stencil settings that allow us to fill the
248 // inner polygon directly to the final render target. By the time these programs
249 // execute, the outer curves will already be stencilled in. So if the stencil value is
250 // zero, then it means the sample in question is not affected by any curves and we can
251 // fill it in directly. If the stencil value is nonzero, then we don't fill and instead
252 // continue the standard Redbook counting process.
253 constexpr static GrUserStencilSettings kFillOrIncrDecrStencil(
254 GrUserStencilSettings::StaticInitSeparate<
255 0x0000, 0x0000,
256 GrUserStencilTest::kEqual, GrUserStencilTest::kEqual,
257 0xffff, 0xffff,
258 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep,
259 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap,
260 0xffff, 0xffff>());
261
262 constexpr static GrUserStencilSettings kFillOrInvertStencil(
263 GrUserStencilSettings::StaticInit<
264 0x0000,
265 GrUserStencilTest::kEqual,
266 0xffff,
267 GrUserStencilOp::kKeep,
268 // "Zero" instead of "Invert" because the fan only touches any given pixel once.
269 GrUserStencilOp::kZero,
270 0xffff>());
271
272 auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
273 ? &kFillOrIncrDecrStencil
274 : &kFillOrInvertStencil;
275 this->pushFanFillProgram(args, stencil);
276 } else {
277 // This is the same idea as above, but we use two passes instead of one because there is
278 // a stencil clip. The stencil test isn't expressive enough to do the above tests and
279 // also check the clip bit in a single pass.
280 constexpr static GrUserStencilSettings kFillIfZeroAndInClip(
281 GrUserStencilSettings::StaticInit<
282 0x0000,
283 GrUserStencilTest::kEqualIfInClip,
284 0xffff,
285 GrUserStencilOp::kKeep,
286 GrUserStencilOp::kKeep,
287 0xffff>());
288
289 constexpr static GrUserStencilSettings kIncrDecrStencilIfNonzero(
290 GrUserStencilSettings::StaticInitSeparate<
291 0x0000, 0x0000,
292 // No need to check the clip because the previous stencil pass will have only
293 // written to samples already inside the clip.
294 GrUserStencilTest::kNotEqual, GrUserStencilTest::kNotEqual,
295 0xffff, 0xffff,
296 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap,
297 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep,
298 0xffff, 0xffff>());
299
300 constexpr static GrUserStencilSettings kInvertStencilIfNonZero(
301 GrUserStencilSettings::StaticInit<
302 0x0000,
303 // No need to check the clip because the previous stencil pass will have only
304 // written to samples already inside the clip.
305 GrUserStencilTest::kNotEqual,
306 0xffff,
307 // "Zero" instead of "Invert" because the fan only touches any given pixel once.
308 GrUserStencilOp::kZero,
309 GrUserStencilOp::kKeep,
310 0xffff>());
311
312 // Pass 2a: Directly fill fan samples whose stencil values (from curves) are zero.
313 this->pushFanFillProgram(args, &kFillIfZeroAndInClip);
314
315 // Pass 2b: Redbook counting on fan samples whose stencil values (from curves) != 0.
316 auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
317 ? &kIncrDecrStencilIfNonzero
318 : &kInvertStencilIfNonZero;
319 this->pushFanStencilProgram(args, pipelineForStencils, stencil);
320 }
321 }
322
323 // Pass 3: Draw convex hulls around each curve.
324 if (doFill && !isLinear) {
325 // By the time this program executes, every pixel will be filled in except the ones touched
326 // by curves. We issue a final cover pass over the curves by drawing their convex hulls.
327 // This will fill in any remaining samples and reset the stencil values back to zero.
328 SkASSERT(fTessellator);
Chris Daltona05ccc32021-06-29 19:42:13 -0600329 auto* hullShader = args.fArena->make<HullShader>(fViewMatrix, fColor,
330 *args.fCaps->shaderCaps());
Chris Dalton031d76b2021-06-08 16:32:00 -0600331 fCoverHullsProgram = GrTessellationShader::MakeProgram(
Chris Daltonebb37e72021-01-27 17:59:45 -0700332 args, hullShader, fPipelineForFills,
Chris Dalton2f733ec2021-06-01 12:11:57 -0600333 GrPathTessellationShader::TestAndResetStencilSettings());
Chris Daltonebb37e72021-01-27 17:59:45 -0700334 }
335}
336
337void GrPathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
338 const GrSurfaceProxyView& writeView,
339 GrAppliedClip* clip,
John Stiles52cb1d02021-06-02 11:58:05 -0400340 const GrDstProxyView& dstProxyView,
Chris Daltonebb37e72021-01-27 17:59:45 -0700341 GrXferBarrierFlags renderPassXferBarriers,
342 GrLoadOp colorLoadOp) {
343 this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
344 renderPassXferBarriers, colorLoadOp, context->priv().caps()},
345 (clip) ? std::move(*clip) : GrAppliedClip::Disabled());
346 if (fStencilCurvesProgram) {
347 context->priv().recordProgramInfo(fStencilCurvesProgram);
348 }
349 for (const GrProgramInfo* fanProgram : fFanPrograms) {
350 context->priv().recordProgramInfo(fanProgram);
351 }
Chris Dalton031d76b2021-06-08 16:32:00 -0600352 if (fCoverHullsProgram) {
353 context->priv().recordProgramInfo(fCoverHullsProgram);
Chris Daltonebb37e72021-01-27 17:59:45 -0700354 }
355}
356
Chris Daltona05ccc32021-06-29 19:42:13 -0600357GR_DECLARE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);
358
Chris Daltonebb37e72021-01-27 17:59:45 -0700359void GrPathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
360 if (!fFanTriangulator) {
361 this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
362 &flushState->dstProxyView(), flushState->renderPassBarriers(),
363 flushState->colorLoadOp(), &flushState->caps()},
364 flushState->detachAppliedClip());
365 if (!fFanTriangulator) {
366 return;
367 }
368 }
369
370 if (fFanPolys) {
371 GrEagerDynamicVertexAllocator alloc(flushState, &fFanBuffer, &fBaseFanVertex);
372 fFanVertexCount = fFanTriangulator->polysToTriangles(fFanPolys, &alloc, &fFanBreadcrumbs);
373 }
374
375 if (fTessellator) {
376 // Must be called after polysToTriangles() in order for fFanBreadcrumbs to be complete.
Chris Dalton569c01b2021-05-25 10:11:46 -0600377 fTessellator->prepare(flushState, this->bounds(), fPath, &fFanBreadcrumbs);
Chris Daltonebb37e72021-01-27 17:59:45 -0700378 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600379
380 if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
381 constexpr static float kStripOrderIDs[4] = {0, 1, 3, 2};
382
383 GR_DEFINE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);
384
385 fHullVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
386 GrGpuBufferType::kVertex, sizeof(kStripOrderIDs), kStripOrderIDs,
387 gHullVertexBufferKey);
388 }
Chris Daltonebb37e72021-01-27 17:59:45 -0700389}
390
391void GrPathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
392 if (fStencilCurvesProgram) {
393 SkASSERT(fTessellator);
394 flushState->bindPipelineAndScissorClip(*fStencilCurvesProgram, this->bounds());
395 fTessellator->draw(flushState);
Chris Daltond9bdc322021-06-01 19:22:05 -0600396 if (flushState->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) {
397 flushState->gpu()->insertManualFramebufferBarrier(); // http://skbug.com/9739
398 }
Chris Daltonebb37e72021-01-27 17:59:45 -0700399 }
400
401 for (const GrProgramInfo* fanProgram : fFanPrograms) {
402 SkASSERT(fFanBuffer);
403 flushState->bindPipelineAndScissorClip(*fanProgram, this->bounds());
Robert Phillips787fd9d2021-03-22 14:48:09 -0400404 flushState->bindTextures(fanProgram->geomProc(), nullptr, fanProgram->pipeline());
Chris Daltonebb37e72021-01-27 17:59:45 -0700405 flushState->bindBuffers(nullptr, nullptr, fFanBuffer);
406 flushState->draw(fFanVertexCount, fBaseFanVertex);
407 }
408
Chris Dalton031d76b2021-06-08 16:32:00 -0600409 if (fCoverHullsProgram) {
Chris Daltonebb37e72021-01-27 17:59:45 -0700410 SkASSERT(fTessellator);
Chris Dalton031d76b2021-06-08 16:32:00 -0600411 flushState->bindPipelineAndScissorClip(*fCoverHullsProgram, this->bounds());
412 flushState->bindTextures(fCoverHullsProgram->geomProc(), nullptr, *fPipelineForFills);
Chris Daltona05ccc32021-06-29 19:42:13 -0600413 fTessellator->drawHullInstances(flushState, fHullVertexBufferIfNoIDSupport);
Chris Daltonebb37e72021-01-27 17:59:45 -0700414 }
415}