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 | |
| 8 | #ifndef GrCCPRCoverageProcessor_DEFINED |
| 9 | #define GrCCPRCoverageProcessor_DEFINED |
| 10 | |
| 11 | #include "GrGeometryProcessor.h" |
| 12 | #include "glsl/GrGLSLGeometryProcessor.h" |
| 13 | #include "glsl/GrGLSLVarying.h" |
| 14 | |
| 15 | class GrGLSLFragmentBuilder; |
| 16 | |
| 17 | /** |
| 18 | * This is the geometry processor for the simple convex primitive shapes (triangles and closed curve |
| 19 | * segments) from which ccpr paths are composed. The output is a single-channel alpha value, |
| 20 | * positive for clockwise primitives and negative for counter-clockwise, that indicates coverage. |
| 21 | * |
| 22 | * The caller is responsible to render all modes for all applicable primitives into a cleared, |
| 23 | * floating point, alpha-only render target using SkBlendMode::kPlus. Once all of a path's |
| 24 | * primitives have been drawn, the render target contains a composite coverage count that can then |
| 25 | * be used to draw the path (see GrCCPRPathProcessor). |
| 26 | * |
| 27 | * Caller provides the primitives' (x,y) points in an fp32x2 (RG) texel buffer, and an instance |
| 28 | * buffer with a single int32x4 attrib for each primitive (defined below). There are no vertex |
| 29 | * attribs. |
| 30 | * |
| 31 | * Draw calls are instanced, with one vertex per bezier point (3 for triangles). They use the |
| 32 | * corresponding GrPrimitiveType as defined below. |
| 33 | */ |
| 34 | class GrCCPRCoverageProcessor : public GrGeometryProcessor { |
| 35 | public: |
| 36 | // Use top-left to avoid a uniform access in the fragment shader. |
| 37 | static constexpr GrSurfaceOrigin kAtlasOrigin = kTopLeft_GrSurfaceOrigin; |
| 38 | |
| 39 | static constexpr GrPrimitiveType kTrianglesGrPrimitiveType = GrPrimitiveType::kTriangles; |
| 40 | static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles; |
| 41 | static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency; |
| 42 | |
| 43 | struct PrimitiveInstance { |
| 44 | union { |
| 45 | struct { |
| 46 | int32_t fPt0Idx; |
| 47 | int32_t fPt1Idx; |
| 48 | int32_t fPt2Idx; |
| 49 | } fTriangleData; |
| 50 | |
| 51 | struct { |
| 52 | int32_t fControlPtIdx; |
| 53 | int32_t fEndPtsIdx; // The endpoints (P0 and P2) are adjacent in the texel buffer. |
| 54 | } fQuadraticData; |
| 55 | |
| 56 | struct { |
| 57 | int32_t fControlPtsKLMRootsIdx; // The control points (P1 and P2) are adjacent in |
| 58 | // the texel buffer, followed immediately by the |
| 59 | // homogenous KLM roots ({tl,sl}, {tm,sm}). |
| 60 | int32_t fEndPtsIdx; // The endpoints (P0 and P3) are adjacent in the texel buffer. |
| 61 | } fCubicData; |
| 62 | }; |
| 63 | |
| 64 | int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff) |
| 65 | }; |
| 66 | |
| 67 | GR_STATIC_ASSERT(4 * 4 == sizeof(PrimitiveInstance)); |
| 68 | |
| 69 | enum class Mode { |
| 70 | // Triangles. |
| 71 | kTriangleHulls, |
| 72 | kTriangleEdges, |
| 73 | kCombinedTriangleHullsAndEdges, |
| 74 | kTriangleCorners, |
| 75 | |
| 76 | // Quadratics. |
| 77 | kQuadraticHulls, |
Chris Dalton | b072bb6 | 2017-08-07 09:00:46 -0600 | [diff] [blame] | 78 | kQuadraticCorners, |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 79 | |
| 80 | // Cubics. |
| 81 | kSerpentineInsets, |
| 82 | kSerpentineBorders, |
| 83 | kLoopInsets, |
| 84 | kLoopBorders |
| 85 | }; |
| 86 | static const char* GetProcessorName(Mode); |
| 87 | |
| 88 | GrCCPRCoverageProcessor(Mode, GrBuffer* pointsBuffer); |
| 89 | |
| 90 | const char* instanceAttrib() const { return fInstanceAttrib.fName; } |
| 91 | const char* name() const override { return GetProcessorName(fMode); } |
| 92 | SkString dumpInfo() const override { |
| 93 | return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str()); |
| 94 | } |
| 95 | |
| 96 | void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; |
| 97 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; |
| 98 | |
| 99 | #ifdef SK_DEBUG |
| 100 | static constexpr float kDebugBloat = 50; |
| 101 | |
| 102 | // Increases the 1/2 pixel AA bloat by a factor of kDebugBloat and outputs color instead of |
| 103 | // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red). |
| 104 | void enableDebugVisualizations() { fDebugVisualizations = true; } |
| 105 | bool debugVisualizations() const { return fDebugVisualizations; } |
| 106 | |
Robert Phillips | 2890fbf | 2017-07-26 15:48:41 -0400 | [diff] [blame] | 107 | static void Validate(GrRenderTargetProxy* atlasProxy); |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 108 | #endif |
| 109 | |
| 110 | class PrimitiveProcessor; |
| 111 | |
| 112 | private: |
| 113 | const Mode fMode; |
| 114 | const Attribute& fInstanceAttrib; |
| 115 | BufferAccess fPointsBufferAccess; |
| 116 | SkDEBUGCODE(bool fDebugVisualizations = false;) |
| 117 | |
| 118 | typedef GrGeometryProcessor INHERITED; |
| 119 | }; |
| 120 | |
| 121 | /** |
| 122 | * This class represents the actual SKSL implementation for the various primitives and modes of |
| 123 | * GrCCPRCoverageProcessor. |
| 124 | */ |
| 125 | class GrCCPRCoverageProcessor::PrimitiveProcessor : public GrGLSLGeometryProcessor { |
| 126 | protected: |
| 127 | // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't |
| 128 | // accidentally bleed into neighbor pixels. |
| 129 | static constexpr float kAABloatRadius = 0.491111f; |
| 130 | |
| 131 | // Specifies how the fragment shader should calculate sk_FragColor.a. |
| 132 | enum class CoverageType { |
| 133 | kOne, // Output +1 all around, modulated by wind. |
| 134 | kInterpolated, // Interpolate the coverage values that the geometry shader associates with |
| 135 | // each point, modulated by wind. |
| 136 | kShader // Call emitShaderCoverage and let the subclass decide, then a modulate by wind. |
| 137 | }; |
| 138 | |
| 139 | PrimitiveProcessor(CoverageType coverageType) |
| 140 | : fCoverageType(coverageType) |
Ethan Nicholas | 88d99c6 | 2017-08-16 16:41:30 -0400 | [diff] [blame] | 141 | , fGeomWind("wind", kHalf_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision) |
| 142 | , fFragWind(kHalf_GrSLType) |
| 143 | , fFragCoverageTimesWind(kHalf_GrSLType) {} |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 144 | |
| 145 | // Called before generating shader code. Subclass should add its custom varyings to the handler |
| 146 | // and update its corresponding internal member variables. |
| 147 | virtual void resetVaryings(GrGLSLVaryingHandler*) {} |
| 148 | |
| 149 | // Here the subclass fetches its vertex from the texel buffer, translates by atlasOffset, and |
| 150 | // sets "fPositionVar" in the GrGPArgs. |
| 151 | virtual void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*, |
| 152 | const TexelBufferHandle& pointsBuffer, const char* atlasOffset, |
| 153 | const char* rtAdjust, GrGPArgs*) const = 0; |
| 154 | |
| 155 | // Here the subclass determines the winding direction of its primitive. It must write a value of |
| 156 | // either -1, 0, or +1 to "outputWind" (e.g. "sign(area)"). Fractional values are not valid. |
| 157 | virtual void emitWind(GrGLSLGeometryBuilder*, const char* rtAdjust, |
| 158 | const char* outputWind) const = 0; |
| 159 | |
| 160 | // This is where the subclass generates the actual geometry to be rasterized by hardware: |
| 161 | // |
| 162 | // emitVertexFn(point1, coverage); |
| 163 | // emitVertexFn(point2, coverage); |
| 164 | // ... |
| 165 | // EndPrimitive(); |
| 166 | // |
| 167 | // Generally a subclass will want to use emitHullGeometry and/or emitEdgeGeometry rather than |
| 168 | // calling emitVertexFn directly. |
| 169 | // |
| 170 | // Subclass must also call GrGLSLGeometryBuilder::configure. |
| 171 | virtual void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, |
| 172 | const char* wind, const char* rtAdjust) const = 0; |
| 173 | |
| 174 | // This is a hook to inject code in the geometry shader's "emitVertex" function. Subclass |
| 175 | // should use this to write values to its custom varyings. |
| 176 | // NOTE: even flat varyings should be rewritten at each vertex. |
| 177 | virtual void emitPerVertexGeometryCode(SkString* fnBody, const char* position, |
| 178 | const char* coverage, const char* wind) const {} |
| 179 | |
| 180 | // Called when the subclass has selected CoverageType::kShader. Primitives should produce |
| 181 | // coverage values between +0..1. Base class modulates the sign for wind. |
| 182 | // TODO: subclasses might have good spots to stuff the winding information without burning a |
| 183 | // whole new varying slot. Consider requiring them to generate the correct coverage sign. |
| 184 | virtual void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const { |
Ben Wagner | b4aab9a | 2017-08-16 10:53:04 -0400 | [diff] [blame] | 185 | SK_ABORT("Shader coverage not implemented when using CoverageType::kShader."); |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | // Emits one wedge of the conservative raster hull of a convex polygon. The complete hull has |
| 189 | // one wedge for each side of the polygon (i.e. call this N times, generally from different |
| 190 | // geometry shader invocations). Coverage is +1 all around. |
| 191 | // |
| 192 | // Logically, the conservative raster hull is equivalent to the convex hull of pixel-size boxes |
| 193 | // centered on the vertices. |
| 194 | // |
| 195 | // If an optional inset polygon is provided, then this emits a border from the inset to the |
| 196 | // hull, rather than the entire hull. |
| 197 | // |
| 198 | // Geometry shader must be configured to output triangle strips. |
| 199 | // |
| 200 | // Returns the maximum number of vertices that will be emitted. |
| 201 | int emitHullGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* polygonPts, |
| 202 | int numSides, const char* wedgeIdx, const char* insetPts = nullptr) const; |
| 203 | |
| 204 | // Emits the conservative raster of an edge (i.e. convex hull of two pixel-size boxes centered |
| 205 | // on the endpoints). Coverage is -1 on the outside border of the edge geometry and 0 on the |
| 206 | // inside. This effectively converts a jagged conservative raster edge into a smooth antialiased |
| 207 | // edge when using CoverageType::kInterpolated. |
| 208 | // |
| 209 | // If the subclass has already called emitEdgeDistanceEquation, then provide the distance |
| 210 | // equation. Otherwise this function will call emitEdgeDistanceEquation implicitly. |
| 211 | // |
| 212 | // Geometry shader must be configured to output triangle strips. |
| 213 | // |
| 214 | // Returns the maximum number of vertices that will be emitted. |
| 215 | int emitEdgeGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* leftPt, |
| 216 | const char* rightPt, const char* distanceEquation = nullptr) const; |
| 217 | |
Ethan Nicholas | 5af9ea3 | 2017-07-28 15:19:46 -0400 | [diff] [blame] | 218 | // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside |
| 219 | // border of a conservative raster edge and 0 on the inside (see emitEdgeGeometry). |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 220 | void emitEdgeDistanceEquation(GrGLSLGeometryBuilder*, const char* leftPt, const char* rightPt, |
| 221 | const char* outputDistanceEquation) const; |
| 222 | |
Chris Dalton | b072bb6 | 2017-08-07 09:00:46 -0600 | [diff] [blame] | 223 | // Emits the conservative raster of a single point (i.e. pixel-size box centered on the point). |
| 224 | // Coverage is +1 all around. |
| 225 | // |
| 226 | // Geometry shader must be configured to output triangle strips. |
| 227 | // |
| 228 | // Returns the number of vertices that were emitted. |
| 229 | int emitCornerGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* pt) const; |
| 230 | |
Ethan Nicholas | 5af9ea3 | 2017-07-28 15:19:46 -0400 | [diff] [blame] | 231 | // Defines a global float2 array that contains MSAA sample locations as offsets from pixel |
| 232 | // center. Subclasses can use this for software multisampling. |
Chris Dalton | 1a325d2 | 2017-07-14 15:17:41 -0600 | [diff] [blame] | 233 | // |
| 234 | // Returns the number of samples. |
| 235 | int defineSoftSampleLocations(GrGLSLFragmentBuilder*, const char* samplesName) const; |
| 236 | |
| 237 | private: |
| 238 | void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&, |
| 239 | FPCoordTransformIter&& transformIter) final { |
| 240 | this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); |
| 241 | } |
| 242 | |
| 243 | void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final; |
| 244 | |
| 245 | void emitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*, |
| 246 | const TexelBufferHandle& pointsBuffer, const char* rtAdjust, |
| 247 | GrGPArgs* gpArgs) const; |
| 248 | void emitGeometryShader(const GrCCPRCoverageProcessor&, GrGLSLGeometryBuilder*, |
| 249 | const char* rtAdjust) const; |
| 250 | void emitCoverage(const GrCCPRCoverageProcessor&, GrGLSLFragmentBuilder*, |
| 251 | const char* outputColor, const char* outputCoverage) const; |
| 252 | |
| 253 | const CoverageType fCoverageType; |
| 254 | GrShaderVar fGeomWind; |
| 255 | GrGLSLGeoToFrag fFragWind; |
| 256 | GrGLSLGeoToFrag fFragCoverageTimesWind; |
| 257 | |
| 258 | typedef GrGLSLGeometryProcessor INHERITED; |
| 259 | }; |
| 260 | |
| 261 | #endif |