Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [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 | #ifndef GrCCCoverageProcessor_DEFINED |
| 9 | #define GrCCCoverageProcessor_DEFINED |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 10 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 11 | #include "GrCaps.h" |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 12 | #include "GrGeometryProcessor.h" |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 13 | #include "GrShaderCaps.h" |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 14 | #include "SkNx.h" |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 15 | #include "glsl/GrGLSLGeometryProcessor.h" |
| 16 | #include "glsl/GrGLSLVarying.h" |
| 17 | |
Robert Phillips | 7f86192 | 2018-01-30 13:13:42 +0000 | [diff] [blame] | 18 | class GrGLSLPPFragmentBuilder; |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 19 | class GrGLSLVertexGeoBuilder; |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 20 | class GrMesh; |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 21 | |
| 22 | /** |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 23 | * This is the geometry processor for the simple convex primitive shapes (triangles and closed, |
| 24 | * convex bezier curves) from which ccpr paths are composed. The output is a single-channel alpha |
| 25 | * value, positive for clockwise shapes and negative for counter-clockwise, that indicates coverage. |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 26 | * |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 27 | * The caller is responsible to execute all render passes for all applicable primitives into a |
| 28 | * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass |
| 29 | * below). Once all of a path's primitives have been drawn, the render target contains a composite |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 30 | * coverage count that can then be used to draw the path (see GrCCPathProcessor). |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 31 | * |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 32 | * To draw a renderer pass, see appendMesh below. |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 33 | */ |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 34 | class GrCCCoverageProcessor : public GrGeometryProcessor { |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 35 | public: |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 36 | // Defines a single primitive shape with 3 input points (i.e. Triangles and Quadratics). |
| 37 | // X,Y point values are transposed. |
| 38 | struct TriPointInstance { |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 39 | float fX[3]; |
| 40 | float fY[3]; |
Chris Dalton | c1e5963 | 2017-09-05 00:30:07 -0600 | [diff] [blame] | 41 | |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 42 | void set(const SkPoint[3], const Sk2f& trans); |
| 43 | void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans); |
Chris Dalton | c1e5963 | 2017-09-05 00:30:07 -0600 | [diff] [blame] | 44 | }; |
| 45 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 46 | // Defines a single primitive shape with 4 input points, or 3 input points plus a W parameter |
| 47 | // duplicated in both 4th components (i.e. Cubics or Triangles with a custom winding number). |
| 48 | // X,Y point values are transposed. |
| 49 | struct QuadPointInstance { |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 50 | float fX[4]; |
| 51 | float fY[4]; |
| 52 | |
| 53 | void set(const SkPoint[4], float dx, float dy); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 54 | void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans, float w); |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 55 | }; |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 56 | |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 57 | // All primitive shapes (triangles and closed, convex bezier curves) require more than one |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 58 | // render pass. Here we enumerate every render pass needed in order to produce a complete |
| 59 | // coverage count mask. This is an exhaustive list of all ccpr coverage shaders. |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 60 | // |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 61 | // During a render pass, the "Impl" (GSImpl or VSimpl) generates conservative geometry for |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 62 | // rasterization, and the Shader decides the coverage value at each pixel. |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 63 | enum class RenderPass { |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 64 | // For a Hull, the Impl generates a "conservative raster hull" around the input points. This |
| 65 | // is the geometry that causes a pixel to be rasterized if it is touched anywhere by the |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 66 | // input polygon. The input coverage values sent to the Shader at each vertex are either |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 67 | // null, or +1 all around if the Impl combines this pass with kTriangleEdges. Logically, |
| 68 | // the conservative raster hull is equivalent to the convex hull of pixel size boxes |
| 69 | // centered on each input point. |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 70 | kTriangleHulls, |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 71 | kQuadraticHulls, |
Chris Dalton | be4ffab | 2017-12-08 10:59:58 -0700 | [diff] [blame] | 72 | kCubicHulls, |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 73 | |
| 74 | // For Edges, the Impl generates conservative rasters around every input edge (i.e. convex |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 75 | // hulls of two pixel-size boxes centered on both of the edge's endpoints). The input |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 76 | // coverage values sent to the Shader at each vertex are -1 on the outside border of the |
| 77 | // edge geometry and 0 on the inside. This is the only geometry type that associates |
| 78 | // coverage values with the output vertices. Interpolated, these coverage values convert |
| 79 | // jagged conservative raster edges into a smooth antialiased edge. |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 80 | // |
| 81 | // NOTE: The Impl may combine this pass with kTriangleHulls, in which case DoesRenderPass() |
| 82 | // will be false for kTriangleEdges and it must not be used. |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 83 | kTriangleEdges, |
| 84 | |
| 85 | // For Corners, the Impl Generates the conservative rasters of corner points (i.e. |
| 86 | // pixel-size boxes). It generates 3 corner boxes for triangles and 2 for curves. The Shader |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 87 | // specifies which corners. Input coverage values sent to the Shader will be null. |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 88 | kTriangleCorners, |
| 89 | kQuadraticCorners, |
Chris Dalton | be4ffab | 2017-12-08 10:59:58 -0700 | [diff] [blame] | 90 | kCubicCorners |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 91 | }; |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 92 | static bool RenderPassIsCubic(RenderPass); |
| 93 | static const char* RenderPassName(RenderPass); |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 94 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 95 | constexpr static bool DoesRenderPass(RenderPass renderPass, const GrCaps& caps) { |
| 96 | return RenderPass::kTriangleEdges != renderPass || |
| 97 | caps.shaderCaps()->geometryShaderSupport(); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 98 | } |
| 99 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 100 | enum class WindMethod : bool { |
| 101 | kCrossProduct, // Calculate wind = +/-1 by sign of the cross product. |
| 102 | kInstanceData // Instance data provides custom, signed wind values of any magnitude. |
| 103 | // (For tightly-wound tessellated triangles.) |
| 104 | }; |
| 105 | |
| 106 | GrCCCoverageProcessor(GrResourceProvider* rp, RenderPass pass, WindMethod windMethod) |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 107 | : INHERITED(kGrCCCoverageProcessor_ClassID) |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 108 | , fRenderPass(pass) |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 109 | , fWindMethod(windMethod) |
| 110 | , fImpl(rp->caps()->shaderCaps()->geometryShaderSupport() ? Impl::kGeometryShader |
| 111 | : Impl::kVertexShader) { |
| 112 | SkASSERT(DoesRenderPass(pass, *rp->caps())); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 113 | if (Impl::kGeometryShader == fImpl) { |
| 114 | this->initGS(); |
| 115 | } else { |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 116 | this->initVS(rp); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 117 | } |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 118 | } |
| 119 | |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 120 | // Appends a GrMesh that will draw the provided instances. The instanceBuffer must be an array |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 121 | // of either TriPointInstance or QuadPointInstance, depending on this processor's RendererPass, |
| 122 | // with coordinates in the desired shape's final atlas-space position. |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 123 | void appendMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 124 | SkTArray<GrMesh>* out) { |
| 125 | if (Impl::kGeometryShader == fImpl) { |
| 126 | this->appendGSMesh(instanceBuffer, instanceCount, baseInstance, out); |
| 127 | } else { |
| 128 | this->appendVSMesh(instanceBuffer, instanceCount, baseInstance, out); |
| 129 | } |
Chris Dalton | be4ffab | 2017-12-08 10:59:58 -0700 | [diff] [blame] | 130 | } |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 131 | |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 132 | // GrPrimitiveProcessor overrides. |
| 133 | const char* name() const override { return RenderPassName(fRenderPass); } |
| 134 | SkString dumpInfo() const override { |
| 135 | return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str()); |
| 136 | } |
| 137 | void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
| 138 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; |
| 139 | |
| 140 | #ifdef SK_DEBUG |
| 141 | // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of |
| 142 | // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red). |
| 143 | void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; } |
| 144 | bool debugVisualizationsEnabled() const { return fDebugBloat > 0; } |
| 145 | float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; } |
| 146 | #endif |
| 147 | |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 148 | // The Shader provides code to calculate each pixel's coverage in a RenderPass. It also |
| 149 | // provides details about shape-specific geometry. |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 150 | class Shader { |
| 151 | public: |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 152 | union GeometryVars { |
| 153 | struct { |
| 154 | const char* fAlternatePoints; // floatNx2 (if left null, will use input points). |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 155 | } fHullVars; |
| 156 | |
| 157 | struct { |
| 158 | const char* fPoint; // float2 |
| 159 | } fCornerVars; |
| 160 | |
| 161 | GeometryVars() { memset(this, 0, sizeof(*this)); } |
| 162 | }; |
| 163 | |
| 164 | // Called before generating geometry. Subclasses must fill out the applicable fields in |
| 165 | // GeometryVars (if any), and may also use this opportunity to setup internal member |
| 166 | // variables that will be needed during onEmitVaryings (e.g. transformation matrices). |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 167 | // |
| 168 | // repetitionID is a 0-based index and indicates which edge or corner is being generated. |
| 169 | // It will be null when generating a hull. |
| 170 | virtual void emitSetupCode(GrGLSLVertexGeoBuilder*, const char* pts, |
| 171 | const char* repetitionID, const char* wind, |
| 172 | GeometryVars*) const {} |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 173 | |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 174 | void emitVaryings(GrGLSLVaryingHandler* varyingHandler, GrGLSLVarying::Scope scope, |
| 175 | SkString* code, const char* position, const char* inputCoverage, |
| 176 | const char* wind) { |
| 177 | SkASSERT(GrGLSLVarying::Scope::kVertToGeo != scope); |
| 178 | this->onEmitVaryings(varyingHandler, scope, code, position, inputCoverage, wind); |
| 179 | } |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 180 | |
Robert Phillips | 7f86192 | 2018-01-30 13:13:42 +0000 | [diff] [blame] | 181 | void emitFragmentCode(const GrCCCoverageProcessor& proc, GrGLSLPPFragmentBuilder*, |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 182 | const char* skOutputColor, const char* skOutputCoverage) const; |
| 183 | |
| 184 | // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside |
Chris Dalton | cc0ab7e | 2017-10-24 14:16:52 -0600 | [diff] [blame] | 185 | // border of a conservative raster edge and 0 on the inside. 'leftPt' and 'rightPt' must be |
| 186 | // ordered clockwise. |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 187 | static void EmitEdgeDistanceEquation(GrGLSLVertexGeoBuilder*, const char* leftPt, |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 188 | const char* rightPt, |
| 189 | const char* outputDistanceEquation); |
| 190 | |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 191 | virtual ~Shader() {} |
| 192 | |
| 193 | protected: |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 194 | // Here the subclass adds its internal varyings to the handler and produces code to |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 195 | // initialize those varyings from a given position, input coverage value, and wind. |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 196 | // |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 197 | // NOTE: the coverage input is only relevant for edges (see comments in RenderPass). |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 198 | // Otherwise it is +1 all around. |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 199 | virtual void onEmitVaryings(GrGLSLVaryingHandler*, GrGLSLVarying::Scope, SkString* code, |
| 200 | const char* position, const char* inputCoverage, |
| 201 | const char* wind) = 0; |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 202 | |
Chris Dalton | f510e26 | 2018-01-30 16:42:37 -0700 | [diff] [blame] | 203 | // Emits the fragment code that calculates a pixel's signed coverage value. |
Robert Phillips | 7f86192 | 2018-01-30 13:13:42 +0000 | [diff] [blame] | 204 | virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*, |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 205 | const char* outputCoverage) const = 0; |
| 206 | |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 207 | // Returns the name of a Shader's internal varying at the point where where its value is |
| 208 | // assigned. This is intended to work whether called for a vertex or a geometry shader. |
| 209 | const char* OutName(const GrGLSLVarying& varying) const { |
| 210 | using Scope = GrGLSLVarying::Scope; |
| 211 | SkASSERT(Scope::kVertToGeo != varying.scope()); |
| 212 | return Scope::kGeoToFrag == varying.scope() ? varying.gsOut() : varying.vsOut(); |
| 213 | } |
| 214 | |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 215 | // Defines a global float2 array that contains MSAA sample locations as offsets from pixel |
| 216 | // center. Subclasses can use this for software multisampling. |
| 217 | // |
| 218 | // Returns the number of samples. |
Robert Phillips | 7f86192 | 2018-01-30 13:13:42 +0000 | [diff] [blame] | 219 | static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName); |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 220 | }; |
| 221 | |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 222 | class GSImpl; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 223 | class VSImpl; |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 224 | |
| 225 | private: |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 226 | // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't |
| 227 | // accidentally bleed into neighbor pixels. |
| 228 | static constexpr float kAABloatRadius = 0.491111f; |
| 229 | |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 230 | // Number of bezier points for curves, or 3 for triangles. |
| 231 | int numInputPoints() const { return RenderPassIsCubic(fRenderPass) ? 4 : 3; } |
| 232 | |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 233 | enum class Impl : bool { |
| 234 | kGeometryShader, |
| 235 | kVertexShader |
| 236 | }; |
| 237 | |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 238 | void initGS(); |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 239 | void initVS(GrResourceProvider*); |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 240 | |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 241 | void appendGSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 242 | SkTArray<GrMesh>* out) const; |
| 243 | void appendVSMesh(GrBuffer* instanceBuffer, int instanceCount, int baseInstance, |
| 244 | SkTArray<GrMesh>* out) const; |
| 245 | |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 246 | GrGLSLPrimitiveProcessor* createGSImpl(std::unique_ptr<Shader>) const; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 247 | GrGLSLPrimitiveProcessor* createVSImpl(std::unique_ptr<Shader>) const; |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 248 | |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 249 | const RenderPass fRenderPass; |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 250 | const WindMethod fWindMethod; |
Chris Dalton | 90e8fb1 | 2017-12-22 02:24:53 -0700 | [diff] [blame] | 251 | const Impl fImpl; |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 252 | SkDEBUGCODE(float fDebugBloat = 0); |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 253 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 254 | // Used by VSImpl. |
| 255 | sk_sp<const GrBuffer> fVertexBuffer; |
| 256 | sk_sp<const GrBuffer> fIndexBuffer; |
| 257 | int fNumIndicesPerInstance; |
| 258 | GrPrimitiveType fPrimitiveType; |
| 259 | |
Chris Dalton | 6a3dbee | 2017-10-16 10:44:41 -0600 | [diff] [blame] | 260 | typedef GrGeometryProcessor INHERITED; |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 261 | }; |
| 262 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 263 | inline void GrCCCoverageProcessor::TriPointInstance::set(const SkPoint p[3], const Sk2f& trans) { |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 264 | this->set(p[0], p[1], p[2], trans); |
| 265 | } |
| 266 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 267 | inline void GrCCCoverageProcessor::TriPointInstance::set(const SkPoint& p0, const SkPoint& p1, |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 268 | const SkPoint& p2, const Sk2f& trans) { |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 269 | Sk2f P0 = Sk2f::Load(&p0) + trans; |
| 270 | Sk2f P1 = Sk2f::Load(&p1) + trans; |
| 271 | Sk2f P2 = Sk2f::Load(&p2) + trans; |
| 272 | Sk2f::Store3(this, P0, P1, P2); |
| 273 | } |
| 274 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 275 | inline void GrCCCoverageProcessor::QuadPointInstance::set(const SkPoint p[4], float dx, float dy) { |
Chris Dalton | a3e9271 | 2017-12-04 11:45:51 -0700 | [diff] [blame] | 276 | Sk4f X,Y; |
| 277 | Sk4f::Load2(p, &X, &Y); |
| 278 | (X + dx).store(&fX); |
| 279 | (Y + dy).store(&fY); |
| 280 | } |
| 281 | |
Chris Dalton | 84403d7 | 2018-02-13 21:46:17 -0500 | [diff] [blame] | 282 | inline void GrCCCoverageProcessor::QuadPointInstance::set(const SkPoint& p0, const SkPoint& p1, |
| 283 | const SkPoint& p2, const Sk2f& trans, |
| 284 | float w) { |
| 285 | Sk2f P0 = Sk2f::Load(&p0) + trans; |
| 286 | Sk2f P1 = Sk2f::Load(&p1) + trans; |
| 287 | Sk2f P2 = Sk2f::Load(&p2) + trans; |
| 288 | Sk2f W = Sk2f(w); |
| 289 | Sk2f::Store4(this, P0, P1, P2, W); |
| 290 | } |
| 291 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 292 | inline bool GrCCCoverageProcessor::RenderPassIsCubic(RenderPass pass) { |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 293 | switch (pass) { |
| 294 | case RenderPass::kTriangleHulls: |
| 295 | case RenderPass::kTriangleEdges: |
| 296 | case RenderPass::kTriangleCorners: |
| 297 | case RenderPass::kQuadraticHulls: |
| 298 | case RenderPass::kQuadraticCorners: |
| 299 | return false; |
| 300 | case RenderPass::kCubicHulls: |
| 301 | case RenderPass::kCubicCorners: |
| 302 | return true; |
| 303 | } |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 304 | SK_ABORT("Invalid RenderPass"); |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 305 | return false; |
| 306 | } |
| 307 | |
Chris Dalton | 383a2ef | 2018-01-08 17:21:41 -0500 | [diff] [blame] | 308 | inline const char* GrCCCoverageProcessor::RenderPassName(RenderPass pass) { |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 309 | switch (pass) { |
| 310 | case RenderPass::kTriangleHulls: return "kTriangleHulls"; |
| 311 | case RenderPass::kTriangleEdges: return "kTriangleEdges"; |
| 312 | case RenderPass::kTriangleCorners: return "kTriangleCorners"; |
| 313 | case RenderPass::kQuadraticHulls: return "kQuadraticHulls"; |
| 314 | case RenderPass::kQuadraticCorners: return "kQuadraticCorners"; |
| 315 | case RenderPass::kCubicHulls: return "kCubicHulls"; |
| 316 | case RenderPass::kCubicCorners: return "kCubicCorners"; |
| 317 | } |
Chris Dalton | 1fbdb61 | 2017-12-12 12:48:47 -0700 | [diff] [blame] | 318 | SK_ABORT("Invalid RenderPass"); |
Chris Dalton | 2326177 | 2017-12-10 16:41:45 -0700 | [diff] [blame] | 319 | return ""; |
| 320 | } |
| 321 | |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 322 | #endif |