blob: 15cd7f8221c6da42d4916316cdcbd2461731d36e [file] [log] [blame]
Chris Dalton70a0d2c2021-01-26 12:01:21 -07001/*
2 * Copyright 2021 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
Robert Phillipse453fa02021-08-19 14:57:05 -04008#include "src/gpu/ops/PathStencilCoverOp.h"
Chris Dalton70a0d2c2021-01-26 12:01:21 -07009
10#include "src/gpu/GrEagerVertexAllocator.h"
Chris Daltond9bdc322021-06-01 19:22:05 -060011#include "src/gpu/GrGpu.h"
Chris Dalton70a0d2c2021-01-26 12:01:21 -070012#include "src/gpu/GrOpFlushState.h"
13#include "src/gpu/GrRecordingContextPriv.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040014#include "src/gpu/GrResourceProvider.h"
Chris Dalton8aec1242021-07-19 11:10:45 -060015#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
16#include "src/gpu/glsl/GrGLSLVarying.h"
Chris Dalton2f733ec2021-06-01 12:11:57 -060017#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
Robert Phillips06273bc2021-08-11 15:43:50 -040018#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Chris Dalton70a0d2c2021-01-26 12:01:21 -070019#include "src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h"
Chris Daltond9bdc322021-06-01 19:22:05 -060020#include "src/gpu/tessellate/GrPathCurveTessellator.h"
Chris Daltond9bdc322021-06-01 19:22:05 -060021#include "src/gpu/tessellate/GrPathWedgeTessellator.h"
Chris Dalton3b412782021-06-01 13:40:03 -060022#include "src/gpu/tessellate/shaders/GrPathTessellationShader.h"
Chris Dalton70a0d2c2021-01-26 12:01:21 -070023
Robert Phillips832f3fb2021-08-18 13:05:15 -040024using PathFlags = GrTessellationPathFlags;
Chris Dalton70a0d2c2021-01-26 12:01:21 -070025
Chris Dalton2f733ec2021-06-01 12:11:57 -060026namespace {
27
28// Fills a path's bounding box, with subpixel outset to avoid possible T-junctions with extreme
29// edges of the path.
30// NOTE: The emitted geometry may not be axis-aligned, depending on the view matrix.
Chris Dalton8aec1242021-07-19 11:10:45 -060031class BoundingBoxShader : public GrGeometryProcessor {
Chris Dalton2f733ec2021-06-01 12:11:57 -060032public:
Chris Daltone909e1e2021-07-27 13:23:18 -060033 BoundingBoxShader(SkPMColor4f color, const GrShaderCaps& shaderCaps)
Chris Dalton8aec1242021-07-19 11:10:45 -060034 : GrGeometryProcessor(kTessellate_BoundingBoxShader_ClassID)
Chris Dalton8aec1242021-07-19 11:10:45 -060035 , fColor(color) {
Chris Daltona05ccc32021-06-29 19:42:13 -060036 if (!shaderCaps.vertexIDSupport()) {
37 constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType,
38 kFloat2_GrSLType);
39 this->setVertexAttributes(&kUnitCoordAttrib, 1);
40 }
Chris Daltone909e1e2021-07-27 13:23:18 -060041 constexpr static Attribute kInstanceAttribs[] = {
42 {"matrix2d", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
43 {"translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
44 {"pathBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType}
45 };
46 this->setInstanceAttributes(kInstanceAttribs, SK_ARRAY_COUNT(kInstanceAttribs));
Chris Dalton2f733ec2021-06-01 12:11:57 -060047 }
48
49private:
Chris Daltonb63711a2021-06-01 14:52:02 -060050 const char* name() const final { return "tessellate_BoundingBoxShader"; }
Brian Salomon13b28732021-08-06 15:33:58 -040051 void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const final {}
Brian Salomonf95940b2021-08-09 15:56:24 -040052 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const final;
Chris Dalton8aec1242021-07-19 11:10:45 -060053
Chris Dalton8aec1242021-07-19 11:10:45 -060054 const SkPMColor4f fColor;
Chris Dalton2f733ec2021-06-01 12:11:57 -060055};
56
Brian Salomonf95940b2021-08-09 15:56:24 -040057std::unique_ptr<GrGeometryProcessor::ProgramImpl> BoundingBoxShader::makeProgramImpl(
58 const GrShaderCaps&) const {
59 class Impl : public ProgramImpl {
Brian Salomonbab2d112021-08-11 09:59:56 -040060 public:
61 void setData(const GrGLSLProgramDataManager& pdman,
62 const GrShaderCaps&,
63 const GrGeometryProcessor& gp) override {
64 const SkPMColor4f& color = gp.cast<BoundingBoxShader>().fColor;
65 pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA);
66 }
67
68 private:
Chris Dalton8aec1242021-07-19 11:10:45 -060069 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
70 args.fVaryingHandler->emitAttributes(args.fGeomProc);
71
72 // Vertex shader.
Chris Dalton8aec1242021-07-19 11:10:45 -060073 if (args.fShaderCaps->vertexIDSupport()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060074 // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex
75 // attrib.
Chris Daltone909e1e2021-07-27 13:23:18 -060076 args.fVertBuilder->codeAppend(R"(
Chris Daltona05ccc32021-06-29 19:42:13 -060077 float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
78 }
Chris Daltone909e1e2021-07-27 13:23:18 -060079 args.fVertBuilder->codeAppend(R"(
Chris Dalton8aec1242021-07-19 11:10:45 -060080 // Bloat the bounding box by 1/4px to be certain we will reset every stencil value.
Chris Daltone909e1e2021-07-27 13:23:18 -060081 float2x2 M_ = inverse(float2x2(matrix2d));
Chris Dalton2f733ec2021-06-01 12:11:57 -060082 float2 bloat = float2(abs(M_[0]) + abs(M_[1])) * .25;
83
84 // Find the vertex position.
Chris Daltona05ccc32021-06-29 19:42:13 -060085 float2 localcoord = mix(pathBounds.xy - bloat, pathBounds.zw + bloat, unitCoord);
Chris Daltone909e1e2021-07-27 13:23:18 -060086 float2 vertexpos = float2x2(matrix2d) * localcoord + translate;)");
Chris Dalton2f733ec2021-06-01 12:11:57 -060087 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord");
88 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
Chris Dalton8aec1242021-07-19 11:10:45 -060089
90 // Fragment shader.
91 const char* color;
92 fColorUniform = args.fUniformHandler->addUniform(nullptr, kFragment_GrShaderFlag,
93 kHalf4_GrSLType, "color", &color);
94 args.fFragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, color);
95 args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
Chris Dalton2f733ec2021-06-01 12:11:57 -060096 }
Chris Dalton8aec1242021-07-19 11:10:45 -060097
Chris Dalton8aec1242021-07-19 11:10:45 -060098 GrGLSLUniformHandler::UniformHandle fColorUniform;
Chris Dalton2f733ec2021-06-01 12:11:57 -060099 };
Chris Dalton8aec1242021-07-19 11:10:45 -0600100
Brian Salomonf95940b2021-08-09 15:56:24 -0400101 return std::make_unique<Impl>();
Chris Dalton2f733ec2021-06-01 12:11:57 -0600102}
103
Robert Phillips62bd6332021-08-26 09:56:55 -0400104} // anonymous namespace
Chris Dalton2f733ec2021-06-01 12:11:57 -0600105
Robert Phillips62bd6332021-08-26 09:56:55 -0400106namespace skgpu::v1 {
107
108void PathStencilCoverOp::visitProxies(const GrVisitProxyFunc& func) const {
Chris Dalton031d76b2021-06-08 16:32:00 -0600109 if (fCoverBBoxProgram) {
Robert Phillips294723d2021-06-17 09:23:58 -0400110 fCoverBBoxProgram->pipeline().visitProxies(func);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700111 } else {
Robert Phillips294723d2021-06-17 09:23:58 -0400112 fProcessors.visitProxies(func);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700113 }
114}
115
Robert Phillips62bd6332021-08-26 09:56:55 -0400116GrDrawOp::FixedFunctionFlags PathStencilCoverOp::fixedFunctionFlags() const {
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700117 auto flags = FixedFunctionFlags::kUsesStencil;
118 if (fAAType != GrAAType::kNone) {
119 flags |= FixedFunctionFlags::kUsesHWAA;
120 }
121 return flags;
122}
123
Robert Phillips62bd6332021-08-26 09:56:55 -0400124GrProcessorSet::Analysis PathStencilCoverOp::finalize(const GrCaps& caps,
125 const GrAppliedClip* clip,
126 GrClampType clampType) {
Chris Dalton57ab06c2021-04-22 12:57:28 -0600127 return fProcessors.finalize(fColor, GrProcessorAnalysisCoverage::kNone, clip, nullptr, caps,
128 clampType, &fColor);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700129}
130
Robert Phillips62bd6332021-08-26 09:56:55 -0400131void PathStencilCoverOp::prePreparePrograms(const GrTessellationShader::ProgramArgs& args,
132 GrAppliedClip&& appliedClip) {
Chris Dalton569c01b2021-05-25 10:11:46 -0600133 SkASSERT(!fTessellator);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700134 SkASSERT(!fStencilFanProgram);
135 SkASSERT(!fStencilPathProgram);
Chris Dalton031d76b2021-06-08 16:32:00 -0600136 SkASSERT(!fCoverBBoxProgram);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700137
Chris Dalton69669812021-07-27 10:00:12 -0600138 // We transform paths on the CPU. This allows for better batching.
139 const SkMatrix& shaderMatrix = SkMatrix::I();
Chris Dalton2f733ec2021-06-01 12:11:57 -0600140 const GrPipeline* stencilPipeline = GrPathTessellationShader::MakeStencilOnlyPipeline(
Chris Dalton917f9192021-06-08 14:32:37 -0600141 args, fAAType, fPathFlags, appliedClip.hardClip());
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600142 const GrUserStencilSettings* stencilSettings = GrPathTessellationShader::StencilPathSettings(
143 GrFillRuleForPathFillType(this->pathFillType()));
Chris Dalton569c01b2021-05-25 10:11:46 -0600144
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600145 if (fTotalCombinedPathVerbCnt > 50 &&
146 this->bounds().height() * this->bounds().width() > 256 * 256) {
Chris Daltond2b8ba32021-06-09 00:12:59 -0600147 // Large complex paths do better with a dedicated triangle shader for the inner fan.
148 // This takes less PCI bus bandwidth (6 floats per triangle instead of 8) and allows us
149 // to make sure it has an efficient middle-out topology.
Chris Dalton69669812021-07-27 10:00:12 -0600150 auto shader = GrPathTessellationShader::MakeSimpleTriangleShader(args.fArena,
151 shaderMatrix,
152 SK_PMColor4fTRANSPARENT);
153 fStencilFanProgram = GrTessellationShader::MakeProgram(args,
154 shader,
155 stencilPipeline,
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600156 stencilSettings);
Chris Dalton69669812021-07-27 10:00:12 -0600157 fTessellator = GrPathCurveTessellator::Make(args.fArena,
158 shaderMatrix,
Chris Daltond2b8ba32021-06-09 00:12:59 -0600159 SK_PMColor4fTRANSPARENT,
160 GrPathCurveTessellator::DrawInnerFan::kNo,
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600161 fTotalCombinedPathVerbCnt,
Chris Dalton69669812021-07-27 10:00:12 -0600162 *stencilPipeline,
Chris Dalton198ac152021-06-09 13:49:43 -0600163 *args.fCaps);
Chris Dalton917f9192021-06-08 14:32:37 -0600164 } else {
Chris Dalton69669812021-07-27 10:00:12 -0600165 fTessellator = GrPathWedgeTessellator::Make(args.fArena,
166 shaderMatrix,
167 SK_PMColor4fTRANSPARENT,
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600168 fTotalCombinedPathVerbCnt,
Chris Dalton69669812021-07-27 10:00:12 -0600169 *stencilPipeline,
170 *args.fCaps);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700171 }
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600172 fStencilPathProgram = GrTessellationShader::MakeProgram(args,
173 fTessellator->shader(),
174 stencilPipeline,
175 stencilSettings);
Chris Dalton569c01b2021-05-25 10:11:46 -0600176
Chris Dalton917f9192021-06-08 14:32:37 -0600177 if (!(fPathFlags & PathFlags::kStencilOnly)) {
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700178 // Create a program that draws a bounding box over the path and fills its stencil coverage
179 // into the color buffer.
Chris Daltone909e1e2021-07-27 13:23:18 -0600180 auto* bboxShader = args.fArena->make<BoundingBoxShader>(fColor, *args.fCaps->shaderCaps());
Chris Dalton2f733ec2021-06-01 12:11:57 -0600181 auto* bboxPipeline = GrTessellationShader::MakePipeline(args, fAAType,
182 std::move(appliedClip),
183 std::move(fProcessors));
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600184 auto* bboxStencil = GrPathTessellationShader::TestAndResetStencilSettings(
185 SkPathFillType_IsInverse(this->pathFillType()));
Chris Dalton8aec1242021-07-19 11:10:45 -0600186 fCoverBBoxProgram = GrSimpleMeshDrawOpHelper::CreateProgramInfo(
Chris Dalton2a26c502021-08-26 10:05:11 -0600187 args.fCaps,
Chris Dalton8aec1242021-07-19 11:10:45 -0600188 args.fArena,
189 bboxPipeline,
190 args.fWriteView,
Chris Dalton2a26c502021-08-26 10:05:11 -0600191 args.fUsesMSAASurface,
Chris Dalton8aec1242021-07-19 11:10:45 -0600192 bboxShader,
193 GrPrimitiveType::kTriangleStrip,
194 args.fXferBarrierFlags,
195 args.fColorLoadOp,
196 bboxStencil);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700197 }
198}
199
Robert Phillips62bd6332021-08-26 09:56:55 -0400200void PathStencilCoverOp::onPrePrepare(GrRecordingContext* context,
201 const GrSurfaceProxyView& writeView, GrAppliedClip* clip,
202 const GrDstProxyView& dstProxyView,
203 GrXferBarrierFlags renderPassXferBarriers,
204 GrLoadOp colorLoadOp) {
Chris Dalton2a26c502021-08-26 10:05:11 -0600205 // DMSAA is not supported on DDL.
206 bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
207 this->prePreparePrograms({context->priv().recordTimeAllocator(), writeView, usesMSAASurface,
208 &dstProxyView, renderPassXferBarriers, colorLoadOp,
209 context->priv().caps()},
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700210 (clip) ? std::move(*clip) : GrAppliedClip::Disabled());
211 if (fStencilFanProgram) {
212 context->priv().recordProgramInfo(fStencilFanProgram);
213 }
214 if (fStencilPathProgram) {
215 context->priv().recordProgramInfo(fStencilPathProgram);
216 }
Chris Dalton031d76b2021-06-08 16:32:00 -0600217 if (fCoverBBoxProgram) {
218 context->priv().recordProgramInfo(fCoverBBoxProgram);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700219 }
220}
221
Chris Daltona05ccc32021-06-29 19:42:13 -0600222GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
223
Robert Phillips62bd6332021-08-26 09:56:55 -0400224void PathStencilCoverOp::onPrepare(GrOpFlushState* flushState) {
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700225 if (!fTessellator) {
226 this->prePreparePrograms({flushState->allocator(), flushState->writeView(),
Chris Dalton2a26c502021-08-26 10:05:11 -0600227 flushState->usesMSAASurface(), &flushState->dstProxyView(),
228 flushState->renderPassBarriers(), flushState->colorLoadOp(),
229 &flushState->caps()}, flushState->detachAppliedClip());
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700230 if (!fTessellator) {
231 return;
232 }
233 }
234
235 if (fStencilFanProgram) {
236 // The inner fan isn't built into the tessellator. Generate a standard Redbook fan with a
237 // middle-out topology.
238 GrEagerDynamicVertexAllocator vertexAlloc(flushState, &fFanBuffer, &fFanBaseVertex);
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600239 int maxCombinedFanEdges =
240 GrPathTessellator::MaxCombinedFanEdgesInPathDrawList(fTotalCombinedPathVerbCnt);
241 // A single n-sided polygon is fanned by n-2 triangles. Multiple polygons with a combined
242 // edge count of n are fanned by strictly fewer triangles.
243 int maxTrianglesInFans = std::max(maxCombinedFanEdges - 2, 0);
244 GrVertexWriter triangleVertexWriter = vertexAlloc.lock<SkPoint>(maxTrianglesInFans * 3);
245 int fanTriangleCount = 0;
246 for (auto [pathMatrix, path] : *fPathDrawList) {
247 int numTrianglesWritten;
248 triangleVertexWriter = GrMiddleOutPolygonTriangulator::WritePathInnerFan(
249 std::move(triangleVertexWriter),
250 0,
251 0,
252 pathMatrix,
253 path,
254 &numTrianglesWritten);
255 fanTriangleCount += numTrianglesWritten;
256 }
257 SkASSERT(fanTriangleCount <= maxTrianglesInFans);
258 fFanVertexCount = fanTriangleCount * 3;
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700259 vertexAlloc.unlock(fFanVertexCount);
260 }
261
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600262 fTessellator->prepare(flushState, this->bounds(), *fPathDrawList, fTotalCombinedPathVerbCnt);
Chris Daltonc91dd692021-05-24 15:04:47 -0600263
Chris Dalton031d76b2021-06-08 16:32:00 -0600264 if (fCoverBBoxProgram) {
Chris Daltone909e1e2021-07-27 13:23:18 -0600265 size_t instanceStride = fCoverBBoxProgram->geomProc().instanceStride();
266 GrVertexWriter vertexWriter = flushState->makeVertexSpace(
267 instanceStride,
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600268 fPathCount,
Chris Daltone909e1e2021-07-27 13:23:18 -0600269 &fBBoxBuffer,
270 &fBBoxBaseInstance);
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600271 SkDEBUGCODE(int pathCount = 0;)
272 for (auto [pathMatrix, path] : *fPathDrawList) {
273 SkDEBUGCODE(auto end = vertexWriter.makeOffset(instanceStride));
274 vertexWriter.write(pathMatrix.getScaleX(),
275 pathMatrix.getSkewY(),
276 pathMatrix.getSkewX(),
277 pathMatrix.getScaleY(),
278 pathMatrix.getTranslateX(),
279 pathMatrix.getTranslateY());
280 if (path.isInverseFillType()) {
281 // Fill the entire backing store to make sure we clear every stencil value back to
282 // 0. If there is a scissor it will have already clipped the stencil draw.
283 auto rtBounds =
284 flushState->writeView().asRenderTargetProxy()->backingStoreBoundsRect();
285 SkASSERT(rtBounds == fOriginalDrawBounds);
286 SkRect pathSpaceRTBounds;
287 if (SkMatrixPriv::InverseMapRect(pathMatrix, &pathSpaceRTBounds, rtBounds)) {
288 vertexWriter.write(pathSpaceRTBounds);
289 } else {
290 vertexWriter.write(path.getBounds());
291 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600292 } else {
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600293 vertexWriter.write(path.getBounds());
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600294 }
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600295 SkASSERT(vertexWriter == end);
296 SkDEBUGCODE(++pathCount;)
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600297 }
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600298 SkASSERT(pathCount == fPathCount);
Chris Daltonc91dd692021-05-24 15:04:47 -0600299 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600300
301 if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
302 constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};
303
304 GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
305
306 fBBoxVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
307 GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
308 }
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700309}
310
Robert Phillips62bd6332021-08-26 09:56:55 -0400311void PathStencilCoverOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700312 if (!fTessellator) {
313 return;
314 }
315
316 // Stencil the inner fan, if any.
317 if (fFanVertexCount > 0) {
318 SkASSERT(fStencilFanProgram);
319 SkASSERT(fFanBuffer);
320 flushState->bindPipelineAndScissorClip(*fStencilFanProgram, this->bounds());
321 flushState->bindBuffers(nullptr, nullptr, fFanBuffer);
322 flushState->draw(fFanVertexCount, fFanBaseVertex);
323 }
324
325 // Stencil the rest of the path.
326 SkASSERT(fStencilPathProgram);
327 flushState->bindPipelineAndScissorClip(*fStencilPathProgram, this->bounds());
328 fTessellator->draw(flushState);
Chris Daltond9bdc322021-06-01 19:22:05 -0600329 if (flushState->caps().requiresManualFBBarrierAfterTessellatedStencilDraw()) {
330 flushState->gpu()->insertManualFramebufferBarrier(); // http://skbug.com/9739
331 }
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700332
333 // Fill in the bounding box (if not in stencil-only mode).
Chris Dalton031d76b2021-06-08 16:32:00 -0600334 if (fCoverBBoxProgram) {
335 flushState->bindPipelineAndScissorClip(*fCoverBBoxProgram, this->bounds());
336 flushState->bindTextures(fCoverBBoxProgram->geomProc(), nullptr,
337 fCoverBBoxProgram->pipeline());
Chris Daltona05ccc32021-06-29 19:42:13 -0600338 flushState->bindBuffers(nullptr, fBBoxBuffer, fBBoxVertexBufferIfNoIDSupport);
Chris Dalton8a1bbaa2021-07-28 14:43:07 -0600339 flushState->drawInstanced(fPathCount, fBBoxBaseInstance, 4, 0);
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700340 }
Chris Dalton70a0d2c2021-01-26 12:01:21 -0700341}
Robert Phillips62bd6332021-08-26 09:56:55 -0400342
343} // namespace skgpu::v1