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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "src/gpu/ccpr/GrVSCoverageProcessor.h" |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 9 | |
Chris Dalton | 39ca973 | 2020-03-10 10:34:17 -0600 | [diff] [blame^] | 10 | #include "src/gpu/GrOpsRenderPass.h" |
Robert Phillips | 03e4c95 | 2019-11-26 16:20:22 -0500 | [diff] [blame] | 11 | #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 12 | #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 13 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 14 | // This class implements the coverage processor with vertex shaders. |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 15 | class GrVSCoverageProcessor::Impl : public GrGLSLGeometryProcessor { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 16 | public: |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 17 | Impl(std::unique_ptr<Shader> shader, int numSides) |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 18 | : fShader(std::move(shader)), fNumSides(numSides) {} |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 19 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 20 | private: |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 21 | void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, |
Brian Salomon | c241b58 | 2019-11-27 08:57:17 -0500 | [diff] [blame] | 22 | const CoordTransformRange& transformRange) final { |
| 23 | this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 24 | } |
| 25 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 26 | void onEmitCode(EmitArgs&, GrGPArgs*) override; |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 27 | |
| 28 | const std::unique_ptr<Shader> fShader; |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 29 | const int fNumSides; |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 30 | }; |
| 31 | |
Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 32 | static constexpr int kInstanceAttribIdx_X = 0; // Transposed X values of all input points. |
| 33 | static constexpr int kInstanceAttribIdx_Y = 1; // Transposed Y values of all input points. |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 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 | // |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 252 | // Curve shaders handle the opposite edge and corners on their own. For curves we just generate a |
| 253 | // conservative raster here and the shader does the rest. |
| 254 | void GrVSCoverageProcessor::Impl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { |
| 255 | const GrVSCoverageProcessor& proc = args.fGP.cast<GrVSCoverageProcessor>(); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 256 | GrGLSLVertexBuilder* v = args.fVertBuilder; |
| 257 | int numInputPoints = proc.numInputPoints(); |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 258 | |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 259 | int inputWidth = (4 == numInputPoints || proc.hasInputWeight()) ? 4 : 3; |
| 260 | const char* swizzle = (4 == inputWidth) ? "xyzw" : "xyz"; |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 261 | v->codeAppendf("float%ix2 pts = transpose(float2x%i(%s.%s, %s.%s));", inputWidth, inputWidth, |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 262 | proc.fInputXAndYValues[kInstanceAttribIdx_X].name(), swizzle, |
| 263 | proc.fInputXAndYValues[kInstanceAttribIdx_Y].name(), swizzle); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 264 | |
Chris Dalton | 6f5e77a | 2018-04-23 21:14:42 -0600 | [diff] [blame] | 265 | v->codeAppend ("half wind;"); |
| 266 | Shader::CalcWind(proc, v, "pts", "wind"); |
| 267 | if (PrimitiveType::kWeightedTriangles == proc.fPrimitiveType) { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 268 | SkASSERT(3 == numInputPoints); |
Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 269 | SkASSERT(kFloat4_GrVertexAttribType == |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 270 | proc.fInputXAndYValues[kInstanceAttribIdx_X].cpuType()); |
Ethan Nicholas | e1f5502 | 2019-02-05 17:17:40 -0500 | [diff] [blame] | 271 | v->codeAppendf("wind *= half(%s.w);", |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 272 | proc.fInputXAndYValues[kInstanceAttribIdx_X].name()); |
Chris Dalton | 622650a | 2018-03-07 17:30:10 -0700 | [diff] [blame] | 273 | } |
| 274 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 275 | float bloat = kAABloatRadius; |
| 276 | #ifdef SK_DEBUG |
| 277 | if (proc.debugBloatEnabled()) { |
| 278 | bloat *= proc.debugBloat(); |
| 279 | } |
| 280 | #endif |
| 281 | v->defineConstant("bloat", bloat); |
| 282 | |
| 283 | const char* hullPts = "pts"; |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 284 | fShader->emitSetupCode(v, "pts", (4 == fNumSides) ? &hullPts : nullptr); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 285 | |
| 286 | // Reverse all indices if the wind is counter-clockwise: [0, 1, 2] -> [2, 1, 0]. |
| 287 | v->codeAppendf("int clockwise_indices = wind > 0 ? %s : 0x%x - %s;", |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 288 | proc.fPerVertexData.name(), |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 289 | ((fNumSides - 1) << kVertexData_LeftNeighborIdShift) | |
| 290 | ((fNumSides - 1) << kVertexData_RightNeighborIdShift) | |
| 291 | (((1 << kVertexData_RightNeighborIdShift) - 1) ^ 3) | |
| 292 | (fNumSides - 1), |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 293 | proc.fPerVertexData.name()); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 294 | |
| 295 | // Here we generate conservative raster geometry for the input polygon. It is the convex |
| 296 | // hull of N pixel-size boxes, one centered on each the input points. Each corner has three |
| 297 | // vertices, where one or two may cause degenerate triangles. The vertex data tells us how |
| 298 | // to offset each vertex. Triangle edges and corners are also handled here using the same |
| 299 | // concept. For more details on conservative raster, see: |
| 300 | // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter42.html |
| 301 | v->codeAppendf("float2 corner = %s[clockwise_indices & 3];", hullPts); |
| 302 | v->codeAppendf("float2 left = %s[clockwise_indices >> %i];", |
| 303 | hullPts, kVertexData_LeftNeighborIdShift); |
| 304 | v->codeAppendf("float2 right = %s[(clockwise_indices >> %i) & 3];", |
| 305 | hullPts, kVertexData_RightNeighborIdShift); |
| 306 | |
| 307 | v->codeAppend ("float2 leftbloat = sign(corner - left);"); |
| 308 | v->codeAppend ("leftbloat = float2(0 != leftbloat.y ? leftbloat.y : leftbloat.x, " |
| 309 | "0 != leftbloat.x ? -leftbloat.x : -leftbloat.y);"); |
| 310 | |
| 311 | v->codeAppend ("float2 rightbloat = sign(right - corner);"); |
| 312 | v->codeAppend ("rightbloat = float2(0 != rightbloat.y ? rightbloat.y : rightbloat.x, " |
| 313 | "0 != rightbloat.x ? -rightbloat.x : -rightbloat.y);"); |
| 314 | |
| 315 | v->codeAppend ("bool2 left_right_notequal = notEqual(leftbloat, rightbloat);"); |
| 316 | |
| 317 | v->codeAppend ("float2 bloatdir = leftbloat;"); |
| 318 | |
| 319 | v->codeAppend ("float2 leftdir = corner - left;"); |
| 320 | v->codeAppend ("leftdir = (float2(0) != leftdir) ? normalize(leftdir) : float2(1, 0);"); |
| 321 | |
| 322 | v->codeAppend ("float2 rightdir = right - corner;"); |
| 323 | v->codeAppend ("rightdir = (float2(0) != rightdir) ? normalize(rightdir) : float2(1, 0);"); |
| 324 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 325 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 326 | proc.fPerVertexData.name(), kVertexData_IsCornerBit); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 327 | |
| 328 | // In corner boxes, all 4 coverage values will not map linearly. |
| 329 | // Therefore it is important to align the box so its diagonal shared |
| 330 | // edge points out of the triangle, in the direction that ramps to 0. |
| 331 | v->codeAppend ( "bloatdir = float2(leftdir.x > rightdir.x ? +1 : -1, " |
| 332 | "leftdir.y > rightdir.y ? +1 : -1);"); |
| 333 | |
| 334 | // For corner boxes, we hack left_right_notequal to always true. This |
| 335 | // in turn causes the upcoming code to always rotate, generating all |
| 336 | // 4 vertices of the corner box. |
| 337 | v->codeAppendf( "left_right_notequal = bool2(true);"); |
| 338 | v->codeAppend ("}"); |
| 339 | |
| 340 | // At each corner of the polygon, our hull will have either 1, 2, or 3 vertices (or 4 if |
| 341 | // it's a corner box). We begin with this corner's first raster vertex (leftbloat), then |
| 342 | // continue rotating 90 degrees clockwise until we reach the desired raster vertex for this |
| 343 | // invocation. Corners with less than 3 corresponding raster vertices will result in |
| 344 | // redundant vertices and degenerate triangles. |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 345 | v->codeAppendf("int bloatidx = (%s >> %i) & 3;", proc.fPerVertexData.name(), |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 346 | kVertexData_BloatIdxShift); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 347 | v->codeAppend ("switch (bloatidx) {"); |
| 348 | v->codeAppend ( "case 3:"); |
| 349 | // Only corners will have bloatidx=3, and corners always rotate. |
| 350 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 351 | // fallthru. |
| 352 | v->codeAppend ( "case 2:"); |
| 353 | v->codeAppendf( "if (all(left_right_notequal)) {"); |
| 354 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 355 | v->codeAppend ( "}"); |
| 356 | // fallthru. |
| 357 | v->codeAppend ( "case 1:"); |
| 358 | v->codeAppendf( "if (any(left_right_notequal)) {"); |
| 359 | v->codeAppend ( "bloatdir = float2(-bloatdir.y, +bloatdir.x);"); // 90 deg CW. |
| 360 | v->codeAppend ( "}"); |
| 361 | // fallthru. |
| 362 | v->codeAppend ("}"); |
| 363 | |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 364 | v->codeAppend ("float2 vertexpos = fma(bloatdir, float2(bloat), corner);"); |
| 365 | gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 366 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 367 | // Hulls have a coverage of +1 all around. |
| 368 | v->codeAppend ("half coverage = +1;"); |
| 369 | |
| 370 | if (3 == fNumSides) { |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 371 | v->codeAppend ("half left_coverage; {"); |
| 372 | Shader::CalcEdgeCoverageAtBloatVertex(v, "left", "corner", "bloatdir", "left_coverage"); |
| 373 | v->codeAppend ("}"); |
| 374 | |
| 375 | v->codeAppend ("half right_coverage; {"); |
| 376 | Shader::CalcEdgeCoverageAtBloatVertex(v, "corner", "right", "bloatdir", "right_coverage"); |
| 377 | v->codeAppend ("}"); |
| 378 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 379 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we an edge? |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 380 | proc.fPerVertexData.name(), kVertexData_IsEdgeBit); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 381 | v->codeAppend ( "coverage = left_coverage;"); |
| 382 | v->codeAppend ("}"); |
| 383 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 384 | v->codeAppendf("if (0 != (%s & %i)) {", // Invert coverage? |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 385 | proc.fPerVertexData.name(), |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 386 | kVertexData_InvertNegativeCoverageBit); |
| 387 | v->codeAppend ( "coverage = -1 - coverage;"); |
| 388 | v->codeAppend ("}"); |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 389 | } else if (!fShader->calculatesOwnEdgeCoverage()) { |
| 390 | // Determine the amount of coverage to subtract out for the flat edge of the curve. |
| 391 | v->codeAppendf("float2 p0 = pts[0], p1 = pts[%i];", numInputPoints - 1); |
| 392 | v->codeAppendf("float2 n = float2(p0.y - p1.y, p1.x - p0.x);"); |
| 393 | v->codeAppend ("float nwidth = bloat*2 * (abs(n.x) + abs(n.y));"); |
| 394 | // When nwidth=0, wind must also be 0 (and coverage * wind = 0). So it doesn't matter |
| 395 | // what we come up with here as long as it isn't NaN or Inf. |
| 396 | v->codeAppend ("float d = dot(p0 - vertexpos, n);"); |
| 397 | v->codeAppend ("d /= (0 != nwidth) ? nwidth : 1;"); |
| 398 | v->codeAppend ("coverage = half(d) - .5*sign(wind);"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 399 | } |
| 400 | |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 401 | // Non-corner geometry should have zero effect from corner coverage. |
| 402 | v->codeAppend ("half2 corner_coverage = half2(0);"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 403 | |
Brian Salomon | 70132d0 | 2018-05-29 15:33:06 -0400 | [diff] [blame] | 404 | v->codeAppendf("if (0 != (%s & %i)) {", // Are we a corner? |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 405 | proc.fPerVertexData.name(), kVertexData_IsCornerBit); |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 406 | // Erase what the previous geometry wrote. |
| 407 | v->codeAppend ( "wind = -wind;"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 408 | if (3 == fNumSides) { |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 409 | v->codeAppend ("coverage = 1 + left_coverage + right_coverage;"); |
| 410 | } else if (!fShader->calculatesOwnEdgeCoverage()) { |
| 411 | v->codeAppend ("coverage = -coverage;"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 412 | } |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 413 | |
| 414 | // Corner boxes require attenuated coverage. |
| 415 | v->codeAppend ( "half attenuation; {"); |
| 416 | Shader::CalcCornerAttenuation(v, "leftdir", "rightdir", "attenuation"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 417 | v->codeAppend ( "}"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 418 | |
| 419 | // Attenuate corner coverage towards the outermost vertex (where bloatidx=0). |
| 420 | // This is all that curves need: At each vertex of the corner box, the curve |
| 421 | // Shader will calculate the curve's local coverage value, interpolate it |
| 422 | // alongside our attenuation parameter, and multiply the two together for a |
| 423 | // final coverage value. |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 424 | v->codeAppend ( "corner_coverage = (0 == bloatidx) ? half2(0, attenuation) : half2(-1,+1);"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 425 | |
| 426 | if (3 == fNumSides) { |
| 427 | // For triangles we also provide the actual coverage values at each vertex of |
| 428 | // the corner box. |
| 429 | v->codeAppend ("if (1 == bloatidx || 2 == bloatidx) {"); |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 430 | v->codeAppend ( "corner_coverage.x -= right_coverage;"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 431 | v->codeAppend ("}"); |
| 432 | v->codeAppend ("if (bloatidx >= 2) {"); |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 433 | v->codeAppend ( "corner_coverage.x -= left_coverage;"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 434 | v->codeAppend ("}"); |
| 435 | } |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 436 | v->codeAppend ("}"); |
| 437 | |
| 438 | GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 439 | v->codeAppend ("coverage *= wind;"); |
Chris Dalton | 4c23934 | 2018-04-05 18:43:40 -0600 | [diff] [blame] | 440 | v->codeAppend ("corner_coverage.x *= wind;"); |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 441 | fShader->emitVaryings(varyingHandler, GrGLSLVarying::Scope::kVertToFrag, &AccessCodeString(v), |
Chris Dalton | 84d36cd | 2019-04-17 14:47:17 -0600 | [diff] [blame] | 442 | "vertexpos", "coverage", "corner_coverage", "wind"); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 443 | |
| 444 | varyingHandler->emitAttributes(proc); |
Brian Salomon | 7d8b397 | 2019-11-26 22:34:44 -0500 | [diff] [blame] | 445 | SkASSERT(!*args.fFPCoordTransformHandler); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 446 | |
| 447 | // Fragment shader. |
Chris Dalton | c3318f0 | 2019-07-19 14:20:53 -0600 | [diff] [blame] | 448 | GrGLSLFPFragmentBuilder* f = args.fFragBuilder; |
| 449 | f->codeAppendf("half coverage;"); |
| 450 | fShader->emitFragmentCoverageCode(f, "coverage"); |
| 451 | f->codeAppendf("%s = half4(coverage);", args.fOutputColor); |
| 452 | f->codeAppendf("%s = half4(1);", args.fOutputCoverage); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 453 | } |
Chris Dalton | 622650a | 2018-03-07 17:30:10 -0700 | [diff] [blame] | 454 | |
Chris Dalton | 39ca973 | 2020-03-10 10:34:17 -0600 | [diff] [blame^] | 455 | void GrVSCoverageProcessor::reset(PrimitiveType primitiveType, int subpassIdx, |
| 456 | GrResourceProvider* rp) { |
| 457 | SkASSERT(subpassIdx == 0); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 458 | const GrCaps& caps = *rp->caps(); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 459 | |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 460 | fPrimitiveType = primitiveType; |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 461 | switch (fPrimitiveType) { |
Chris Dalton | 703b476 | 2018-04-06 16:11:48 -0600 | [diff] [blame] | 462 | case PrimitiveType::kTriangles: |
| 463 | case PrimitiveType::kWeightedTriangles: { |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 464 | GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleVertexBufferKey); |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 465 | fVertexBuffer = rp->findOrMakeStaticBuffer( |
| 466 | GrGpuBufferType::kVertex, sizeof(kTriangleVertices), kTriangleVertices, |
| 467 | gTriangleVertexBufferKey); |
Chris Dalton | 8738cf4 | 2018-03-09 11:57:40 -0700 | [diff] [blame] | 468 | GR_DEFINE_STATIC_UNIQUE_KEY(gTriangleIndexBufferKey); |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 469 | if (caps.usePrimitiveRestart()) { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 470 | fIndexBuffer = rp->findOrMakeStaticBuffer( |
| 471 | GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsStrips), |
| 472 | kTriangleIndicesAsStrips, gTriangleIndexBufferKey); |
| 473 | fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsStrips); |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 474 | } else { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 475 | fIndexBuffer = rp->findOrMakeStaticBuffer( |
| 476 | GrGpuBufferType::kIndex, sizeof(kTriangleIndicesAsTris), |
| 477 | kTriangleIndicesAsTris, gTriangleIndexBufferKey); |
| 478 | fNumIndicesPerInstance = SK_ARRAY_COUNT(kTriangleIndicesAsTris); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 479 | } |
| 480 | break; |
| 481 | } |
| 482 | |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 483 | case PrimitiveType::kQuadratics: |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 484 | case PrimitiveType::kCubics: |
| 485 | case PrimitiveType::kConics: { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 486 | GR_DEFINE_STATIC_UNIQUE_KEY(gCurveVertexBufferKey); |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 487 | fVertexBuffer = rp->findOrMakeStaticBuffer( |
| 488 | GrGpuBufferType::kVertex, sizeof(kCurveVertices), kCurveVertices, |
| 489 | gCurveVertexBufferKey); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 490 | GR_DEFINE_STATIC_UNIQUE_KEY(gCurveIndexBufferKey); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 491 | if (caps.usePrimitiveRestart()) { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 492 | fIndexBuffer = rp->findOrMakeStaticBuffer( |
| 493 | GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsStrips), |
| 494 | kCurveIndicesAsStrips, gCurveIndexBufferKey); |
| 495 | fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsStrips); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 496 | } else { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 497 | fIndexBuffer = rp->findOrMakeStaticBuffer( |
| 498 | GrGpuBufferType::kIndex, sizeof(kCurveIndicesAsTris), kCurveIndicesAsTris, |
| 499 | gCurveIndexBufferKey); |
| 500 | fNumIndicesPerInstance = SK_ARRAY_COUNT(kCurveIndicesAsTris); |
Chris Dalton | baf3e78 | 2018-03-08 15:55:58 +0000 | [diff] [blame] | 501 | } |
| 502 | break; |
| 503 | } |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 504 | } |
| 505 | |
Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 506 | GrVertexAttribType xyAttribType; |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 507 | GrSLType xySLType; |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 508 | if (4 == this->numInputPoints() || this->hasInputWeight()) { |
Brian Salomon | 4dea72a | 2019-12-18 10:43:10 -0500 | [diff] [blame] | 509 | static_assert(offsetof(QuadPointInstance, fX) == 0); |
| 510 | static_assert(sizeof(QuadPointInstance::fX) == |
| 511 | GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); |
| 512 | static_assert(sizeof(QuadPointInstance::fY) == |
| 513 | GrVertexAttribTypeSize(kFloat4_GrVertexAttribType)); |
Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 514 | xyAttribType = kFloat4_GrVertexAttribType; |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 515 | xySLType = kFloat4_GrSLType; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 516 | } else { |
Brian Salomon | 4dea72a | 2019-12-18 10:43:10 -0500 | [diff] [blame] | 517 | static_assert(sizeof(TriPointInstance) == |
| 518 | 2 * GrVertexAttribTypeSize(kFloat3_GrVertexAttribType)); |
Brian Salomon | 92be2f7 | 2018-06-19 14:33:47 -0400 | [diff] [blame] | 519 | xyAttribType = kFloat3_GrVertexAttribType; |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 520 | xySLType = kFloat3_GrSLType; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 521 | } |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 522 | fInputXAndYValues[kInstanceAttribIdx_X] = {"X", xyAttribType, xySLType}; |
| 523 | fInputXAndYValues[kInstanceAttribIdx_Y] = {"Y", xyAttribType, xySLType}; |
| 524 | this->setInstanceAttributes(fInputXAndYValues, 2); |
| 525 | fPerVertexData = {"vertexdata", kInt_GrVertexAttribType, kInt_GrSLType}; |
| 526 | this->setVertexAttributes(&fPerVertexData, 1); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 527 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 528 | if (caps.usePrimitiveRestart()) { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 529 | fTriangleType = GrPrimitiveType::kTriangleStrip; |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 530 | } else { |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 531 | fTriangleType = GrPrimitiveType::kTriangles; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 532 | } |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 533 | } |
| 534 | |
Chris Dalton | 39ca973 | 2020-03-10 10:34:17 -0600 | [diff] [blame^] | 535 | void GrVSCoverageProcessor::bindBuffers(GrOpsRenderPass* renderPass, |
| 536 | const GrBuffer* instanceBuffer) const { |
Robert Phillips | cea290f | 2019-11-06 11:21:03 -0500 | [diff] [blame] | 537 | SkASSERT(fTriangleType == GrPrimitiveType::kTriangles || |
| 538 | fTriangleType == GrPrimitiveType::kTriangleStrip); |
Chris Dalton | 39ca973 | 2020-03-10 10:34:17 -0600 | [diff] [blame^] | 539 | renderPass->bindBuffers(fIndexBuffer.get(), instanceBuffer, fVertexBuffer.get(), |
| 540 | GrPrimitiveRestart(GrPrimitiveType::kTriangleStrip == fTriangleType)); |
| 541 | } |
Robert Phillips | cea290f | 2019-11-06 11:21:03 -0500 | [diff] [blame] | 542 | |
Chris Dalton | 39ca973 | 2020-03-10 10:34:17 -0600 | [diff] [blame^] | 543 | void GrVSCoverageProcessor::drawInstances(GrOpsRenderPass* renderPass, int instanceCount, |
| 544 | int baseInstance) const { |
| 545 | renderPass->drawIndexedInstanced(fNumIndicesPerInstance, 0, instanceCount, baseInstance, 0); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 546 | } |
| 547 | |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 548 | GrGLSLPrimitiveProcessor* GrVSCoverageProcessor::onCreateGLSLInstance( |
| 549 | std::unique_ptr<Shader> shader) const { |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 550 | switch (fPrimitiveType) { |
| 551 | case PrimitiveType::kTriangles: |
Chris Dalton | 703b476 | 2018-04-06 16:11:48 -0600 | [diff] [blame] | 552 | case PrimitiveType::kWeightedTriangles: |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 553 | return new Impl(std::move(shader), 3); |
Chris Dalton | 8dfc70f | 2018-03-26 19:15:22 -0600 | [diff] [blame] | 554 | case PrimitiveType::kQuadratics: |
| 555 | case PrimitiveType::kCubics: |
Chris Dalton | 9f2dab0 | 2018-04-18 14:07:03 -0600 | [diff] [blame] | 556 | case PrimitiveType::kConics: |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 557 | return new Impl(std::move(shader), 4); |
Chris Dalton | fe462ef | 2018-03-08 15:54:01 +0000 | [diff] [blame] | 558 | } |
Chris Dalton | 2c5e011 | 2019-03-29 13:14:18 -0500 | [diff] [blame] | 559 | SK_ABORT("Invalid PrimitiveType"); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 560 | } |