blob: 46f4dc93105b5063fe9d819dc90b9f1fecc73477 [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 {
53 v->insertFunction(SkSLPortable_isinf(shaderCaps));
Chris Dalton2f733ec2021-06-01 12:11:57 -060054 v->codeAppend(R"(
Chris Dalton202441f2021-06-30 22:48:30 -060055 float2 p0=p01.xy, p1=p01.zw, p2=p23.xy, p3=p23.zw;
56 if (isinf_portable(p3.y)) { // Is the curve a conic?
57 float w = p3.x;
58 p3 = p2;
59 if (!isinf_portable(w)) { // A conic with w=Inf is an exact triangle.
Chris Dalton2f733ec2021-06-01 12:11:57 -060060 // Convert the points to a trapeziodal hull that circumcscribes the conic.
Chris Dalton202441f2021-06-30 22:48:30 -060061 float2 p1w = p1 * w;
Chris Dalton2f733ec2021-06-01 12:11:57 -060062 float T = .51; // Bias outward a bit to ensure we cover the outermost samples.
Chris Dalton202441f2021-06-30 22:48:30 -060063 float2 c1 = mix(p0, p1w, T);
64 float2 c2 = mix(p2, p1w, T);
Chris Dalton2f733ec2021-06-01 12:11:57 -060065 float iw = 1 / mix(1, w, T);
Chris Dalton202441f2021-06-30 22:48:30 -060066 p2 = c2 * iw;
67 p1 = c1 * iw;
Chris Dalton2f733ec2021-06-01 12:11:57 -060068 }
69 }
70
71 // Translate the points to v0..3 where v0=0.
Chris Dalton202441f2021-06-30 22:48:30 -060072 float2 v1 = p1 - p0;
73 float2 v2 = p2 - p0;
74 float2 v3 = p3 - p0;
Chris Dalton2f733ec2021-06-01 12:11:57 -060075
76 // Reorder the points so v2 bisects v1 and v3.
Chris Dalton202441f2021-06-30 22:48:30 -060077 if (sign(cross(v2, v1)) == sign(cross(v2, v3))) {
78 float2 tmp = p2;
79 if (sign(cross(v1, v2)) != sign(cross(v1, v3))) {
80 p2 = p1; // swap(p2, p1)
81 p1 = tmp;
Chris Dalton2f733ec2021-06-01 12:11:57 -060082 } else {
Chris Dalton202441f2021-06-30 22:48:30 -060083 p2 = p3; // swap(p2, p3)
84 p3 = tmp;
Chris Dalton2f733ec2021-06-01 12:11:57 -060085 }
Chris Daltona05ccc32021-06-29 19:42:13 -060086 })");
87
Chris Dalton69043032021-07-01 11:17:53 -060088 if (shaderCaps.vertexIDSupport()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060089 // If we don't have sk_VertexID support then "vertexidx" already came in as a
90 // vertex attrib.
91 v->codeAppend(R"(
92 // sk_VertexID comes in fan order. Convert to strip order.
93 int vertexidx = sk_VertexID;
94 vertexidx ^= vertexidx >> 1;)");
Chris Dalton2f733ec2021-06-01 12:11:57 -060095 }
96
Chris Daltona05ccc32021-06-29 19:42:13 -060097 v->codeAppend(R"(
Chris Dalton2f733ec2021-06-01 12:11:57 -060098 // Find the "turn direction" of each corner and net turn direction.
99 float vertexdir = 0;
100 float netdir = 0;
Chris Daltona05ccc32021-06-29 19:42:13 -0600101 float2 prev, next;
102 float dir;
103 float2 localcoord;
104 float2 nextcoord;)");
105
Chris Dalton2f733ec2021-06-01 12:11:57 -0600106 for (int i = 0; i < 4; ++i) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600107 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600108 prev = p%i - p%i;)", i, (i + 3) % 4);
Chris Daltona05ccc32021-06-29 19:42:13 -0600109 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600110 next = p%i - p%i;)", (i + 1) % 4, i);
Chris Daltona05ccc32021-06-29 19:42:13 -0600111 v->codeAppendf(R"(
Chris Dalton202441f2021-06-30 22:48:30 -0600112 dir = sign(cross(prev, next));
Chris Daltona05ccc32021-06-29 19:42:13 -0600113 if (vertexidx == %i) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600114 vertexdir = dir;
Chris Dalton202441f2021-06-30 22:48:30 -0600115 localcoord = p%i;
116 nextcoord = p%i;
Chris Dalton2f733ec2021-06-01 12:11:57 -0600117 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600118 netdir += dir;)", i, i, (i + 1) % 4);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600119 }
120
Chris Daltona05ccc32021-06-29 19:42:13 -0600121 v->codeAppend(R"(
Chris Dalton2f733ec2021-06-01 12:11:57 -0600122 // Remove the non-convex vertex, if any.
123 if (vertexdir != sign(netdir)) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600124 localcoord = nextcoord;
Chris Dalton2f733ec2021-06-01 12:11:57 -0600125 }
126
Chris Dalton2f733ec2021-06-01 12:11:57 -0600127 float2 vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;)");
128 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
129 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
130 }
131 };
132 return new Impl;
133}
134
135} // namespace
136
Robert Phillips294723d2021-06-17 09:23:58 -0400137void GrPathInnerTriangulateOp::visitProxies(const GrVisitProxyFunc& func) const {
Chris Daltonebb37e72021-01-27 17:59:45 -0700138 if (fPipelineForFills) {
Robert Phillips294723d2021-06-17 09:23:58 -0400139 fPipelineForFills->visitProxies(func);
Chris Daltonebb37e72021-01-27 17:59:45 -0700140 } else {
Robert Phillips294723d2021-06-17 09:23:58 -0400141 fProcessors.visitProxies(func);
Chris Daltonebb37e72021-01-27 17:59:45 -0700142 }
143}
144
145GrDrawOp::FixedFunctionFlags GrPathInnerTriangulateOp::fixedFunctionFlags() const {
146 auto flags = FixedFunctionFlags::kUsesStencil;
147 if (GrAAType::kNone != fAAType) {
148 flags |= FixedFunctionFlags::kUsesHWAA;
149 }
150 return flags;
151}
152
153GrProcessorSet::Analysis GrPathInnerTriangulateOp::finalize(const GrCaps& caps,
154 const GrAppliedClip* clip,
Chris Daltonebb37e72021-01-27 17:59:45 -0700155 GrClampType clampType) {
Chris Dalton57ab06c2021-04-22 12:57:28 -0600156 return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
157 clampType, &fColor);
Chris Daltonebb37e72021-01-27 17:59:45 -0700158}
159
Chris Dalton2f733ec2021-06-01 12:11:57 -0600160void GrPathInnerTriangulateOp::pushFanStencilProgram(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700161 const GrPipeline* pipelineForStencils,
162 const GrUserStencilSettings* stencil) {
163 SkASSERT(pipelineForStencils);
Chris Daltonb63711a2021-06-01 14:52:02 -0600164 auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
165 SK_PMColor4fTRANSPARENT);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600166 fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, pipelineForStencils,
167 stencil)); }
Chris Daltonebb37e72021-01-27 17:59:45 -0700168
Chris Dalton2f733ec2021-06-01 12:11:57 -0600169void GrPathInnerTriangulateOp::pushFanFillProgram(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700170 const GrUserStencilSettings* stencil) {
171 SkASSERT(fPipelineForFills);
Chris Daltonb63711a2021-06-01 14:52:02 -0600172 auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena, fViewMatrix,
173 fColor);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600174 fFanPrograms.push_back(GrTessellationShader::MakeProgram(args, shader, fPipelineForFills,
175 stencil));
Chris Daltonebb37e72021-01-27 17:59:45 -0700176}
177
Chris Dalton2f733ec2021-06-01 12:11:57 -0600178void GrPathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
Chris Daltonebb37e72021-01-27 17:59:45 -0700179 GrAppliedClip&& appliedClip) {
180 SkASSERT(!fFanTriangulator);
181 SkASSERT(!fFanPolys);
182 SkASSERT(!fPipelineForFills);
183 SkASSERT(!fTessellator);
184 SkASSERT(!fStencilCurvesProgram);
185 SkASSERT(fFanPrograms.empty());
Chris Dalton031d76b2021-06-08 16:32:00 -0600186 SkASSERT(!fCoverHullsProgram);
Chris Daltonebb37e72021-01-27 17:59:45 -0700187
188 if (fPath.countVerbs() <= 0) {
189 return;
190 }
191
Chris Dalton031d76b2021-06-08 16:32:00 -0600192 // If using wireframe, we have to fall back on a standard Redbook "stencil then cover" algorithm
Chris Dalton57ab06c2021-04-22 12:57:28 -0600193 // instead of bypassing the stencil buffer to fill the fan directly.
Chris Dalton917f9192021-06-08 14:32:37 -0600194 bool forceRedbookStencilPass = (fPathFlags & (PathFlags::kStencilOnly | PathFlags::kWireframe));
195 bool doFill = !(fPathFlags & PathFlags::kStencilOnly);
Chris Daltonebb37e72021-01-27 17:59:45 -0700196
197 bool isLinear;
198 fFanTriangulator = args.fArena->make<GrInnerFanTriangulator>(fPath, args.fArena);
199 fFanPolys = fFanTriangulator->pathToPolys(&fFanBreadcrumbs, &isLinear);
200
201 // Create a pipeline for stencil passes if needed.
202 const GrPipeline* pipelineForStencils = nullptr;
203 if (forceRedbookStencilPass || !isLinear) { // Curves always get stencilled.
Chris Dalton2f733ec2021-06-01 12:11:57 -0600204 pipelineForStencils = GrPathTessellationShader::MakeStencilOnlyPipeline(
Chris Dalton917f9192021-06-08 14:32:37 -0600205 args, fAAType, fPathFlags, appliedClip.hardClip());
Chris Daltonebb37e72021-01-27 17:59:45 -0700206 }
207
208 // Create a pipeline for fill passes if needed.
209 if (doFill) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600210 fPipelineForFills = GrTessellationShader::MakePipeline(args, fAAType,
211 std::move(appliedClip),
212 std::move(fProcessors));
Chris Daltonebb37e72021-01-27 17:59:45 -0700213 }
214
215 // Pass 1: Tessellate the outer curves into the stencil buffer.
216 if (!isLinear) {
Chris Dalton26666bd2021-06-08 16:25:46 -0600217 fTessellator = GrPathCurveTessellator::Make(args.fArena, fViewMatrix,
218 SK_PMColor4fTRANSPARENT,
Chris Daltond2b8ba32021-06-09 00:12:59 -0600219 GrPathCurveTessellator::DrawInnerFan::kNo,
Chris Dalton198ac152021-06-09 13:49:43 -0600220 fPath.countVerbs(), *pipelineForStencils,
221 *args.fCaps);
Chris Dalton2f733ec2021-06-01 12:11:57 -0600222 const GrUserStencilSettings* stencilPathSettings =
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600223 GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
Chris Dalton2f733ec2021-06-01 12:11:57 -0600224 fStencilCurvesProgram = GrTessellationShader::MakeProgram(args, fTessellator->shader(),
225 pipelineForStencils,
226 stencilPathSettings);
Chris Daltonebb37e72021-01-27 17:59:45 -0700227 }
228
229 // Pass 2: Fill the path's inner fan with a stencil test against the curves.
230 if (fFanPolys) {
231 if (forceRedbookStencilPass) {
Chris Dalton031d76b2021-06-08 16:32:00 -0600232 // Use a standard Redbook "stencil then cover" algorithm instead of bypassing the
233 // stencil buffer to fill the fan directly.
Chris Dalton2f733ec2021-06-01 12:11:57 -0600234 const GrUserStencilSettings* stencilPathSettings =
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600235 GrPathTessellationShader::StencilPathSettings(GrFillRuleForSkPath(fPath));
Chris Dalton2f733ec2021-06-01 12:11:57 -0600236 this->pushFanStencilProgram(args, pipelineForStencils, stencilPathSettings);
Chris Daltonebb37e72021-01-27 17:59:45 -0700237 if (doFill) {
Chris Dalton2f733ec2021-06-01 12:11:57 -0600238 this->pushFanFillProgram(args,
239 GrPathTessellationShader::TestAndResetStencilSettings());
Chris Daltonebb37e72021-01-27 17:59:45 -0700240 }
241 } else if (isLinear) {
242 // There are no outer curves! Ignore stencil and fill the path directly.
243 SkASSERT(!pipelineForStencils);
244 this->pushFanFillProgram(args, &GrUserStencilSettings::kUnused);
245 } else if (!fPipelineForFills->hasStencilClip()) {
246 // These are a twist on the standard Redbook stencil settings that allow us to fill the
247 // inner polygon directly to the final render target. By the time these programs
248 // execute, the outer curves will already be stencilled in. So if the stencil value is
249 // zero, then it means the sample in question is not affected by any curves and we can
250 // fill it in directly. If the stencil value is nonzero, then we don't fill and instead
251 // continue the standard Redbook counting process.
252 constexpr static GrUserStencilSettings kFillOrIncrDecrStencil(
253 GrUserStencilSettings::StaticInitSeparate<
254 0x0000, 0x0000,
255 GrUserStencilTest::kEqual, GrUserStencilTest::kEqual,
256 0xffff, 0xffff,
257 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep,
258 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap,
259 0xffff, 0xffff>());
260
261 constexpr static GrUserStencilSettings kFillOrInvertStencil(
262 GrUserStencilSettings::StaticInit<
263 0x0000,
264 GrUserStencilTest::kEqual,
265 0xffff,
266 GrUserStencilOp::kKeep,
267 // "Zero" instead of "Invert" because the fan only touches any given pixel once.
268 GrUserStencilOp::kZero,
269 0xffff>());
270
271 auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
272 ? &kFillOrIncrDecrStencil
273 : &kFillOrInvertStencil;
274 this->pushFanFillProgram(args, stencil);
275 } else {
276 // This is the same idea as above, but we use two passes instead of one because there is
277 // a stencil clip. The stencil test isn't expressive enough to do the above tests and
278 // also check the clip bit in a single pass.
279 constexpr static GrUserStencilSettings kFillIfZeroAndInClip(
280 GrUserStencilSettings::StaticInit<
281 0x0000,
282 GrUserStencilTest::kEqualIfInClip,
283 0xffff,
284 GrUserStencilOp::kKeep,
285 GrUserStencilOp::kKeep,
286 0xffff>());
287
288 constexpr static GrUserStencilSettings kIncrDecrStencilIfNonzero(
289 GrUserStencilSettings::StaticInitSeparate<
290 0x0000, 0x0000,
291 // No need to check the clip because the previous stencil pass will have only
292 // written to samples already inside the clip.
293 GrUserStencilTest::kNotEqual, GrUserStencilTest::kNotEqual,
294 0xffff, 0xffff,
295 GrUserStencilOp::kIncWrap, GrUserStencilOp::kDecWrap,
296 GrUserStencilOp::kKeep, GrUserStencilOp::kKeep,
297 0xffff, 0xffff>());
298
299 constexpr static GrUserStencilSettings kInvertStencilIfNonZero(
300 GrUserStencilSettings::StaticInit<
301 0x0000,
302 // No need to check the clip because the previous stencil pass will have only
303 // written to samples already inside the clip.
304 GrUserStencilTest::kNotEqual,
305 0xffff,
306 // "Zero" instead of "Invert" because the fan only touches any given pixel once.
307 GrUserStencilOp::kZero,
308 GrUserStencilOp::kKeep,
309 0xffff>());
310
311 // Pass 2a: Directly fill fan samples whose stencil values (from curves) are zero.
312 this->pushFanFillProgram(args, &kFillIfZeroAndInClip);
313
314 // Pass 2b: Redbook counting on fan samples whose stencil values (from curves) != 0.
315 auto* stencil = (fPath.getFillType() == SkPathFillType::kWinding)
316 ? &kIncrDecrStencilIfNonzero
317 : &kInvertStencilIfNonZero;
318 this->pushFanStencilProgram(args, pipelineForStencils, stencil);
319 }
320 }
321
322 // Pass 3: Draw convex hulls around each curve.
323 if (doFill && !isLinear) {
324 // By the time this program executes, every pixel will be filled in except the ones touched
325 // by curves. We issue a final cover pass over the curves by drawing their convex hulls.
326 // This will fill in any remaining samples and reset the stencil values back to zero.
327 SkASSERT(fTessellator);
Chris Daltona05ccc32021-06-29 19:42:13 -0600328 auto* hullShader = args.fArena->make<HullShader>(fViewMatrix, fColor,
329 *args.fCaps->shaderCaps());
Chris Dalton031d76b2021-06-08 16:32:00 -0600330 fCoverHullsProgram = GrTessellationShader::MakeProgram(
Chris Daltonebb37e72021-01-27 17:59:45 -0700331 args, hullShader, fPipelineForFills,
Chris Dalton2f733ec2021-06-01 12:11:57 -0600332 GrPathTessellationShader::TestAndResetStencilSettings());
Chris Daltonebb37e72021-01-27 17:59:45 -0700333 }
334}
335
336void GrPathInnerTriangulateOp::onPrePrepare(GrRecordingContext* context,
337 const GrSurfaceProxyView& writeView,
338 GrAppliedClip* clip,
John Stiles52cb1d02021-06-02 11:58:05 -0400339 const GrDstProxyView& dstProxyView,
Chris Daltonebb37e72021-01-27 17:59:45 -0700340 GrXferBarrierFlags renderPassXferBarriers,
341 GrLoadOp colorLoadOp) {
342 this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, &dstProxyView,
343 renderPassXferBarriers, colorLoadOp, context->priv().caps()},
344 (clip) ? std::move(*clip) : GrAppliedClip::Disabled());
345 if (fStencilCurvesProgram) {
346 context->priv().recordProgramInfo(fStencilCurvesProgram);
347 }
348 for (const GrProgramInfo* fanProgram : fFanPrograms) {
349 context->priv().recordProgramInfo(fanProgram);
350 }
Chris Dalton031d76b2021-06-08 16:32:00 -0600351 if (fCoverHullsProgram) {
352 context->priv().recordProgramInfo(fCoverHullsProgram);
Chris Daltonebb37e72021-01-27 17:59:45 -0700353 }
354}
355
Chris Daltona05ccc32021-06-29 19:42:13 -0600356GR_DECLARE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);
357
Chris Daltonebb37e72021-01-27 17:59:45 -0700358void GrPathInnerTriangulateOp::onPrepare(GrOpFlushState* flushState) {
359 if (!fFanTriangulator) {
360 this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
361 &flushState->dstProxyView(), flushState->renderPassBarriers(),
362 flushState->colorLoadOp(), &flushState->caps()},
363 flushState->detachAppliedClip());
364 if (!fFanTriangulator) {
365 return;
366 }
367 }
368
369 if (fFanPolys) {
370 GrEagerDynamicVertexAllocator alloc(flushState, &fFanBuffer, &fBaseFanVertex);
371 fFanVertexCount = fFanTriangulator->polysToTriangles(fFanPolys, &alloc, &fFanBreadcrumbs);
372 }
373
374 if (fTessellator) {
375 // Must be called after polysToTriangles() in order for fFanBreadcrumbs to be complete.
Chris Dalton569c01b2021-05-25 10:11:46 -0600376 fTessellator->prepare(flushState, this->bounds(), fPath, &fFanBreadcrumbs);
Chris Daltonebb37e72021-01-27 17:59:45 -0700377 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600378
379 if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
380 constexpr static float kStripOrderIDs[4] = {0, 1, 3, 2};
381
382 GR_DEFINE_STATIC_UNIQUE_KEY(gHullVertexBufferKey);
383
384 fHullVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
385 GrGpuBufferType::kVertex, sizeof(kStripOrderIDs), kStripOrderIDs,
386 gHullVertexBufferKey);
387 }
Chris Daltonebb37e72021-01-27 17:59:45 -0700388}
389
390void GrPathInnerTriangulateOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
391 if (fStencilCurvesProgram) {
392 SkASSERT(fTessellator);
393 flushState->bindPipelineAndScissorClip(*fStencilCurvesProgram, this->bounds());
394 fTessellator->draw(flushState);
Chris Daltond9bdc322021-06-01 19:22:05 -0600395 if (flushState->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) {
396 flushState->gpu()->insertManualFramebufferBarrier(); // http://skbug.com/9739
397 }
Chris Daltonebb37e72021-01-27 17:59:45 -0700398 }
399
400 for (const GrProgramInfo* fanProgram : fFanPrograms) {
401 SkASSERT(fFanBuffer);
402 flushState->bindPipelineAndScissorClip(*fanProgram, this->bounds());
Robert Phillips787fd9d2021-03-22 14:48:09 -0400403 flushState->bindTextures(fanProgram->geomProc(), nullptr, fanProgram->pipeline());
Chris Daltonebb37e72021-01-27 17:59:45 -0700404 flushState->bindBuffers(nullptr, nullptr, fFanBuffer);
405 flushState->draw(fFanVertexCount, fBaseFanVertex);
406 }
407
Chris Dalton031d76b2021-06-08 16:32:00 -0600408 if (fCoverHullsProgram) {
Chris Daltonebb37e72021-01-27 17:59:45 -0700409 SkASSERT(fTessellator);
Chris Dalton031d76b2021-06-08 16:32:00 -0600410 flushState->bindPipelineAndScissorClip(*fCoverHullsProgram, this->bounds());
411 flushState->bindTextures(fCoverHullsProgram->geomProc(), nullptr, *fPipelineForFills);
Chris Daltona05ccc32021-06-29 19:42:13 -0600412 fTessellator->drawHullInstances(flushState, fHullVertexBufferIfNoIDSupport);
Chris Daltonebb37e72021-01-27 17:59:45 -0700413 }
414}