2 * Copyright 2019 Google LLC.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef PathInnerTriangulateOp_DEFINED
9 #define PathInnerTriangulateOp_DEFINED
11 #include "src/gpu/ganesh/geometry/GrInnerFanTriangulator.h"
12 #include "src/gpu/ganesh/ops/FillPathFlags.h"
13 #include "src/gpu/ganesh/ops/GrDrawOp.h"
14 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h"
18 class PathCurveTessellator;
20 // This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm:
22 // 1) Tessellate the path's outer curves into the stencil buffer.
23 // 2) Triangulate the path's inner fan and fill it with a stencil test against the curves.
24 // 3) Draw convex hulls around each curve that fill in remaining samples.
26 // In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load
27 // perspective, this op is effectively as fast as a single-pass algorithm.
28 class PathInnerTriangulateOp final : public GrDrawOp {
32 PathInnerTriangulateOp(const SkMatrix& viewMatrix,
36 FillPathFlags pathFlags,
37 const SkRect& drawBounds)
39 , fPathFlags(pathFlags)
40 , fViewMatrix(viewMatrix)
43 , fColor(paint.getColor4f())
44 , fProcessors(std::move(paint)) {
45 SkASSERT(!fPath.isInverseFillType());
46 this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
49 const char* name() const override { return "PathInnerTriangulateOp"; }
50 void visitProxies(const GrVisitProxyFunc&) const override;
51 FixedFunctionFlags fixedFunctionFlags() const override;
52 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
54 // These calls set up the stencil & fill programs we will use prior to preparing and executing.
55 void pushFanStencilProgram(const GrTessellationShader::ProgramArgs&,
56 const GrPipeline* pipelineForStencils, const GrUserStencilSettings*);
57 void pushFanFillProgram(const GrTessellationShader::ProgramArgs&, const GrUserStencilSettings*);
58 void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&&);
60 void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
61 const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
62 void onPrepare(GrOpFlushState*) override;
63 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
65 const FillPathFlags fPathFlags;
66 const SkMatrix fViewMatrix;
68 const GrAAType fAAType;
70 GrProcessorSet fProcessors;
72 // Triangulates the inner fan.
73 GrInnerFanTriangulator* fFanTriangulator = nullptr;
74 GrTriangulator::Poly* fFanPolys = nullptr;
75 GrInnerFanTriangulator::BreadcrumbTriangleList fFanBreadcrumbs;
77 // This pipeline is shared by all programs that do filling.
78 const GrPipeline* fPipelineForFills = nullptr;
80 // Tessellates the outer curves.
81 PathCurveTessellator* fTessellator = nullptr;
83 // Pass 1: Tessellate the outer curves into the stencil buffer.
84 const GrProgramInfo* fStencilCurvesProgram = nullptr;
86 // Pass 2: Fill the path's inner fan with a stencil test against the curves. (In extenuating
87 // circumstances this might require two separate draws.)
88 SkSTArray<2, const GrProgramInfo*> fFanPrograms;
90 // Pass 3: Draw convex hulls around each curve.
91 const GrProgramInfo* fCoverHullsProgram = nullptr;
93 // This buffer gets created by fFanTriangulator during onPrepare.
94 sk_sp<const GrBuffer> fFanBuffer;
95 int fBaseFanVertex = 0;
96 int fFanVertexCount = 0;
98 // Only used if sk_VertexID is not supported.
99 sk_sp<const GrGpuBuffer> fHullVertexBufferIfNoIDSupport;
101 friend class GrOp; // For ctor.
104 } // namespace skgpu::v1
106 #endif // PathInnerTriangulateOp_DEFINED