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 *= half(%s.w);",
272 proc.fInstanceAttributes[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", "wind", (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.fVertexAttribute.name(),
289 ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
290 ((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
291 (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
292 (fNumSides - 1),
293 proc.fVertexAttribute.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.fVertexAttribute.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.fVertexAttribute.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 vertex = fma(bloatdir, float2(bloat), corner);");
365 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex");
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.fVertexAttribute.name(), kVertexData_IsEdgeBit);
381 v->codeAppend ( "coverage = left_coverage;");
382 v->codeAppend ("}");
383
384 v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage?
385 proc.fVertexAttribute.name(),
386 kVertexData_InvertNegativeCoverageBit);
387 v->codeAppend ( "coverage = -1 - coverage;");
388 v->codeAppend ("}");
389 }
390
391 // Non-corner geometry should have zero effect from corner coverage.
392 v->codeAppend ("half2 corner_coverage = half2(0);");
393
394 v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
395 proc.fVertexAttribute.name(), kVertexData_IsCornerBit);
396 // We use coverage=-1 to erase what the hull geometry wrote.
397 //
398 // In the context of curves, this effectively means "wind = -wind" and
399 // causes the Shader to erase what it had written previously for the hull.
400 //
401 // For triangles it just erases the "+1" value written by the hull geometry.
402 v->codeAppend ( "coverage = -1;");
403 if (3 == fNumSides) {
404 // Triangle corners also have to erase what the edge geometry wrote.
405 v->codeAppend ("coverage -= left_coverage + right_coverage;");
406 }
407
408 // Corner boxes require attenuated coverage.
409 v->codeAppend ( "half attenuation; {");
410 Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation");
411 v->codeAppend ( "}");
412
413 // Attenuate corner coverage towards the outermost vertex (where bloatidx=0).
414 // This is all that curves need: At each vertex of the corner box, the curve
415 // Shader will calculate the curve's local coverage value, interpolate it
416 // alongside our attenuation parameter, and multiply the two together for a
417 // final coverage value.
418 v->codeAppend ( "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(1);");
419
420 if (3 == fNumSides) {
421 // For triangles we also provide the actual coverage values at each vertex of
422 // the corner box.
423 v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {");
424 v->codeAppend ( "corner_coverage.x += right_coverage;");
425 v->codeAppend ("}");
426 v->codeAppend ("if (bloatidx >= 2) {");
427 v->codeAppend ( "corner_coverage.x += left_coverage;");
428 v->codeAppend ("}");
429 }
430 v->codeAppend ("}");
431
432 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
433 v->codeAppend ("coverage *= wind;");
434 v->codeAppend ("corner_coverage.x *= wind;");
435 fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &v->code(),
436 gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage");
437
438 varyingHandler->emitAttributes(proc);
439 SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform());
440
441 // Fragment shader.
442 fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage);
443 }
444
initVS(GrResourceProvider * rp)445 void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) {
446 SkASSERT(Impl::kVertexShader == fImpl);
447 const GrCaps& caps = *rp->caps();
448
449 switch (fPrimitiveType) {
450 case PrimitiveType::kTriangles:
451 case PrimitiveType::kWeightedTriangles: {
452 GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
453 fVSVertexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kVertex,
454 sizeof(kTriangleVertices),
455 kTriangleVertices,
456 gTriangleVertexBufferKey);
457 GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
458 if (caps.usePrimitiveRestart()) {
459 fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
460 sizeof(kTriangleIndicesAsStrips),
461 kTriangleIndicesAsStrips,
462 gTriangleIndexBufferKey);
463 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
464 } else {
465 fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
466 sizeof(kTriangleIndicesAsTris),
467 kTriangleIndicesAsTris,
468 gTriangleIndexBufferKey);
469 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
470 }
471 break;
472 }
473
474 case PrimitiveType::kQuadratics:
475 case PrimitiveType::kCubics:
476 case PrimitiveType::kConics: {
477 GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
478 fVSVertexBuffer =
479 rp->findOrMakeStaticBuffer(GrGpuBufferType::kVertex, sizeof(kCurveVertices),
480 kCurveVertices, gCurveVertexBufferKey);
481 GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
482 if (caps.usePrimitiveRestart()) {
483 fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
484 sizeof(kCurveIndicesAsStrips),
485 kCurveIndicesAsStrips,
486 gCurveIndexBufferKey);
487 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
488 } else {
489 fVSIndexBuffer = rp->findOrMakeStaticBuffer(GrGpuBufferType::kIndex,
490 sizeof(kCurveIndicesAsTris),
491 kCurveIndicesAsTris,
492 gCurveIndexBufferKey);
493 fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
494 }
495 break;
496 }
497 }
498
499 GrVertexAttribType xyAttribType;
500 GrSLType xySLType;
501 if (4 == this->numInputPoints() || this->hasInputWeight()) {
502 GR_STATIC_ASSERT(offsetof(QuadPointInstance, fX) == 0);
503 GR_STATIC_ASSERT(sizeof(QuadPointInstance::fX) ==
504 GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
505 GR_STATIC_ASSERT(sizeof(QuadPointInstance::fY) ==
506 GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
507 xyAttribType = kFloat4_GrVertexAttribType;
508 xySLType = kFloat4_GrSLType;
509 } else {
510 GR_STATIC_ASSERT(offsetof(TriPointInstance, fX) == 0);
511 GR_STATIC_ASSERT(sizeof(TriPointInstance::fX) ==
512 GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
513 GR_STATIC_ASSERT(sizeof(TriPointInstance::fY) ==
514 GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
515 xyAttribType = kFloat3_GrVertexAttribType;
516 xySLType = kFloat3_GrSLType;
517 }
518 fInstanceAttributes[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
519 fInstanceAttributes[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
520 this->setInstanceAttributes(fInstanceAttributes, 2);
521 fVertexAttribute = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
522 this->setVertexAttributes(&fVertexAttribute, 1);
523
524 if (caps.usePrimitiveRestart()) {
525 fVSTriangleType = GrPrimitiveType::kTriangleStrip;
526 } else {
527 fVSTriangleType = GrPrimitiveType::kTriangles;
528 }
529 }
530
appendVSMesh(sk_sp<const GrGpuBuffer> instanceBuffer,int instanceCount,int baseInstance,SkTArray<GrMesh> * out) const531 void GrCCCoverageProcessor::appendVSMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
532 int baseInstance, SkTArray<GrMesh>* out) const {
533 SkASSERT(Impl::kVertexShader == fImpl);
534 GrMesh& mesh = out->emplace_back(fVSTriangleType);
535 auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fVSTriangleType);
536 mesh.setIndexedInstanced(fVSIndexBuffer, fVSNumIndicesPerInstance, std::move(instanceBuffer),
537 instanceCount, baseInstance, primitiveRestart);
538 mesh.setVertexData(fVSVertexBuffer, 0);
539 }
540
createVSImpl(std::unique_ptr<Shader> shadr) const541 GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const {
542 switch (fPrimitiveType) {
543 case PrimitiveType::kTriangles:
544 case PrimitiveType::kWeightedTriangles:
545 return new VSImpl(std::move(shadr), 3);
546 case PrimitiveType::kQuadratics:
547 case PrimitiveType::kCubics:
548 case PrimitiveType::kConics:
549 return new VSImpl(std::move(shadr), 4);
550 }
551 SK_ABORT("Invalid RenderPass");
552 return nullptr;
553 }
554