• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 PathTessellator_DEFINED
9 #define PathTessellator_DEFINED
10 
11 #include "src/base/SkArenaAlloc.h"
12 #include "src/gpu/ganesh/GrGpuBuffer.h"
13 #include "src/gpu/ganesh/GrVertexChunkArray.h"
14 #include "src/gpu/ganesh/geometry/GrInnerFanTriangulator.h"
15 #include "src/gpu/tessellate/FixedCountBufferUtils.h"
16 #include "src/gpu/tessellate/Tessellation.h"
17 
18 class GrMeshDrawTarget;
19 class GrOpFlushState;
20 class SkPath;
21 
22 namespace skgpu::v1 {
23 
24 // Prepares GPU data for, and then draws a path's tessellated geometry. Depending on the subclass,
25 // the caller may or may not be required to draw the path's inner fan separately.
26 class PathTessellator {
27 public:
28     using PatchAttribs = tess::PatchAttribs;
29 
30     struct PathDrawList {
31         PathDrawList(const SkMatrix& pathMatrix,
32                      const SkPath& path,
33                      const SkPMColor4f& color,
34                      PathDrawList* next = nullptr)
fPathMatrixPathDrawList35                 : fPathMatrix(pathMatrix), fPath(path), fColor(color), fNext(next) {}
36 
37         SkMatrix fPathMatrix;
38         SkPath fPath;
39         SkPMColor4f fColor;
40         PathDrawList* fNext;
41 
42         struct Iter {
43             void operator++() { fHead = fHead->fNext; }
44             bool operator!=(const Iter& b) const { return fHead != b.fHead; }
45             std::tuple<const SkMatrix&, const SkPath&, const SkPMColor4f&> operator*() const {
46                 return {fHead->fPathMatrix, fHead->fPath, fHead->fColor};
47             }
48             const PathDrawList* fHead;
49         };
beginPathDrawList50         Iter begin() const { return {this}; }
endPathDrawList51         Iter end() const { return {nullptr}; }
52     };
53 
~PathTessellator()54     virtual ~PathTessellator() {}
55 
patchAttribs()56     PatchAttribs patchAttribs() const { return fAttribs; }
57 
58     // Called before draw(). Prepares GPU buffers containing the geometry to tessellate.
59     virtual void prepare(GrMeshDrawTarget* target,
60                          const SkMatrix& shaderMatrix,
61                          const PathDrawList& pathDrawList,
62                          int totalCombinedPathVerbCnt) = 0;
63 
64     // Issues fixed-count instanced draw calls over the patches. The caller is responsible for
65     // binding its desired pipeline ahead of time.
66     virtual void draw(GrOpFlushState* flushState) const = 0;
67 
68 protected:
PathTessellator(bool infinitySupport,PatchAttribs attribs)69     PathTessellator(bool infinitySupport, PatchAttribs attribs) : fAttribs(attribs) {
70         if (!infinitySupport) {
71             fAttribs |= PatchAttribs::kExplicitCurveType;
72         }
73     }
74 
75     PatchAttribs fAttribs;
76 
77     GrVertexChunkArray fVertexChunkArray;
78     // The max number of vertices that must be drawn to account for the accumulated tessellation
79     // levels of the written patches.
80     int fMaxVertexCount = 0;
81 
82     sk_sp<const GrGpuBuffer> fFixedVertexBuffer;
83     sk_sp<const GrGpuBuffer> fFixedIndexBuffer;
84 };
85 
86 // Draws an array of "outer curve" patches. Each patch is an independent 4-point curve, representing
87 // either a cubic or a conic. Quadratics are converted to cubics and triangles are converted to
88 // conics with w=Inf.
89 class PathCurveTessellator final : public PathTessellator {
90 public:
91     static PathCurveTessellator* Make(SkArenaAlloc* arena,
92                                       bool infinitySupport,
93                                       PatchAttribs attribs = PatchAttribs::kNone) {
94         return arena->make<PathCurveTessellator>(infinitySupport, attribs);
95     }
96 
97     PathCurveTessellator(bool infinitySupport,
98                          PatchAttribs attribs = PatchAttribs::kNone)
PathTessellator(infinitySupport,attribs)99             : PathTessellator(infinitySupport, attribs) {}
100 
101     void prepareWithTriangles(GrMeshDrawTarget* target,
102                               const SkMatrix& shaderMatrix,
103                               GrInnerFanTriangulator::BreadcrumbTriangleList* extraTriangles,
104                               const PathDrawList& pathDrawList,
105                               int totalCombinedPathVerbCnt);
106 
prepare(GrMeshDrawTarget * target,const SkMatrix & shaderMatrix,const PathDrawList & pathDrawList,int totalCombinedPathVerbCnt)107     void prepare(GrMeshDrawTarget* target,
108                  const SkMatrix& shaderMatrix,
109                  const PathDrawList& pathDrawList,
110                  int totalCombinedPathVerbCnt) final {
111         this->prepareWithTriangles(target,
112                                    shaderMatrix,
113                                    nullptr, // no extra triangles by default
114                                    pathDrawList,
115                                    totalCombinedPathVerbCnt);
116     }
117 
118     void draw(GrOpFlushState*) const final;
119 
120     // Draws a 4-point instance for each patch. This method is used for drawing convex hulls over
121     // each cubic with GrFillCubicHullShader. The caller is responsible for binding its desired
122     // pipeline ahead of time.
123     void drawHullInstances(GrOpFlushState*, sk_sp<const GrGpuBuffer> vertexBufferIfNeeded) const;
124 };
125 
126 // Prepares an array of "wedge" patches. A wedge is an independent, 5-point closed contour
127 // consisting of 4 control points plus an anchor point fanning from the center of the curve's
128 // resident contour. A wedge can be either a cubic or a conic. Quadratics and lines are converted to
129 // cubics. Once stencilled, these wedges alone define the complete path.
130 class PathWedgeTessellator final : public PathTessellator {
131 public:
132     static PathWedgeTessellator* Make(SkArenaAlloc* arena,
133                                       bool infinitySupport,
134                                       PatchAttribs attribs = PatchAttribs::kNone) {
135         return arena->make<PathWedgeTessellator>(infinitySupport, attribs);
136     }
137 
138     PathWedgeTessellator(bool infinitySupport, PatchAttribs attribs = PatchAttribs::kNone)
PathTessellator(infinitySupport,attribs)139             : PathTessellator(infinitySupport, attribs) {
140         fAttribs |= PatchAttribs::kFanPoint;
141     }
142 
143     void prepare(GrMeshDrawTarget* target,
144                  const SkMatrix& shaderMatrix,
145                  const PathDrawList& pathDrawList,
146                  int totalCombinedPathVerbCnt) final;
147 
148     void draw(GrOpFlushState*) const final;
149 };
150 
151 }  // namespace skgpu::v1
152 
153 #endif  // PathTessellator_DEFINED
154