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