• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,
78         kQuadraticFlatEdges,
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 
instanceAttrib()90     const char* instanceAttrib() const { return fInstanceAttrib.fName; }
name()91     const char* name() const override { return GetProcessorName(fMode); }
dumpInfo()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).
enableDebugVisualizations()104     void enableDebugVisualizations() { fDebugVisualizations = true; }
debugVisualizations()105     bool debugVisualizations() const { return fDebugVisualizations; }
106 
107     static void Validate(GrRenderTarget* atlasTexture);
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 
PrimitiveProcessor(CoverageType coverageType)139     PrimitiveProcessor(CoverageType coverageType)
140             : fCoverageType(coverageType)
141             , fGeomWind("wind", kFloat_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
142             , fFragWind(kFloat_GrSLType)
143             , fFragCoverageTimesWind(kFloat_GrSLType) {}
144 
145     // Called before generating shader code. Subclass should add its custom varyings to the handler
146     // and update its corresponding internal member variables.
resetVaryings(GrGLSLVaryingHandler *)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.
emitPerVertexGeometryCode(SkString * fnBody,const char * position,const char * coverage,const char * wind)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.
emitShaderCoverage(GrGLSLFragmentBuilder *,const char * outputCoverage)184     virtual void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const {
185         SkFAIL("Shader coverage not implemented when using CoverageType::kShader.");
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 
218     // Defines an equation ("dot(vec3(pt, 1), distance_equation)") that is -1 on the outside border
219     // of a conservative raster edge and 0 on the inside (see emitEdgeGeometry).
220     void emitEdgeDistanceEquation(GrGLSLGeometryBuilder*, const char* leftPt, const char* rightPt,
221                                   const char* outputDistanceEquation) const;
222 
223     // Defines a global vec2 array that contains MSAA sample locations as offsets from pixel center.
224     // Subclasses can use this for software multisampling.
225     //
226     // Returns the number of samples.
227     int defineSoftSampleLocations(GrGLSLFragmentBuilder*, const char* samplesName) const;
228 
229 private:
setData(const GrGLSLProgramDataManager & pdman,const GrPrimitiveProcessor &,FPCoordTransformIter && transformIter)230     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
231                  FPCoordTransformIter&& transformIter) final {
232         this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
233     }
234 
235     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final;
236 
237     void emitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
238                           const TexelBufferHandle& pointsBuffer, const char* rtAdjust,
239                           GrGPArgs* gpArgs) const;
240     void emitGeometryShader(const GrCCPRCoverageProcessor&, GrGLSLGeometryBuilder*,
241                             const char* rtAdjust) const;
242     void emitCoverage(const GrCCPRCoverageProcessor&, GrGLSLFragmentBuilder*,
243                       const char* outputColor, const char* outputCoverage) const;
244 
245     const CoverageType   fCoverageType;
246     GrShaderVar          fGeomWind;
247     GrGLSLGeoToFrag      fFragWind;
248     GrGLSLGeoToFrag      fFragCoverageTimesWind;
249 
250     typedef GrGLSLGeometryProcessor INHERITED;
251 };
252 
253 #endif
254