GrVSCoverageProcessor.cpp 23 KB

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