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