blob: 0f40a12487738606a41e6aa92315093ee31eb003 [file] [log] [blame]
Chris Dalton90e8fb12017-12-22 02:24:53 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/ccpr/GrVSCoverageProcessor.h"
Chris Dalton90e8fb12017-12-22 02:24:53 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrMesh.h"
Robert Phillips03e4c952019-11-26 16:20:22 -050011#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
Chris Dalton90e8fb12017-12-22 02:24:53 -070013
Chris Dalton8dfc70f2018-03-26 19:15:22 -060014// This class implements the coverage processor with vertex shaders.
Chris Dalton2c5e0112019-03-29 13:14:18 -050015class GrVSCoverageProcessor::Impl : public GrGLSLGeometryProcessor {
Chris Dalton8dfc70f2018-03-26 19:15:22 -060016public:
Chris Dalton2c5e0112019-03-29 13:14:18 -050017 Impl(std::unique_ptr<Shader> shader, int numSides)
Chris Dalton8dfc70f2018-03-26 19:15:22 -060018 : fShader(std::move(shader)), fNumSides(numSides) {}
Chris Daltonfe462ef2018-03-08 15:54:01 +000019
Chris Dalton8dfc70f2018-03-26 19:15:22 -060020private:
Chris Daltonfe462ef2018-03-08 15:54:01 +000021 void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
Brian Salomonc241b582019-11-27 08:57:17 -050022 const CoordTransformRange& transformRange) final {
23 this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
Chris Daltonfe462ef2018-03-08 15:54:01 +000024 }
25
Chris Dalton8dfc70f2018-03-26 19:15:22 -060026 void onEmitCode(EmitArgs&, GrGPArgs*) override;
Chris Daltonfe462ef2018-03-08 15:54:01 +000027
28 const std::unique_ptr<Shader> fShader;
Chris Dalton8dfc70f2018-03-26 19:15:22 -060029 const int fNumSides;
Chris Daltonfe462ef2018-03-08 15:54:01 +000030};
31
Brian Salomon92be2f72018-06-19 14:33:47 -040032static constexpr int kInstanceAttribIdx_X = 0; // Transposed X values of all input points.
33static constexpr int kInstanceAttribIdx_Y = 1; // Transposed Y values of all input points.
Chris Dalton8dfc70f2018-03-26 19:15:22 -060034
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.
Chris Dalton8738cf42018-03-09 11:57:40 -070037static constexpr int kVertexData_LeftNeighborIdShift = 10;
38static constexpr int kVertexData_RightNeighborIdShift = 8;
39static constexpr int kVertexData_BloatIdxShift = 6;
40static constexpr int kVertexData_InvertNegativeCoverageBit = 1 << 5;
41static constexpr int kVertexData_IsCornerBit = 1 << 4;
Chris Dalton0a793812018-03-07 11:18:30 -070042static constexpr int kVertexData_IsEdgeBit = 1 << 3;
43static constexpr int kVertexData_IsHullBit = 1 << 2;
44
Chris Dalton0a793812018-03-07 11:18:30 -070045static 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;
Chris Dalton90e8fb12017-12-22 02:24:53 -070052}
53
Chris Dalton0a793812018-03-07 11:18:30 -070054static 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);
Chris Dalton90e8fb12017-12-22 02:24:53 -070057}
58
Chris Daltonbaf3e782018-03-08 15:55:58 +000059static 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 |
Chris Dalton8738cf42018-03-09 11:57:40 -070065 (!endptIdx ? kVertexData_InvertNegativeCoverageBit : 0));
Chris Dalton90e8fb12017-12-22 02:24:53 -070066}
67
Chris Dalton21ba5512018-03-21 17:20:21 -060068static 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);
Chris Dalton8738cf42018-03-09 11:57:40 -070071}
72
73static constexpr int32_t kTriangleVertices[] = {
Chris Dalton90e8fb12017-12-22 02:24:53 -070074 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
Chris Daltonbaf3e782018-03-08 15:55:58 +000084 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),
Chris Dalton90e8fb12017-12-22 02:24:53 -070090
Chris Daltonbaf3e782018-03-08 15:55:58 +000091 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),
Chris Dalton90e8fb12017-12-22 02:24:53 -070097
Chris Daltonbaf3e782018-03-08 15:55:58 +000098 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),
Chris Dalton8738cf42018-03-09 11:57:40 -0700104
Chris Dalton21ba5512018-03-21 17:20:21 -0600105 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),
Chris Dalton8738cf42018-03-09 11:57:40 -0700109
Chris Dalton21ba5512018-03-21 17:20:21 -0600110 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),
Chris Dalton8738cf42018-03-09 11:57:40 -0700114
Chris Dalton21ba5512018-03-21 17:20:21 -0600115 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),
Chris Dalton90e8fb12017-12-22 02:24:53 -0700119};
120
Chris Dalton8738cf42018-03-09 11:57:40 -0700121GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700122
Chris Dalton27059d32018-01-23 14:06:50 -0700123static constexpr uint16_t kRestartStrip = 0xffff;
124
Chris Dalton8738cf42018-03-09 11:57:40 -0700125static constexpr uint16_t kTriangleIndicesAsStrips[] = {
Chris Dalton27059d32018-01-23 14:06:50 -0700126 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.
Chris Dalton8738cf42018-03-09 11:57:40 -0700130 22, 21, 23, 26, 24, 25, kRestartStrip, // Third edge.
Chris Dalton04a1de52018-03-14 02:04:09 -0600131 28, 27, 29, 30, kRestartStrip, // First corner.
132 32, 31, 33, 34, kRestartStrip, // Second corner.
133 36, 35, 37, 38 // Third corner.
Chris Dalton27059d32018-01-23 14:06:50 -0700134};
135
Chris Dalton8738cf42018-03-09 11:57:40 -0700136static constexpr uint16_t kTriangleIndicesAsTris[] = {
Chris Dalton90e8fb12017-12-22 02:24:53 -0700137 // 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,
Chris Dalton8738cf42018-03-09 11:57:40 -0700165
166 // First corner.
Chris Dalton04a1de52018-03-14 02:04:09 -0600167 28, 27, 29,
168 27, 30, 29,
Chris Dalton8738cf42018-03-09 11:57:40 -0700169
170 // Second corner.
Chris Dalton04a1de52018-03-14 02:04:09 -0600171 32, 31, 33,
172 31, 34, 33,
Chris Dalton8738cf42018-03-09 11:57:40 -0700173
174 // Third corner.
Chris Dalton04a1de52018-03-14 02:04:09 -0600175 36, 35, 37,
176 35, 38, 37,
Chris Dalton90e8fb12017-12-22 02:24:53 -0700177};
178
Chris Dalton8738cf42018-03-09 11:57:40 -0700179GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700180
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600181// Curves, including quadratics, are drawn with a four-sided hull.
182static constexpr int32_t kCurveVertices[] = {
Chris Dalton90e8fb12017-12-22 02:24:53 -0700183 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
Chris Dalton21ba5512018-03-21 17:20:21 -0600196 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),
Chris Dalton90e8fb12017-12-22 02:24:53 -0700205};
206
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600207GR_DECLARE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700208
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600209static constexpr uint16_t kCurveIndicesAsStrips[] = {
Chris Dalton27059d32018-01-23 14:06:50 -0700210 1, 0, 2, 11, 3, 5, 4, kRestartStrip, // First half of the hull (split diagonally).
Chris Dalton21ba5512018-03-21 17:20:21 -0600211 7, 6, 8, 5, 9, 11, 10, kRestartStrip, // Second half of the hull.
212 13, 12, 14, 15, kRestartStrip, // First corner.
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600213 17, 16, 18, 19 // Final corner.
Chris Dalton27059d32018-01-23 14:06:50 -0700214};
215
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600216static constexpr uint16_t kCurveIndicesAsTris[] = {
Chris Dalton90e8fb12017-12-22 02:24:53 -0700217 // 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,
Chris Dalton21ba5512018-03-21 17:20:21 -0600230
231 // First corner.
232 13, 12, 14,
233 12, 15, 14,
234
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600235 // Final corner.
Chris Dalton21ba5512018-03-21 17:20:21 -0600236 17, 16, 18,
237 16, 19, 18,
Chris Dalton90e8fb12017-12-22 02:24:53 -0700238};
239
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600240GR_DECLARE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700241
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600242// 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//
Chris Dalton2c5e0112019-03-29 13:14:18 -0500252// 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.
254void GrVSCoverageProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
255 const GrVSCoverageProcessor& proc = args.fGP.cast<GrVSCoverageProcessor>();
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600256 GrGLSLVertexBuilder* v = args.fVertBuilder;
257 int numInputPoints = proc.numInputPoints();
Chris Dalton8738cf42018-03-09 11:57:40 -0700258
Chris Dalton9f2dab02018-04-18 14:07:03 -0600259 int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3;
260 const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz";
Brian Salomon70132d02018-05-29 15:33:06 -0400261 v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth,
Chris Dalton2c5e0112019-03-29 13:14:18 -0500262 proc.fInputXAndYValues[kInstanceAttribIdx_X].name(), swizzle,
263 proc.fInputXAndYValues[kInstanceAttribIdx_Y].name(), swizzle);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700264
Chris Dalton6f5e77a2018-04-23 21:14:42 -0600265 v->codeAppend ("half wind;");
266 Shader::CalcWind(proc, v, "pts", "wind");
267 if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) {
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600268 SkASSERT(3 == numInputPoints);
Brian Salomon92be2f72018-06-19 14:33:47 -0400269 SkASSERT(kFloat4_GrVertexAttribType ==
Chris Dalton2c5e0112019-03-29 13:14:18 -0500270 proc.fInputXAndYValues[kInstanceAttribIdx_X].cpuType());
Ethan Nicholase1f55022019-02-05 17:17:40 -0500271 v->codeAppendf("wind *= half(%s.w);",
Chris Dalton2c5e0112019-03-29 13:14:18 -0500272 proc.fInputXAndYValues[kInstanceAttribIdx_X].name());
Chris Dalton622650a2018-03-07 17:30:10 -0700273 }
274
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600275 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";
Chris Dalton84d36cd2019-04-17 14:47:17 -0600284 fShader->emitSetupCode(v, "pts", (4 == fNumSides) ? &hullPts : nullptr);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600285
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;",
Chris Dalton2c5e0112019-03-29 13:14:18 -0500288 proc.fPerVertexData.name(),
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600289 ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) |
290 ((fNumSides - 1) << kVertexData_RightNeighborIdShift) |
291 (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) |
292 (fNumSides - 1),
Chris Dalton2c5e0112019-03-29 13:14:18 -0500293 proc.fPerVertexData.name());
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600294
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
Brian Salomon70132d02018-05-29 15:33:06 -0400325 v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
Chris Dalton2c5e0112019-03-29 13:14:18 -0500326 proc.fPerVertexData.name(), kVertexData_IsCornerBit);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600327
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.
Chris Dalton2c5e0112019-03-29 13:14:18 -0500345 v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fPerVertexData.name(),
Brian Salomon70132d02018-05-29 15:33:06 -0400346 kVertexData_BloatIdxShift);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600347 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
Chris Dalton84d36cd2019-04-17 14:47:17 -0600364 v->codeAppend ("float2 vertexpos = fma(bloatdir, float2(bloat), corner);");
365 gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600366
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600367 // Hulls have a coverage of +1 all around.
368 v->codeAppend ("half coverage = +1;");
369
370 if (3 == fNumSides) {
Chris Dalton4c239342018-04-05 18:43:40 -0600371 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
Brian Salomon70132d02018-05-29 15:33:06 -0400379 v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge?
Chris Dalton2c5e0112019-03-29 13:14:18 -0500380 proc.fPerVertexData.name(), kVertexData_IsEdgeBit);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600381 v->codeAppend ( "coverage = left_coverage;");
382 v->codeAppend ("}");
383
Brian Salomon70132d02018-05-29 15:33:06 -0400384 v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage?
Chris Dalton2c5e0112019-03-29 13:14:18 -0500385 proc.fPerVertexData.name(),
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600386 kVertexData_InvertNegativeCoverageBit);
387 v->codeAppend ( "coverage = -1 - coverage;");
388 v->codeAppend ("}");
Chris Dalton84d36cd2019-04-17 14:47:17 -0600389 } 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);");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600399 }
400
Chris Dalton4c239342018-04-05 18:43:40 -0600401 // Non-corner geometry should have zero effect from corner coverage.
402 v->codeAppend ("half2 corner_coverage = half2(0);");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600403
Brian Salomon70132d02018-05-29 15:33:06 -0400404 v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner?
Chris Dalton2c5e0112019-03-29 13:14:18 -0500405 proc.fPerVertexData.name(), kVertexData_IsCornerBit);
Chris Dalton84d36cd2019-04-17 14:47:17 -0600406 // Erase what the previous geometry wrote.
407 v->codeAppend ( "wind = -wind;");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600408 if (3 == fNumSides) {
Chris Dalton84d36cd2019-04-17 14:47:17 -0600409 v->codeAppend ("coverage = 1 + left_coverage + right_coverage;");
410 } else if (!fShader->calculatesOwnEdgeCoverage()) {
411 v->codeAppend ("coverage = -coverage;");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600412 }
Chris Dalton4c239342018-04-05 18:43:40 -0600413
414 // Corner boxes require attenuated coverage.
415 v->codeAppend ( "half attenuation; {");
416 Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600417 v->codeAppend ( "}");
Chris Dalton4c239342018-04-05 18:43:40 -0600418
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.
Chris Dalton84d36cd2019-04-17 14:47:17 -0600424 v->codeAppend ( "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(-1,+1);");
Chris Dalton4c239342018-04-05 18:43:40 -0600425
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) {");
Chris Dalton84d36cd2019-04-17 14:47:17 -0600430 v->codeAppend ( "corner_coverage.x -= right_coverage;");
Chris Dalton4c239342018-04-05 18:43:40 -0600431 v->codeAppend ("}");
432 v->codeAppend ("if (bloatidx >= 2) {");
Chris Dalton84d36cd2019-04-17 14:47:17 -0600433 v->codeAppend ( "corner_coverage.x -= left_coverage;");
Chris Dalton4c239342018-04-05 18:43:40 -0600434 v->codeAppend ("}");
435 }
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600436 v->codeAppend ("}");
437
438 GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600439 v->codeAppend ("coverage *= wind;");
Chris Dalton4c239342018-04-05 18:43:40 -0600440 v->codeAppend ("corner_coverage.x *= wind;");
Chris Dalton2c5e0112019-03-29 13:14:18 -0500441 fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &AccessCodeString(v),
Chris Dalton84d36cd2019-04-17 14:47:17 -0600442 "vertexpos", "coverage", "corner_coverage", "wind");
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600443
444 varyingHandler->emitAttributes(proc);
Brian Salomon7d8b3972019-11-26 22:34:44 -0500445 SkASSERT(!*args.fFPCoordTransformHandler);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600446
447 // Fragment shader.
Chris Daltonc3318f02019-07-19 14:20:53 -0600448 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);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600453}
Chris Dalton622650a2018-03-07 17:30:10 -0700454
Chris Dalton2c5e0112019-03-29 13:14:18 -0500455void GrVSCoverageProcessor::reset(PrimitiveType primitiveType, GrResourceProvider* rp) {
Chris Dalton84403d72018-02-13 21:46:17 -0500456 const GrCaps& caps = *rp->caps();
Chris Dalton90e8fb12017-12-22 02:24:53 -0700457
Chris Dalton2c5e0112019-03-29 13:14:18 -0500458 fPrimitiveType = primitiveType;
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600459 switch (fPrimitiveType) {
Chris Dalton703b4762018-04-06 16:11:48 -0600460 case PrimitiveType::kTriangles:
461 case PrimitiveType::kWeightedTriangles: {
Chris Dalton8738cf42018-03-09 11:57:40 -0700462 GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey);
Chris Dalton2c5e0112019-03-29 13:14:18 -0500463 fVertexBuffer = rp->findOrMakeStaticBuffer(
464 GrGpuBufferType::kVertex, sizeof(kTriangleVertices), kTriangleVertices,
465 gTriangleVertexBufferKey);
Chris Dalton8738cf42018-03-09 11:57:40 -0700466 GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey);
Chris Dalton27059d32018-01-23 14:06:50 -0700467 if (caps.usePrimitiveRestart()) {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500468 fIndexBuffer = rp->findOrMakeStaticBuffer(
469 GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsStrips),
470 kTriangleIndicesAsStrips, gTriangleIndexBufferKey);
471 fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips);
Chris Dalton27059d32018-01-23 14:06:50 -0700472 } else {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500473 fIndexBuffer = rp->findOrMakeStaticBuffer(
474 GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsTris),
475 kTriangleIndicesAsTris, gTriangleIndexBufferKey);
476 fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris);
Chris Daltonfe462ef2018-03-08 15:54:01 +0000477 }
478 break;
479 }
480
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600481 case PrimitiveType::kQuadratics:
Chris Dalton9f2dab02018-04-18 14:07:03 -0600482 case PrimitiveType::kCubics:
483 case PrimitiveType::kConics: {
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600484 GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey);
Chris Dalton2c5e0112019-03-29 13:14:18 -0500485 fVertexBuffer = rp->findOrMakeStaticBuffer(
486 GrGpuBufferType::kVertex, sizeof(kCurveVertices), kCurveVertices,
487 gCurveVertexBufferKey);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600488 GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey);
Chris Daltonbaf3e782018-03-08 15:55:58 +0000489 if (caps.usePrimitiveRestart()) {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500490 fIndexBuffer = rp->findOrMakeStaticBuffer(
491 GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsStrips),
492 kCurveIndicesAsStrips, gCurveIndexBufferKey);
493 fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips);
Chris Daltonbaf3e782018-03-08 15:55:58 +0000494 } else {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500495 fIndexBuffer = rp->findOrMakeStaticBuffer(
496 GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsTris), kCurveIndicesAsTris,
497 gCurveIndexBufferKey);
498 fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris);
Chris Daltonbaf3e782018-03-08 15:55:58 +0000499 }
500 break;
501 }
Chris Dalton90e8fb12017-12-22 02:24:53 -0700502 }
503
Brian Salomon92be2f72018-06-19 14:33:47 -0400504 GrVertexAttribType xyAttribType;
Brian Osmand4c29702018-09-14 16:16:55 -0400505 GrSLType xySLType;
Chris Dalton9f2dab02018-04-18 14:07:03 -0600506 if (4 == this->numInputPoints() || this->hasInputWeight()) {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500507 static_assert(offsetof(QuadPointInstance, fX) == 0);
508 static_assert(sizeof(QuadPointInstance::fX) ==
509 GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
510 static_assert(sizeof(QuadPointInstance::fY) ==
511 GrVertexAttribTypeSize(kFloat4_GrVertexAttribType));
Brian Salomon92be2f72018-06-19 14:33:47 -0400512 xyAttribType = kFloat4_GrVertexAttribType;
Brian Osmand4c29702018-09-14 16:16:55 -0400513 xySLType = kFloat4_GrSLType;
Chris Dalton90e8fb12017-12-22 02:24:53 -0700514 } else {
Brian Salomon4dea72a2019-12-18 10:43:10 -0500515 static_assert(sizeof(TriPointInstance) ==
516 2 * GrVertexAttribTypeSize(kFloat3_GrVertexAttribType));
Brian Salomon92be2f72018-06-19 14:33:47 -0400517 xyAttribType = kFloat3_GrVertexAttribType;
Brian Osmand4c29702018-09-14 16:16:55 -0400518 xySLType = kFloat3_GrSLType;
Chris Dalton90e8fb12017-12-22 02:24:53 -0700519 }
Chris Dalton2c5e0112019-03-29 13:14:18 -0500520 fInputXAndYValues[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType};
521 fInputXAndYValues[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType};
522 this->setInstanceAttributes(fInputXAndYValues, 2);
523 fPerVertexData = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType};
524 this->setVertexAttributes(&fPerVertexData, 1);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700525
Chris Dalton27059d32018-01-23 14:06:50 -0700526 if (caps.usePrimitiveRestart()) {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500527 fTriangleType = GrPrimitiveType::kTriangleStrip;
Chris Dalton27059d32018-01-23 14:06:50 -0700528 } else {
Chris Dalton2c5e0112019-03-29 13:14:18 -0500529 fTriangleType = GrPrimitiveType::kTriangles;
Chris Dalton90e8fb12017-12-22 02:24:53 -0700530 }
Chris Dalton90e8fb12017-12-22 02:24:53 -0700531}
532
Chris Dalton2c5e0112019-03-29 13:14:18 -0500533void GrVSCoverageProcessor::appendMesh(sk_sp<const GrGpuBuffer> instanceBuffer, int instanceCount,
534 int baseInstance, SkTArray<GrMesh>* out) const {
Robert Phillipscea290f2019-11-06 11:21:03 -0500535 SkASSERT(fTriangleType == GrPrimitiveType::kTriangles ||
536 fTriangleType == GrPrimitiveType::kTriangleStrip);
537
Chris Dalton79f336d2020-02-11 14:42:56 -0700538 GrMesh& mesh = out->push_back();
Chris Dalton2c5e0112019-03-29 13:14:18 -0500539 auto primitiveRestart = GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fTriangleType);
540 mesh.setIndexedInstanced(fIndexBuffer, fNumIndicesPerInstance, std::move(instanceBuffer),
Brian Salomon802cb312018-06-08 18:05:20 -0400541 instanceCount, baseInstance, primitiveRestart);
Chris Dalton2c5e0112019-03-29 13:14:18 -0500542 mesh.setVertexData(fVertexBuffer, 0);
Chris Dalton90e8fb12017-12-22 02:24:53 -0700543}
544
Chris Dalton2c5e0112019-03-29 13:14:18 -0500545GrGLSLPrimitiveProcessor* GrVSCoverageProcessor::onCreateGLSLInstance(
546 std::unique_ptr<Shader> shader) const {
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600547 switch (fPrimitiveType) {
548 case PrimitiveType::kTriangles:
Chris Dalton703b4762018-04-06 16:11:48 -0600549 case PrimitiveType::kWeightedTriangles:
Chris Dalton2c5e0112019-03-29 13:14:18 -0500550 return new Impl(std::move(shader), 3);
Chris Dalton8dfc70f2018-03-26 19:15:22 -0600551 case PrimitiveType::kQuadratics:
552 case PrimitiveType::kCubics:
Chris Dalton9f2dab02018-04-18 14:07:03 -0600553 case PrimitiveType::kConics:
Chris Dalton2c5e0112019-03-29 13:14:18 -0500554 return new Impl(std::move(shader), 4);
Chris Daltonfe462ef2018-03-08 15:54:01 +0000555 }
Chris Dalton2c5e0112019-03-29 13:14:18 -0500556 SK_ABORT("Invalid PrimitiveType");
Chris Dalton90e8fb12017-12-22 02:24:53 -0700557}