1 /*
2  * Copyright 2017 Google Inc.
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 "GrCCCoverageProcessor.h"
9 
10 #include "GrMesh.h"
11 #include "glsl/GrGLSLVertexGeoBuilder.h"
12 
13 // This class implements the coverage processor with vertex shaders.
14 class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor {
15 public:
VSImpl(std::unique_ptr<Shader> shader,int numSides)16     VSImpl(std::unique_ptr<Shader> shader, int numSides)
17             : fShader(std::move(shader)), fNumSides(numSides) {}
18 
19 private:
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor &,FPCoordTransformIter && transformIter)20     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
21                  FPCoordTransformIter&& transformIter) final {
22         this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
23     }
24 
25     void onEmitCode(EmitArgs&, GrGPArgs*) override;
26 
27     const std::unique_ptr<Shader> fShader;
28     const int fNumSides;
29 };
30 
31 static constexpr int kInstanceAttribIdx_X = 0;  // Transposed X values of all input points.
32 static constexpr int kInstanceAttribIdx_Y = 1;  // Transposed Y values of all input points.
33 
34 // Vertex data tells the shader how to offset vertices for conservative raster, as well as how to
35 // calculate coverage values for corners and edges.
36 static constexpr int kVertexData_LeftNeighborIdShift = 10;
37 static constexpr int kVertexData_RightNeighborIdShift = 8;
38 static constexpr int kVertexData_BloatIdxShift = 6;
39 static constexpr int kVertexData_InvertNegativeCoverageBit = 1 << 5;
40 static constexpr int kVertexData_IsCornerBit = 1 << 4;
41 static constexpr int kVertexData_IsEdgeBit = 1 << 3;
42 static constexpr int kVertexData_IsHullBit = 1 << 2;
43 
pack_vertex_data(int32_t leftNeighborID,int32_t rightNeighborID,int32_t bloatIdx,int32_t cornerID,int32_t extraData=0)44 static constexpr int32_t pack_vertex_data(int32_t leftNeighborID, int32_t rightNeighborID,
45                                           int32_t bloatIdx, int32_t cornerID,
46                                           int32_t extraData = 0) {
47     return (leftNeighborID << kVertexData_LeftNeighborIdShift) |
48            (rightNeighborID << kVertexData_RightNeighborIdShift) |
49            (bloatIdx << kVertexData_BloatIdxShift) |
50            cornerID | extraData;
51 }
52 
hull_vertex_data(int32_t cornerID,int32_t bloatIdx,int n)53 static constexpr int32_t hull_vertex_data(int32_t cornerID, int32_t bloatIdx, int n) {
54     return pack_vertex_data((cornerID + n - 1) % n, (cornerID + 1) % n, bloatIdx, cornerID,
55                             kVertexData_IsHullBit);
56 }
57 
edge_vertex_data(int32_t edgeID,int32_t endptIdx,int32_t bloatIdx,int n)58 static constexpr int32_t edge_vertex_data(int32_t edgeID, int32_t endptIdx, int32_t bloatIdx,
59                                           int n) {
60     return pack_vertex_data(0 == endptIdx ? (edgeID + 1) % n : edgeID,
61                             0 == endptIdx ? (edgeID + 1) % n : edgeID,
62                             bloatIdx, 0 == endptIdx ? edgeID : (edgeID + 1) % n,
63                             kVertexData_IsEdgeBit |
64                             (!endptIdx ? kVertexData_InvertNegativeCoverageBit : 0));
65 }
66 
corner_vertex_data(int32_t leftID,int32_t cornerID,int32_t rightID,int32_t bloatIdx)67 static constexpr int32_t corner_vertex_data(int32_t leftID, int32_t cornerID, int32_t rightID,
68                                             int32_t bloatIdx) {
69     return pack_vertex_data(leftID, rightID, bloatIdx, cornerID, kVertexData_IsCornerBit);
70 }
71 
72 static constexpr int32_t kTriangleVertices[] = {
73     hull_vertex_data(0, 0, 3),
74     hull_vertex_data(0, 1, 3),
75     hull_vertex_data(0, 2, 3),
76     hull_vertex_data(1, 0, 3),
77     hull_vertex_data(1, 1, 3),
78     hull_vertex_data(1, 2, 3),
79     hull_vertex_data(2, 0, 3),
80     hull_vertex_data(2, 1, 3),
81     hull_vertex_data(2, 2, 3),
82 
83     edge_vertex_data(0, 0, 0, 3),
84     edge_vertex_data(0, 0, 1, 3),
85     edge_vertex_data(0, 0, 2, 3),
86     edge_vertex_data(0, 1, 0, 3),
87     edge_vertex_data(0, 1, 1, 3),
88     edge_vertex_data(0, 1, 2, 3),
89 
90     edge_vertex_data(1, 0, 0, 3),
91     edge_vertex_data(1, 0, 1, 3),
92     edge_vertex_data(1, 0, 2, 3),
93     edge_vertex_data(1, 1, 0, 3),
94     edge_vertex_data(1, 1, 1, 3),
95     edge_vertex_data(1, 1, 2, 3),
96 
97     edge_vertex_data(2, 0, 0, 3),
98     edge_vertex_data(2, 0, 1, 3),
99     edge_vertex_data(2, 0, 2, 3),
100     edge_vertex_data(2, 1, 0, 3),
101     edge_vertex_data(2, 1, 1, 3),
102     edge_vertex_data(2, 1, 2, 3),
103 
104     corner_vertex_data(2, 0, 1, 0),
105     corner_vertex_data(2, 0, 1, 1),
106     corner_vertex_data(2, 0, 1, 2),
107     corner_vertex_data(2, 0, 1, 3),
108 
109     corner_vertex_data(0, 1, 2, 0),
110     corner_vertex_data(0, 1, 2, 1),
111     corner_vertex_data(0, 1, 2, 2),
112     corner_vertex_data(0, 1, 2, 3),
113 
114     corner_vertex_data(1, 2, 0, 0),
115     corner_vertex_data(1, 2, 0, 1),
116     corner_vertex_data(1, 2, 0, 2),
117     corner_vertex_data(1, 2, 0, 3),
118 };
119 
120 GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
121 
122 static constexpr uint16_t kRestartStrip = 0xffff;
123 
124 static constexpr uint16_t kTriangleIndicesAsStrips[] =  {
125     1, 2, 0, 3, 8, kRestartStrip, // First corner and main body of the hull.
126     4, 5, 3, 6, 8, 7, kRestartStrip, // Opposite side and corners of the hull.
127     10, 9, 11, 14, 12, 13, kRestartStrip, // First edge.
128     16, 15, 17, 20, 18, 19, kRestartStrip, // Second edge.
129     22, 21, 23, 26, 24, 25, kRestartStrip, // Third edge.
130     28, 27, 29, 30, kRestartStrip, // First corner.
131     32, 31, 33, 34, kRestartStrip, // Second corner.
132     36, 35, 37, 38 // Third corner.
133 };
134 
135 static constexpr uint16_t kTriangleIndicesAsTris[] =  {
136     // First corner and main body of the hull.
137     1, 2, 0,
138     2, 3, 0,
139     0, 3, 8, // Main body.
140 
141     // Opposite side and corners of the hull.
142     4, 5, 3,
143     5, 6, 3,
144     3, 6, 8,
145     6, 7, 8,
146 
147     // First edge.
148     10,  9, 11,
149      9, 14, 11,
150     11, 14, 12,
151     14, 13, 12,
152 
153     // Second edge.
154     16, 15, 17,
155     15, 20, 17,
156     17, 20, 18,
157     20, 19, 18,
158 
159     // Third edge.
160     22, 21, 23,
161     21, 26, 23,
162     23, 26, 24,
163     26, 25, 24,
164 
165     // First corner.
166     28, 27, 29,
167     27, 30, 29,
168 
169     // Second corner.
170     32, 31, 33,
171     31, 34, 33,
172 
173     // Third corner.
174     36, 35, 37,
175     35, 38, 37,
176 };
177 
178 GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
179 
180 // Curves, including quadratics, are drawn with a four-sided hull.
181 static constexpr int32_t kCurveVertices[] = {
182     hull_vertex_data(0, 0, 4),
183     hull_vertex_data(0, 1, 4),
184     hull_vertex_data(0, 2, 4),
185     hull_vertex_data(1, 0, 4),
186     hull_vertex_data(1, 1, 4),
187     hull_vertex_data(1, 2, 4),
188     hull_vertex_data(2, 0, 4),
189     hull_vertex_data(2, 1, 4),
190     hull_vertex_data(2, 2, 4),
191     hull_vertex_data(3, 0, 4),
192     hull_vertex_data(3, 1, 4),
193     hull_vertex_data(3, 2, 4),
194 
195     corner_vertex_data(3, 0, 1, 0),
196     corner_vertex_data(3, 0, 1, 1),
197     corner_vertex_data(3, 0, 1, 2),
198     corner_vertex_data(3, 0, 1, 3),
199 
200     corner_vertex_data(2, 3, 0, 0),
201     corner_vertex_data(2, 3, 0, 1),
202     corner_vertex_data(2, 3, 0, 2),
203     corner_vertex_data(2, 3, 0, 3),
204 };
205 
206 GR_DECLARE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
207 
208 static constexpr uint16_t kCurveIndicesAsStrips[] =  {
209     1, 0, 2, 11, 3, 5, 4, kRestartStrip, // First half of the hull (split diagonally).
210     7, 6, 8, 5, 9, 11, 10, kRestartStrip, // Second half of the hull.
211     13, 12, 14, 15, kRestartStrip, // First corner.
212     17, 16, 18, 19 // Final corner.
213 };
214 
215 static constexpr uint16_t kCurveIndicesAsTris[] =  {
216     // First half of the hull (split diagonally).
217      1,  0,  2,
218      0, 11,  2,
219      2, 11,  3,
220     11,  5,  3,
221      3,  5,  4,
222 
223     // Second half of the hull.
224     7,  6,  8,
225     6,  5,  8,
226     8,  5,  9,
227     5, 11,  9,
228     9, 11, 10,
229 
230     // First corner.
231     13, 12, 14,
232     12, 15, 14,
233 
234     // Final corner.
235     17, 16, 18,
236     16, 19, 18,
237 };
238 
239 GR_DECLARE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
240 
241 // Generates a conservative raster hull around a triangle or curve. For triangles we generate
242 // additional conservative rasters with coverage ramps around the edges and corners.
243 //
244 // Triangles are drawn in three steps: (1) Draw a conservative raster of the entire triangle, with a
245 // coverage of +1. (2) Draw conservative rasters around each edge, with a coverage ramp from -1 to
246 // 0. These edge coverage values convert jagged conservative raster edges into smooth, antialiased
247 // ones. (3) Draw conservative rasters (aka pixel-size boxes) around each corner, replacing the
248 // previous coverage values with ones that ramp to zero in the bloat vertices that fall outside the
249 // triangle.
250 //
251 // Curves are drawn in two separate passes. Here we just draw a conservative raster around the input
252 // points. The Shader takes care of everything else for now. The final curve corners get touched up
253 // in a later step by VSCornerImpl.
onEmitCode(EmitArgs & args,GrGPArgs * gpArgs)254 void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
255     const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>();
256     GrGLSLVertexBuilder* v = args.fVertBuilder;
257     int numInputPoints = proc.numInputPoints();
258 
259     int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
260     const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz";
261     v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth,
262                    proc.fInstanceAttributes[kInstanceAttribIdx_X].name(), swizzle,
263                    proc.fInstanceAttributes[kInstanceAttribIdx_Y].name(), swizzle);
264 
265     v->codeAppend ("half wind;");
266     Shader::CalcWind(proc, v, "pts", "wind");
267     if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) {
268         SkASSERT(3 == numInputPoints);
269         SkASSERT(kFloat4_GrVertexAttribType ==
270                  proc.fInstanceAttributes[kInstanceAttribIdx_X].cpuType());
271         v->codeAppendf("wind *= %s.w;", proc.fInstanceAttributes[kInstanceAttribIdx_X].name());
272     }
273 
274     float bloat = kAABloatRadius;
275 #ifdef SK_DEBUG
276     if (proc.debugBloatEnabled()) {
277         bloat *= proc.debugBloat();
278     }
279 #endif
280     v->defineConstant("bloat", bloat);
281 
282     const char* hullPts = "pts";
283     fShader->emitSetupCode(v, "pts", "wind", (4 == fNumSides) ? &hullPts : nullptr);
284 
285     // Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0].
286     v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;",
287                    proc.fVertexAttribute.name(),
288                    ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
289                    ((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
290                    (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
291                    (fNumSides - 1),
292                    proc.fVertexAttribute.name());
293 
294     // Here we generate conservative raster geometry for the input polygon. It is the convex
295     // hull of N pixel-size boxes, one centered on each the input points. Each corner has three
296     // vertices, where one or two may cause degenerate triangles. The vertex data tells us how
297     // to offset each vertex. Triangle edges and corners are also handled here using the same
298     // concept. For more details on conservative raster, see:
299     // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html
300     v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts);
301     v->codeAppendf("float2 left = %s[clockwise_indices >> %i];",
302                    hullPts, kVertexData_LeftNeighborIdShift);
303     v->codeAppendf("float2 right = %s[(clockwise_indices >> %i) & 3];",
304                    hullPts, kVertexData_RightNeighborIdShift);
305 
306     v->codeAppend ("float2 leftbloat = sign(corner - left);");
307     v->codeAppend ("leftbloat = float2(0 != leftbloat.y ? leftbloat.y : leftbloat.x, "
308                                       "0 != leftbloat.x ? -leftbloat.x : -leftbloat.y);");
309 
310     v->codeAppend ("float2 rightbloat = sign(right - corner);");
311     v->codeAppend ("rightbloat = float2(0 != rightbloat.y ? rightbloat.y : rightbloat.x, "
312                                        "0 != rightbloat.x ? -rightbloat.x : -rightbloat.y);");
313 
314     v->codeAppend ("bool2 left_right_notequal = notEqual(leftbloat, rightbloat);");
315 
316     v->codeAppend ("float2 bloatdir = leftbloat;");
317 
318     v->codeAppend ("float2 leftdir = corner - left;");
319     v->codeAppend ("leftdir = (float2(0) != leftdir) ? normalize(leftdir) : float2(1, 0);");
320 
321     v->codeAppend ("float2 rightdir = right - corner;");
322     v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);");
323 
324     v->codeAppendf("if (0 != (%s & %i)) {",  // Are we a corner?
325                    proc.fVertexAttribute.name(), kVertexData_IsCornerBit);
326 
327                        // In corner boxes, all 4 coverage values will not map linearly.
328                        // Therefore it is important to align the box so its diagonal shared
329                        // edge points out of the triangle, in the direction that ramps to 0.
330     v->codeAppend (    "bloatdir = float2(leftdir.x > rightdir.x ? +1 : -1, "
331                                          "leftdir.y > rightdir.y ? +1 : -1);");
332 
333                        // For corner boxes, we hack left_right_notequal to always true. This
334                        // in turn causes the upcoming code to always rotate, generating all
335                        // 4 vertices of the corner box.
336     v->codeAppendf(    "left_right_notequal = bool2(true);");
337     v->codeAppend ("}");
338 
339     // At each corner of the polygon, our hull will have either 1, 2, or 3 vertices (or 4 if
340     // it's a corner box). We begin with this corner's first raster vertex (leftbloat), then
341     // continue rotating 90 degrees clockwise until we reach the desired raster vertex for this
342     // invocation. Corners with less than 3 corresponding raster vertices will result in
343     // redundant vertices and degenerate triangles.
344     v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fVertexAttribute.name(),
345                    kVertexData_BloatIdxShift);
346     v->codeAppend ("switch (bloatidx) {");
347     v->codeAppend (    "case 3:");
348                             // Only corners will have bloatidx=3, and corners always rotate.
349     v->codeAppend (        "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
350                            // fallthru.
351     v->codeAppend (    "case 2:");
352     v->codeAppendf(        "if (all(left_right_notequal)) {");
353     v->codeAppend (            "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
354     v->codeAppend (        "}");
355                            // fallthru.
356     v->codeAppend (    "case 1:");
357     v->codeAppendf(        "if (any(left_right_notequal)) {");
358     v->codeAppend (            "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW.
359     v->codeAppend (        "}");
360                            // fallthru.
361     v->codeAppend ("}");
362 
363     v->codeAppend ("float2 vertex = fma(bloatdir, float2(bloat), corner);");
364     gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
365 
366     // Hulls have a coverage of +1 all around.
367     v->codeAppend ("half coverage = +1;");
368 
369     if (3 == fNumSides) {
370         v->codeAppend ("half left_coverage; {");
371         Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage");
372         v->codeAppend ("}");
373 
374         v->codeAppend ("half right_coverage; {");
375         Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage");
376         v->codeAppend ("}");
377 
378         v->codeAppendf("if (0 != (%s & %i)) {",  // Are we an edge?
379                        proc.fVertexAttribute.name(), kVertexData_IsEdgeBit);
380         v->codeAppend (    "coverage = left_coverage;");
381         v->codeAppend ("}");
382 
383         v->codeAppendf("if (0 != (%s & %i)) {",  // Invert coverage?
384                        proc.fVertexAttribute.name(),
385                        kVertexData_InvertNegativeCoverageBit);
386         v->codeAppend (    "coverage = -1 - coverage;");
387         v->codeAppend ("}");
388     }
389 
390     // Non-corner geometry should have zero effect from corner coverage.
391     v->codeAppend ("half2 corner_coverage = half2(0);");
392 
393     v->codeAppendf("if (0 != (%s & %i)) {",  // Are we a corner?
394                    proc.fVertexAttribute.name(), kVertexData_IsCornerBit);
395                        // We use coverage=-1 to erase what the hull geometry wrote.
396                        //
397                        // In the context of curves, this effectively means "wind = -wind" and
398                        // causes the Shader to erase what it had written previously for the hull.
399                        //
400                        // For triangles it just erases the "+1" value written by the hull geometry.
401     v->codeAppend (    "coverage = -1;");
402     if (3 == fNumSides) {
403                        // Triangle corners also have to erase what the edge geometry wrote.
404         v->codeAppend ("coverage -= left_coverage + right_coverage;");
405     }
406 
407                        // Corner boxes require attenuated coverage.
408     v->codeAppend (    "half attenuation; {");
409     Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation");
410     v->codeAppend (    "}");
411 
412                        // Attenuate corner coverage towards the outermost vertex (where bloatidx=0).
413                        // This is all that curves need: At each vertex of the corner box, the curve
414                        // Shader will calculate the curve's local coverage value, interpolate it
415                        // alongside our attenuation parameter, and multiply the two together for a
416                        // final coverage value.
417     v->codeAppend (    "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(1);");
418 
419     if (3 == fNumSides) {
420                        // For triangles we also provide the actual coverage values at each vertex of
421                        // the corner box.
422         v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {");
423         v->codeAppend (    "corner_coverage.x += right_coverage;");
424         v->codeAppend ("}");
425         v->codeAppend ("if (bloatidx >= 2) {");
426         v->codeAppend (    "corner_coverage.x += left_coverage;");
427         v->codeAppend ("}");
428     }
429     v->codeAppend ("}");
430 
431     GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
432     v->codeAppend ("coverage *= wind;");
433     v->codeAppend ("corner_coverage.x *= wind;");
434     fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &v->code(),
435                           gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage");
436 
437     varyingHandler->emitAttributes(proc);
438     SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
439 
440     // Fragment shader.
441     fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
442 }
443 
initVS(GrResourceProvider * rp)444 void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) {
445     SkASSERT(Impl::kVertexShader == fImpl);
446     const GrCaps& caps = *rp->caps();
447 
448     switch (fPrimitiveType) {
449         case PrimitiveType::kTriangles:
450         case PrimitiveType::kWeightedTriangles: {
451             GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
452             fVSVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
453                                                          sizeof(kTriangleVertices),
454                                                          kTriangleVertices,
455                                                          gTriangleVertexBufferKey);
456             GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
457             if (caps.usePrimitiveRestart()) {
458                 fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
459                                                             sizeof(kTriangleIndicesAsStrips),
460                                                             kTriangleIndicesAsStrips,
461                                                             gTriangleIndexBufferKey);
462                 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
463             } else {
464                 fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
465                                                             sizeof(kTriangleIndicesAsTris),
466                                                             kTriangleIndicesAsTris,
467                                                             gTriangleIndexBufferKey);
468                 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
469             }
470             break;
471         }
472 
473         case PrimitiveType::kQuadratics:
474         case PrimitiveType::kCubics:
475         case PrimitiveType::kConics: {
476             GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
477             fVSVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType,
478                                                          sizeof(kCurveVertices), kCurveVertices,
479                                                          gCurveVertexBufferKey);
480             GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
481             if (caps.usePrimitiveRestart()) {
482                 fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
483                                                             sizeof(kCurveIndicesAsStrips),
484                                                             kCurveIndicesAsStrips,
485                                                             gCurveIndexBufferKey);
486                 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
487             } else {
488                 fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType,
489                                                             sizeof(kCurveIndicesAsTris),
490                                                             kCurveIndicesAsTris,
491                                                             gCurveIndexBufferKey);
492                 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
493             }
494             break;
495         }
496     }
497 
498     GrVertexAttribType xyAttribType;
499     GrSLType xySLType;
500     if (4 == this->numInputPoints() || this->hasInputWeight()) {
501         GR_STATIC_ASSERT(offsetof(QuadPointInstance, fX) == 0);
502         GR_STATIC_ASSERT(sizeof(QuadPointInstance::fX) ==
503                          GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
504         GR_STATIC_ASSERT(sizeof(QuadPointInstance::fY) ==
505                          GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
506         xyAttribType = kFloat4_GrVertexAttribType;
507         xySLType = kFloat4_GrSLType;
508     } else {
509         GR_STATIC_ASSERT(offsetof(TriPointInstance, fX) == 0);
510         GR_STATIC_ASSERT(sizeof(TriPointInstance::fX) ==
511                          GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
512         GR_STATIC_ASSERT(sizeof(TriPointInstance::fY) ==
513                          GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
514         xyAttribType = kFloat3_GrVertexAttribType;
515         xySLType = kFloat3_GrSLType;
516     }
517     fInstanceAttributes[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
518     fInstanceAttributes[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
519     this->setInstanceAttributes(fInstanceAttributes, 2);
520     fVertexAttribute = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
521     this->setVertexAttributes(&fVertexAttribute, 1);
522 
523     if (caps.usePrimitiveRestart()) {
524         fVSTriangleType = GrPrimitiveType::kTriangleStrip;
525     } else {
526         fVSTriangleType = GrPrimitiveType::kTriangles;
527     }
528 }
529 
appendVSMesh(sk_sp<const GrBuffer> instanceBuffer,int instanceCount,int baseInstance,SkTArray<GrMesh> * out) const530 void GrCCCoverageProcessor::appendVSMesh(sk_sp<const GrBuffer> instanceBuffer, int instanceCount,
531                                          int baseInstance, SkTArray<GrMesh>* out) const {
532     SkASSERT(Impl::kVertexShader == fImpl);
533     GrMesh& mesh = out->emplace_back(fVSTriangleType);
534     auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fVSTriangleType);
535     mesh.setIndexedInstanced(fVSIndexBuffer, fVSNumIndicesPerInstance, std::move(instanceBuffer),
536                              instanceCount, baseInstance, primitiveRestart);
537     mesh.setVertexData(fVSVertexBuffer, 0);
538 }
539 
createVSImpl(std::unique_ptr<Shader> shadr) const540 GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
541     switch (fPrimitiveType) {
542         case PrimitiveType::kTriangles:
543         case PrimitiveType::kWeightedTriangles:
544             return new VSImpl(std::move(shadr), 3);
545         case PrimitiveType::kQuadratics:
546         case PrimitiveType::kCubics:
547         case PrimitiveType::kConics:
548             return new VSImpl(std::move(shadr), 4);
549     }
550     SK_ABORT("Invalid RenderPass");
551     return nullptr;
552 }
553