blob: f02b7422c80747f2cb19406a28e08756de93336e [file] [log] [blame]
Chris Dalton1a325d22017-07-14 15:17:41 -06001/*
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
15class 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 Daltonc1e59632017-09-05 00:30:07 -060028 * buffer with a single int32x4 attrib (for triangles) or int32x2 (for curves) defined below. There
29 * are no vertex attribs.
Chris Dalton1a325d22017-07-14 15:17:41 -060030 *
31 * Draw calls are instanced, with one vertex per bezier point (3 for triangles). They use the
32 * corresponding GrPrimitiveType as defined below.
33 */
34class GrCCPRCoverageProcessor : public GrGeometryProcessor {
35public:
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 Daltonc1e59632017-09-05 00:30:07 -060043 struct TriangleInstance {
44 int32_t fPt0Idx;
45 int32_t fPt1Idx;
46 int32_t fPt2Idx;
Chris Dalton1a325d22017-07-14 15:17:41 -060047 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
48 };
49
Chris Daltonc1e59632017-09-05 00:30:07 -060050 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 Dalton1a325d22017-07-14 15:17:41 -060058
59 enum class Mode {
60 // Triangles.
61 kTriangleHulls,
62 kTriangleEdges,
Chris Dalton1a325d22017-07-14 15:17:41 -060063 kTriangleCorners,
64
65 // Quadratics.
66 kQuadraticHulls,
Chris Daltonb072bb62017-08-07 09:00:46 -060067 kQuadraticCorners,
Chris Dalton1a325d22017-07-14 15:17:41 -060068
69 // Cubics.
Chris Dalton7f578bf2017-09-05 16:46:48 -060070 kSerpentineHulls,
71 kLoopHulls,
72 kSerpentineCorners,
73 kLoopCorners
Chris Dalton1a325d22017-07-14 15:17:41 -060074 };
Chris Daltonc1e59632017-09-05 00:30:07 -060075 static constexpr GrVertexAttribType InstanceArrayFormat(Mode mode) {
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040076 return mode < Mode::kQuadraticHulls ? kInt4_GrVertexAttribType : kInt2_GrVertexAttribType;
Chris Daltonc1e59632017-09-05 00:30:07 -060077 }
Chris Dalton1a325d22017-07-14 15:17:41 -060078 static const char* GetProcessorName(Mode);
79
80 GrCCPRCoverageProcessor(Mode, GrBuffer* pointsBuffer);
81
82 const char* instanceAttrib() const { return fInstanceAttrib.fName; }
Chris Daltonc1e59632017-09-05 00:30:07 -060083 int atlasOffsetIdx() const {
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040084 return kInt4_GrVertexAttribType == InstanceArrayFormat(fMode) ? 3 : 1;
Chris Daltonc1e59632017-09-05 00:30:07 -060085 }
Chris Dalton1a325d22017-07-14 15:17:41 -060086 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 Dalton7f578bf2017-09-05 16:46:48 -060094#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -070095 // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
Chris Dalton1a325d22017-07-14 15:17:41 -060096 // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
Chris Daltona640c492017-09-11 22:04:03 -070097 void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
98 bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
99 float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
Chris Dalton1a325d22017-07-14 15:17:41 -0600100
Robert Phillips2890fbf2017-07-26 15:48:41 -0400101 static void Validate(GrRenderTargetProxy* atlasProxy);
Chris Dalton1a325d22017-07-14 15:17:41 -0600102#endif
103
104 class PrimitiveProcessor;
105
106private:
Chris Daltona640c492017-09-11 22:04:03 -0700107 const Mode fMode;
108 const Attribute& fInstanceAttrib;
109 BufferAccess fPointsBufferAccess;
110 SkDEBUGCODE(float fDebugBloat = false;)
Chris Dalton1a325d22017-07-14 15:17:41 -0600111
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 */
119class GrCCPRCoverageProcessor::PrimitiveProcessor : public GrGLSLGeometryProcessor {
120protected:
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 Nicholasf7b88202017-09-18 14:10:39 -0400135 , fGeomWind("wind", kHalf_GrSLType, GrShaderVar::kNonArray, kLow_GrSLPrecision)
136 , fFragWind(kHalf_GrSLType)
137 , fFragCoverageTimesWind(kHalf_GrSLType) {}
Chris Dalton1a325d22017-07-14 15:17:41 -0600138
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 Wagnerb4aab9a2017-08-16 10:53:04 -0400179 SK_ABORT("Shader coverage not implemented when using CoverageType::kShader.");
Chris Dalton1a325d22017-07-14 15:17:41 -0600180 }
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 Dalton1a325d22017-07-14 15:17:41 -0600189 // 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 Dalton7f578bf2017-09-05 16:46:48 -0600193 int numSides, const char* wedgeIdx, const char* midpoint = nullptr) const;
Chris Dalton1a325d22017-07-14 15:17:41 -0600194
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 Nicholas5af9ea32017-07-28 15:19:46 -0400209 // 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 Dalton1a325d22017-07-14 15:17:41 -0600211 void emitEdgeDistanceEquation(GrGLSLGeometryBuilder*, const char* leftPt, const char* rightPt,
212 const char* outputDistanceEquation) const;
213
Chris Daltonb072bb62017-08-07 09:00:46 -0600214 // 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 Nicholas5af9ea32017-07-28 15:19:46 -0400222 // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
223 // center. Subclasses can use this for software multisampling.
Chris Dalton1a325d22017-07-14 15:17:41 -0600224 //
225 // Returns the number of samples.
226 int defineSoftSampleLocations(GrGLSLFragmentBuilder*, const char* samplesName) const;
227
228private:
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