xref: /aosp_15_r20/external/skia/src/gpu/ganesh/ops/PathInnerTriangulateOp.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
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 #ifndef PathInnerTriangulateOp_DEFINED
9 #define PathInnerTriangulateOp_DEFINED
10 
11 #include "include/core/SkTypes.h"
12 
13 #if !defined(SK_ENABLE_OPTIMIZE_SIZE)
14 
15 #include "include/core/SkMatrix.h"
16 #include "include/core/SkPath.h"
17 #include "include/core/SkRefCnt.h"
18 #include "include/private/SkColorData.h"
19 #include "include/private/base/SkTArray.h"
20 #include "include/private/gpu/ganesh/GrTypesPriv.h"
21 #include "src/gpu/ganesh/GrBuffer.h"
22 #include "src/gpu/ganesh/GrCaps.h"
23 #include "src/gpu/ganesh/GrGpuBuffer.h"
24 #include "src/gpu/ganesh/GrPaint.h"
25 #include "src/gpu/ganesh/GrProcessorSet.h"
26 #include "src/gpu/ganesh/geometry/GrInnerFanTriangulator.h"
27 #include "src/gpu/ganesh/geometry/GrTriangulator.h"
28 #include "src/gpu/ganesh/ops/GrDrawOp.h"
29 #include "src/gpu/ganesh/ops/GrOp.h"
30 #include "src/gpu/ganesh/tessellate/GrTessellationShader.h"
31 
32 #include <utility>
33 
34 class GrAppliedClip;
35 class GrDstProxyView;
36 class GrOpFlushState;
37 class GrPipeline;
38 class GrProgramInfo;
39 class GrRecordingContext;
40 class GrSurfaceProxyView;
41 enum class GrXferBarrierFlags;
42 struct GrUserStencilSettings;
43 struct SkRect;
44 
45 namespace skgpu::ganesh {
46 
47 class PathCurveTessellator;
48 enum class FillPathFlags;
49 
50 // This op is a 3-pass twist on the standard Redbook "stencil then cover" algorithm:
51 //
52 // 1) Tessellate the path's outer curves into the stencil buffer.
53 // 2) Triangulate the path's inner fan and fill it with a stencil test against the curves.
54 // 3) Draw convex hulls around each curve that fill in remaining samples.
55 //
56 // In practice, a path's inner fan takes up a large majority of its pixels. So from a GPU load
57 // perspective, this op is effectively as fast as a single-pass algorithm.
58 class PathInnerTriangulateOp final : public GrDrawOp {
59 private:
60     DEFINE_OP_CLASS_ID
61 
PathInnerTriangulateOp(const SkMatrix & viewMatrix,const SkPath & path,GrPaint && paint,GrAAType aaType,FillPathFlags pathFlags,const SkRect & drawBounds)62     PathInnerTriangulateOp(const SkMatrix& viewMatrix,
63                            const SkPath& path,
64                            GrPaint&& paint,
65                            GrAAType aaType,
66                            FillPathFlags pathFlags,
67                            const SkRect& drawBounds)
68             : GrDrawOp(ClassID())
69             , fPathFlags(pathFlags)
70             , fViewMatrix(viewMatrix)
71             , fPath(path)
72             , fAAType(aaType)
73             , fColor(paint.getColor4f())
74             , fProcessors(std::move(paint)) {
75         SkASSERT(!fPath.isInverseFillType());
76         this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
77     }
78 
name()79     const char* name() const override { return "PathInnerTriangulateOp"; }
80     void visitProxies(const GrVisitProxyFunc&) const override;
81     FixedFunctionFlags fixedFunctionFlags() const override;
82     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
83 
84     // These calls set up the stencil & fill programs we will use prior to preparing and executing.
85     void pushFanStencilProgram(const GrTessellationShader::ProgramArgs&,
86                                const GrPipeline* pipelineForStencils, const GrUserStencilSettings*);
87     void pushFanFillProgram(const GrTessellationShader::ProgramArgs&, const GrUserStencilSettings*);
88     void prePreparePrograms(const GrTessellationShader::ProgramArgs&, GrAppliedClip&&);
89 
90     void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
91                       const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override;
92     void onPrepare(GrOpFlushState*) override;
93     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
94 
95     const FillPathFlags fPathFlags;
96     const SkMatrix fViewMatrix;
97     const SkPath fPath;
98     const GrAAType fAAType;
99     SkPMColor4f fColor;
100     GrProcessorSet fProcessors;
101 
102     // Triangulates the inner fan.
103     GrInnerFanTriangulator* fFanTriangulator = nullptr;
104     GrTriangulator::Poly* fFanPolys = nullptr;
105     GrInnerFanTriangulator::BreadcrumbTriangleList fFanBreadcrumbs;
106 
107     // This pipeline is shared by all programs that do filling.
108     const GrPipeline* fPipelineForFills = nullptr;
109 
110     // Tessellates the outer curves.
111     PathCurveTessellator* fTessellator = nullptr;
112 
113     // Pass 1: Tessellate the outer curves into the stencil buffer.
114     const GrProgramInfo* fStencilCurvesProgram = nullptr;
115 
116     // Pass 2: Fill the path's inner fan with a stencil test against the curves. (In extenuating
117     // circumstances this might require two separate draws.)
118     skia_private::STArray<2, const GrProgramInfo*> fFanPrograms;
119 
120     // Pass 3: Draw convex hulls around each curve.
121     const GrProgramInfo* fCoverHullsProgram = nullptr;
122 
123     // This buffer gets created by fFanTriangulator during onPrepare.
124     sk_sp<const GrBuffer> fFanBuffer;
125     int fBaseFanVertex = 0;
126     int fFanVertexCount = 0;
127 
128     // Only used if sk_VertexID is not supported.
129     sk_sp<const GrGpuBuffer> fHullVertexBufferIfNoIDSupport;
130 
131     friend class GrOp;  // For ctor.
132 };
133 
134 }  // namespace skgpu::ganesh
135 
136 #endif // SK_ENABLE_OPTIMIZE_SIZE
137 
138 #endif // PathInnerTriangulateOp_DEFINED
139