Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 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 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 8 | #include "GrCCCoverageProcessor.h" |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 9 | |
| 10 | #include "GrMesh.h" |
| 11 | #include "glsl/GrGLSLVertexGeoBuilder.h" |
| 12 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 13 | // This class implements the coverage processor with vertex shaders. |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 14 | class GrCCCoverageProcessor::VSImpl : public GrGLSLGeometryProcessor { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 15 | public: |
| 16 | VSImpl(std::unique_ptr<Shader> shader, int numSides) |
| 17 | : fShader(std::move(shader)), fNumSides(numSides) {} |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 18 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 19 | private: |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 20 | void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, |
| 21 | FPCoordTransformIter&& transformIter) final { |
| 22 | this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); |
| 23 | } |
| 24 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 25 | void onEmitCode(EmitArgs&, GrGPArgs*) override; |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 26 | |
| 27 | const std::unique_ptr<Shader> fShader; |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 28 | const int fNumSides; |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 29 | }; |
| 30 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 31 | static constexpr int kAttribIdx_X = 0; // Transposed X values of all input points. |
| 32 | static constexpr int kAttribIdx_Y = 1; // Transposed Y values of all input points. |
| 33 | static constexpr int kAttribIdx_VertexData = 2; |
| 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. |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 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; |
Chris Dalton | 0a79381 | 2018-03-07 11:18:30 -0700 | [diff] [blame] | 42 | static constexpr int kVertexData_IsEdgeBit = 1 << 3; |
| 43 | static constexpr int kVertexData_IsHullBit = 1 << 2; |
| 44 | |
Chris Dalton | 0a79381 | 2018-03-07 11:18:30 -0700 | [diff] [blame] | 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; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 52 | } |
| 53 | |
Chris Dalton | 0a79381 | 2018-03-07 11:18:30 -0700 | [diff] [blame] | 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); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 57 | } |
| 58 | |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 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 | |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 65 | (!endptIdx ? kVertexData_InvertNegativeCoverageBit : 0)); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 66 | } |
| 67 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 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); |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 71 | } |
| 72 | |
| 73 | static constexpr int32_t kTriangleVertices[] = { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 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 | |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 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), |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 90 | |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 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), |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 97 | |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 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), |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 104 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 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), |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 109 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 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), |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 114 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 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), |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 119 | }; |
| 120 | |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 121 | GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 122 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 123 | static constexpr uint16_t kRestartStrip = 0xffff; |
| 124 | |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 125 | static constexpr uint16_t kTriangleIndicesAsStrips[] = { |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 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. |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 130 | 22, 21, 23, 26, 24, 25, kRestartStrip, // Third edge. |
Chris Dalton | 04a1de5 | 2018-03-14 02:04:09 -0600 | [diff] [blame] | 131 | 28, 27, 29, 30, kRestartStrip, // First corner. |
| 132 | 32, 31, 33, 34, kRestartStrip, // Second corner. |
| 133 | 36, 35, 37, 38 // Third corner. |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 134 | }; |
| 135 | |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 136 | static constexpr uint16_t kTriangleIndicesAsTris[] = { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 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, |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 165 | |
| 166 | // First corner. |
Chris Dalton | 04a1de5 | 2018-03-14 02:04:09 -0600 | [diff] [blame] | 167 | 28, 27, 29, |
| 168 | 27, 30, 29, |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 169 | |
| 170 | // Second corner. |
Chris Dalton | 04a1de5 | 2018-03-14 02:04:09 -0600 | [diff] [blame] | 171 | 32, 31, 33, |
| 172 | 31, 34, 33, |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 173 | |
| 174 | // Third corner. |
Chris Dalton | 04a1de5 | 2018-03-14 02:04:09 -0600 | [diff] [blame] | 175 | 36, 35, 37, |
| 176 | 35, 38, 37, |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 177 | }; |
| 178 | |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 179 | GR_DECLARE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 180 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 181 | // Curves, including quadratics, are drawn with a four-sided hull. |
| 182 | static constexpr int32_t kCurveVertices[] = { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 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 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 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), |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 205 | }; |
| 206 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 207 | GR_DECLARE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 208 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 209 | static constexpr uint16_t kCurveIndicesAsStrips[] = { |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 210 | 1, 0, 2, 11, 3, 5, 4, kRestartStrip, // First half of the hull (split diagonally). |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 211 | 7, 6, 8, 5, 9, 11, 10, kRestartStrip, // Second half of the hull. |
| 212 | 13, 12, 14, 15, kRestartStrip, // First corner. |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 213 | 17, 16, 18, 19 // Final corner. |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 214 | }; |
| 215 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 216 | static constexpr uint16_t kCurveIndicesAsTris[] = { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 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, |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 230 | |
| 231 | // First corner. |
| 232 | 13, 12, 14, |
| 233 | 12, 15, 14, |
| 234 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 235 | // Final corner. |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 236 | 17, 16, 18, |
| 237 | 16, 19, 18, |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 238 | }; |
| 239 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 240 | GR_DECLARE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 241 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 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 | // Curves are drawn in two separate passes. Here we just draw a conservative raster around the input |
| 253 | // points. The Shader takes care of everything else for now. The final curve corners get touched up |
| 254 | // in a later step by VSCornerImpl. |
| 255 | void GrCCCoverageProcessor::VSImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
| 256 | const GrCCCoverageProcessor& proc = args.fGP.cast<GrCCCoverageProcessor>(); |
| 257 | GrGLSLVertexBuilder* v = args.fVertBuilder; |
| 258 | int numInputPoints = proc.numInputPoints(); |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 259 | |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 260 | int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3; |
| 261 | const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz"; |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 262 | v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth, |
| 263 | proc.getAttrib(kAttribIdx_X).name(), swizzle, |
| 264 | proc.getAttrib(kAttribIdx_Y).name(), swizzle); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 265 | |
Chris Dalton | 6f5e77a | 2018-04-23 21:14:42 -0600 | [diff] [blame] | 266 | v->codeAppend ("half wind;"); |
| 267 | Shader::CalcWind(proc, v, "pts", "wind"); |
| 268 | if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 269 | SkASSERT(3 == numInputPoints); |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 270 | SkASSERT(kFloat4_GrVertexAttribType == proc.getAttrib(kAttribIdx_X).type()); |
| 271 | v->codeAppendf("wind *= %s.w;", proc.getAttrib(kAttribIdx_X).name()); |
Chris Dalton | 622650a | 2018-03-07 17:30:10 -0700 | [diff] [blame] | 272 | } |
| 273 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 274 | float bloat = kAABloatRadius; |
| 275 | #ifdef SK_DEBUG |
| 276 | if (proc.debugBloatEnabled()) { |
| 277 | bloat *= proc.debugBloat(); |
| 278 | } |
| 279 | #endif |
| 280 | v->defineConstant("bloat", bloat); |
| 281 | |
| 282 | const char* hullPts = "pts"; |
Chris Dalton | 9713dcf | 2018-04-10 00:48:41 -0600 | [diff] [blame] | 283 | fShader->emitSetupCode(v, "pts", "wind", (4 == fNumSides) ? &hullPts : nullptr); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 284 | |
| 285 | // Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0]. |
| 286 | v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;", |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 287 | proc.getAttrib(kAttribIdx_VertexData).name(), |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 288 | ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) | |
| 289 | ((fNumSides - 1) << kVertexData_RightNeighborIdShift) | |
| 290 | (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) | |
| 291 | (fNumSides - 1), |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 292 | proc.getAttrib(kAttribIdx_VertexData).name()); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 293 | |
| 294 | // Here we generate conservative raster geometry for the input polygon. It is the convex |
| 295 | // hull of N pixel-size boxes, one centered on each the input points. Each corner has three |
| 296 | // vertices, where one or two may cause degenerate triangles. The vertex data tells us how |
| 297 | // to offset each vertex. Triangle edges and corners are also handled here using the same |
| 298 | // concept. For more details on conservative raster, see: |
| 299 | // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html |
| 300 | v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts); |
| 301 | v->codeAppendf("float2 left = %s[clockwise_indices >> %i];", |
| 302 | hullPts, kVertexData_LeftNeighborIdShift); |
| 303 | v->codeAppendf("float2 right = %s[(clockwise_indices >> %i) & 3];", |
| 304 | hullPts, kVertexData_RightNeighborIdShift); |
| 305 | |
| 306 | v->codeAppend ("float2 leftbloat = sign(corner - left);"); |
| 307 | v->codeAppend ("leftbloat = float2(0 != leftbloat.y ? leftbloat.y : leftbloat.x, " |
| 308 | "0 != leftbloat.x ? -leftbloat.x : -leftbloat.y);"); |
| 309 | |
| 310 | v->codeAppend ("float2 rightbloat = sign(right - corner);"); |
| 311 | v->codeAppend ("rightbloat = float2(0 != rightbloat.y ? rightbloat.y : rightbloat.x, " |
| 312 | "0 != rightbloat.x ? -rightbloat.x : -rightbloat.y);"); |
| 313 | |
| 314 | v->codeAppend ("bool2 left_right_notequal = notEqual(leftbloat, rightbloat);"); |
| 315 | |
| 316 | v->codeAppend ("float2 bloatdir = leftbloat;"); |
| 317 | |
| 318 | v->codeAppend ("float2 leftdir = corner - left;"); |
| 319 | v->codeAppend ("leftdir = (float2(0) != leftdir) ? normalize(leftdir) : float2(1, 0);"); |
| 320 | |
| 321 | v->codeAppend ("float2 rightdir = right - corner;"); |
| 322 | v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);"); |
| 323 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 324 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? |
| 325 | proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsCornerBit); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 326 | |
| 327 | // In corner boxes, all 4 coverage values will not map linearly. |
| 328 | // Therefore it is important to align the box so its diagonal shared |
| 329 | // edge points out of the triangle, in the direction that ramps to 0. |
| 330 | v->codeAppend ( "bloatdir = float2(leftdir.x > rightdir.x ? +1 : -1, " |
| 331 | "leftdir.y > rightdir.y ? +1 : -1);"); |
| 332 | |
| 333 | // For corner boxes, we hack left_right_notequal to always true. This |
| 334 | // in turn causes the upcoming code to always rotate, generating all |
| 335 | // 4 vertices of the corner box. |
| 336 | v->codeAppendf( "left_right_notequal = bool2(true);"); |
| 337 | v->codeAppend ("}"); |
| 338 | |
| 339 | // At each corner of the polygon, our hull will have either 1, 2, or 3 vertices (or 4 if |
| 340 | // it's a corner box). We begin with this corner's first raster vertex (leftbloat), then |
| 341 | // continue rotating 90 degrees clockwise until we reach the desired raster vertex for this |
| 342 | // invocation. Corners with less than 3 corresponding raster vertices will result in |
| 343 | // redundant vertices and degenerate triangles. |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 344 | v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.getAttrib(kAttribIdx_VertexData).name(), |
| 345 | kVertexData_BloatIdxShift); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 346 | v->codeAppend ("switch (bloatidx) {"); |
| 347 | v->codeAppend ( "case 3:"); |
| 348 | // Only corners will have bloatidx=3, and corners always rotate. |
| 349 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 350 | // fallthru. |
| 351 | v->codeAppend ( "case 2:"); |
| 352 | v->codeAppendf( "if (all(left_right_notequal)) {"); |
| 353 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 354 | v->codeAppend ( "}"); |
| 355 | // fallthru. |
| 356 | v->codeAppend ( "case 1:"); |
| 357 | v->codeAppendf( "if (any(left_right_notequal)) {"); |
| 358 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 359 | v->codeAppend ( "}"); |
| 360 | // fallthru. |
| 361 | v->codeAppend ("}"); |
| 362 | |
| 363 | v->codeAppend ("float2 vertex = corner + bloatdir * bloat;"); |
| 364 | gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertex"); |
| 365 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 366 | // Hulls have a coverage of +1 all around. |
| 367 | v->codeAppend ("half coverage = +1;"); |
| 368 | |
| 369 | if (3 == fNumSides) { |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 370 | v->codeAppend ("half left_coverage; {"); |
| 371 | Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage"); |
| 372 | v->codeAppend ("}"); |
| 373 | |
| 374 | v->codeAppend ("half right_coverage; {"); |
| 375 | Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage"); |
| 376 | v->codeAppend ("}"); |
| 377 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 378 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge? |
| 379 | proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsEdgeBit); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 380 | v->codeAppend ( "coverage = left_coverage;"); |
| 381 | v->codeAppend ("}"); |
| 382 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 383 | v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage? |
| 384 | proc.getAttrib(kAttribIdx_VertexData).name(), |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 385 | kVertexData_InvertNegativeCoverageBit); |
| 386 | v->codeAppend ( "coverage = -1 - coverage;"); |
| 387 | v->codeAppend ("}"); |
| 388 | } |
| 389 | |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 390 | // Non-corner geometry should have zero effect from corner coverage. |
| 391 | v->codeAppend ("half2 corner_coverage = half2(0);"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 392 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 393 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? |
| 394 | proc.getAttrib(kAttribIdx_VertexData).name(), kVertexData_IsCornerBit); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 395 | // We use coverage=-1 to erase what the hull geometry wrote. |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 396 | // |
| 397 | // In the context of curves, this effectively means "wind = -wind" and |
| 398 | // causes the Shader to erase what it had written previously for the hull. |
| 399 | // |
| 400 | // For triangles it just erases the "+1" value written by the hull geometry. |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 401 | v->codeAppend ( "coverage = -1;"); |
| 402 | if (3 == fNumSides) { |
| 403 | // Triangle corners also have to erase what the edge geometry wrote. |
| 404 | v->codeAppend ("coverage -= left_coverage + right_coverage;"); |
| 405 | } |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 406 | |
| 407 | // Corner boxes require attenuated coverage. |
| 408 | v->codeAppend ( "half attenuation; {"); |
| 409 | Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 410 | v->codeAppend ( "}"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 411 | |
| 412 | // Attenuate corner coverage towards the outermost vertex (where bloatidx=0). |
| 413 | // This is all that curves need: At each vertex of the corner box, the curve |
| 414 | // Shader will calculate the curve's local coverage value, interpolate it |
| 415 | // alongside our attenuation parameter, and multiply the two together for a |
| 416 | // final coverage value. |
| 417 | v->codeAppend ( "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(1);"); |
| 418 | |
| 419 | if (3 == fNumSides) { |
| 420 | // For triangles we also provide the actual coverage values at each vertex of |
| 421 | // the corner box. |
| 422 | v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {"); |
| 423 | v->codeAppend ( "corner_coverage.x += right_coverage;"); |
| 424 | v->codeAppend ("}"); |
| 425 | v->codeAppend ("if (bloatidx >= 2) {"); |
| 426 | v->codeAppend ( "corner_coverage.x += left_coverage;"); |
| 427 | v->codeAppend ("}"); |
| 428 | } |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 429 | v->codeAppend ("}"); |
| 430 | |
| 431 | GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 432 | v->codeAppend ("coverage *= wind;"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 433 | v->codeAppend ("corner_coverage.x *= wind;"); |
| 434 | fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &v->code(), |
| 435 | gpArgs->fPositionVar.c_str(), "coverage", "corner_coverage"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 436 | |
| 437 | varyingHandler->emitAttributes(proc); |
| 438 | SkASSERT(!args.fFPCoordTransformHandler->nextCoordTransform()); |
| 439 | |
| 440 | // Fragment shader. |
| 441 | fShader->emitFragmentCode(proc, args.fFragBuilder, args.fOutputColor, args.fOutputCoverage); |
| 442 | } |
Chris Dalton | 622650a | 2018-03-07 17:30:10 -0700 | [diff] [blame] | 443 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 444 | void GrCCCoverageProcessor::initVS(GrResourceProvider* rp) { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 445 | SkASSERT(Impl::kVertexShader == fImpl); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 446 | const GrCaps& caps = *rp->caps(); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 447 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 448 | switch (fPrimitiveType) { |
Chris Dalton | 703b476 | 2018-04-06 16:11:48 -0600 | [diff] [blame] | 449 | case PrimitiveType::kTriangles: |
| 450 | case PrimitiveType::kWeightedTriangles: { |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 451 | GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 452 | fVSVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType, |
| 453 | sizeof(kTriangleVertices), |
| 454 | kTriangleVertices, |
| 455 | gTriangleVertexBufferKey); |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 456 | GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey); |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 457 | if (caps.usePrimitiveRestart()) { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 458 | fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, |
| 459 | sizeof(kTriangleIndicesAsStrips), |
| 460 | kTriangleIndicesAsStrips, |
| 461 | gTriangleIndexBufferKey); |
| 462 | fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips); |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 463 | } else { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 464 | fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, |
| 465 | sizeof(kTriangleIndicesAsTris), |
| 466 | kTriangleIndicesAsTris, |
| 467 | gTriangleIndexBufferKey); |
| 468 | fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 469 | } |
| 470 | break; |
| 471 | } |
| 472 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 473 | case PrimitiveType::kQuadratics: |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 474 | case PrimitiveType::kCubics: |
| 475 | case PrimitiveType::kConics: { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 476 | GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey); |
| 477 | fVSVertexBuffer = rp->findOrMakeStaticBuffer(kVertex_GrBufferType, |
| 478 | sizeof(kCurveVertices), kCurveVertices, |
| 479 | gCurveVertexBufferKey); |
| 480 | GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 481 | if (caps.usePrimitiveRestart()) { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 482 | fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, |
| 483 | sizeof(kCurveIndicesAsStrips), |
| 484 | kCurveIndicesAsStrips, |
| 485 | gCurveIndexBufferKey); |
| 486 | fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 487 | } else { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 488 | fVSIndexBuffer = rp->findOrMakeStaticBuffer(kIndex_GrBufferType, |
| 489 | sizeof(kCurveIndicesAsTris), |
| 490 | kCurveIndicesAsTris, |
| 491 | gCurveIndexBufferKey); |
| 492 | fVSNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 493 | } |
| 494 | break; |
| 495 | } |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 496 | } |
| 497 | |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 498 | if (4 == this->numInputPoints() || this->hasInputWeight()) { |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 499 | SkASSERT(kAttribIdx_X == this->numAttribs()); |
| 500 | this->addInstanceAttrib("X", kFloat4_GrVertexAttribType); |
| 501 | |
| 502 | SkASSERT(kAttribIdx_Y == this->numAttribs()); |
| 503 | this->addInstanceAttrib("Y", kFloat4_GrVertexAttribType); |
| 504 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 505 | SkASSERT(offsetof(QuadPointInstance, fX) == this->getAttrib(kAttribIdx_X).offsetInRecord()); |
| 506 | SkASSERT(offsetof(QuadPointInstance, fY) == this->getAttrib(kAttribIdx_Y).offsetInRecord()); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 507 | SkASSERT(sizeof(QuadPointInstance) == this->getInstanceStride()); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 508 | } else { |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 509 | SkASSERT(kAttribIdx_X == this->numAttribs()); |
| 510 | this->addInstanceAttrib("X", kFloat3_GrVertexAttribType); |
| 511 | |
| 512 | SkASSERT(kAttribIdx_Y == this->numAttribs()); |
| 513 | this->addInstanceAttrib("Y", kFloat3_GrVertexAttribType); |
| 514 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame^] | 515 | SkASSERT(offsetof(TriPointInstance, fX) == this->getAttrib(kAttribIdx_X).offsetInRecord()); |
| 516 | SkASSERT(offsetof(TriPointInstance, fY) == this->getAttrib(kAttribIdx_Y).offsetInRecord()); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 517 | SkASSERT(sizeof(TriPointInstance) == this->getInstanceStride()); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 518 | } |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 519 | |
Chris Dalton | 21ba551 | 2018-03-21 17:20:21 -0600 | [diff] [blame] | 520 | SkASSERT(kAttribIdx_VertexData == this->numAttribs()); |
| 521 | this->addVertexAttrib("vertexdata", kInt_GrVertexAttribType); |
| 522 | SkASSERT(sizeof(int32_t) == this->getVertexStride()); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 523 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 524 | if (caps.usePrimitiveRestart()) { |
| 525 | this->setWillUsePrimitiveRestart(); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 526 | fVSTriangleType = GrPrimitiveType::kTriangleStrip; |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 527 | } else { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 528 | fVSTriangleType = GrPrimitiveType::kTriangles; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 529 | } |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 530 | } |
| 531 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 532 | void GrCCCoverageProcessor::appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, |
| 533 | int baseInstance, SkTArray<GrMesh>* out) const { |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 534 | SkASSERT(Impl::kVertexShader == fImpl); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 535 | GrMesh& mesh = out->emplace_back(fVSTriangleType); |
| 536 | mesh.setIndexedInstanced(fVSIndexBuffer.get(), fVSNumIndicesPerInstance, instanceBuffer, |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 537 | instanceCount, baseInstance); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 538 | mesh.setVertexData(fVSVertexBuffer.get(), 0); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 539 | } |
| 540 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 541 | GrGLSLPrimitiveProcessor* GrCCCoverageProcessor::createVSImpl(std::unique_ptr<Shader> shadr) const { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 542 | switch (fPrimitiveType) { |
| 543 | case PrimitiveType::kTriangles: |
Chris Dalton | 703b476 | 2018-04-06 16:11:48 -0600 | [diff] [blame] | 544 | case PrimitiveType::kWeightedTriangles: |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 545 | return new VSImpl(std::move(shadr), 3); |
| 546 | case PrimitiveType::kQuadratics: |
| 547 | case PrimitiveType::kCubics: |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 548 | case PrimitiveType::kConics: |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 549 | return new VSImpl(std::move(shadr), 4); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 550 | } |
| 551 | SK_ABORT("Invalid RenderPass"); |
| 552 | return nullptr; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 553 | } |