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