blob: f2c5f435e0f0065d8c533b53d7de88ba94281105 [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
Chris Dalton6a3dbee2017-10-16 10:44:41 -060015class GrGLSLPPFragmentBuilder;
16class GrGLSLShaderBuilder;
Chris Dalton1a325d22017-07-14 15:17:41 -060017
18/**
19 * This is the geometry processor for the simple convex primitive shapes (triangles and closed curve
20 * segments) from which ccpr paths are composed. The output is a single-channel alpha value,
Chris Dalton6a3dbee2017-10-16 10:44:41 -060021 * positive for clockwise shapes and negative for counter-clockwise, that indicates coverage.
Chris Dalton1a325d22017-07-14 15:17:41 -060022 *
Chris Dalton6a3dbee2017-10-16 10:44:41 -060023 * The caller is responsible to execute all render passes for all applicable primitives into a
24 * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass
25 * below). Once all of a path's primitives have been drawn, the render target contains a composite
26 * coverage count that can then be used to draw the path (see GrCCPRPathProcessor).
Chris Dalton1a325d22017-07-14 15:17:41 -060027 *
Chris Dalton6a3dbee2017-10-16 10:44:41 -060028 * Caller provides the primitives' (x,y) input points in an fp32x2 (RG) texel buffer, and an
29 * instance buffer with a single int32x4 attrib (for triangles) or int32x2 (for curves) defined
30 * below. There are no vertex attribs.
Chris Dalton1a325d22017-07-14 15:17:41 -060031 *
32 * Draw calls are instanced, with one vertex per bezier point (3 for triangles). They use the
33 * corresponding GrPrimitiveType as defined below.
34 */
35class GrCCPRCoverageProcessor : public GrGeometryProcessor {
36public:
37 // Use top-left to avoid a uniform access in the fragment shader.
38 static constexpr GrSurfaceOrigin kAtlasOrigin = kTopLeft_GrSurfaceOrigin;
39
40 static constexpr GrPrimitiveType kTrianglesGrPrimitiveType = GrPrimitiveType::kTriangles;
41 static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles;
42 static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency;
43
Chris Daltonc1e59632017-09-05 00:30:07 -060044 struct TriangleInstance {
45 int32_t fPt0Idx;
46 int32_t fPt1Idx;
47 int32_t fPt2Idx;
Chris Dalton1a325d22017-07-14 15:17:41 -060048 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
49 };
50
Chris Daltonc1e59632017-09-05 00:30:07 -060051 GR_STATIC_ASSERT(4 * 4 == sizeof(TriangleInstance));
52
53 struct CurveInstance {
54 int32_t fPtsIdx;
55 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
56 };
57
58 GR_STATIC_ASSERT(2 * 4 == sizeof(CurveInstance));
Chris Dalton1a325d22017-07-14 15:17:41 -060059
Chris Dalton6a3dbee2017-10-16 10:44:41 -060060 /**
61 * All primitive shapes (triangles and convex closed curve segments) require more than one
62 * render pass. Here we enumerate every render pass needed in order to produce a complete
63 * coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
64 */
65 enum class RenderPass {
Chris Dalton1a325d22017-07-14 15:17:41 -060066 // Triangles.
67 kTriangleHulls,
68 kTriangleEdges,
Chris Dalton1a325d22017-07-14 15:17:41 -060069 kTriangleCorners,
70
71 // Quadratics.
72 kQuadraticHulls,
Chris Daltonb072bb62017-08-07 09:00:46 -060073 kQuadraticCorners,
Chris Dalton1a325d22017-07-14 15:17:41 -060074
75 // Cubics.
Chris Dalton7f578bf2017-09-05 16:46:48 -060076 kSerpentineHulls,
77 kLoopHulls,
78 kSerpentineCorners,
79 kLoopCorners
Chris Dalton1a325d22017-07-14 15:17:41 -060080 };
Chris Dalton1a325d22017-07-14 15:17:41 -060081
Chris Dalton6a3dbee2017-10-16 10:44:41 -060082 static const char* GetRenderPassName(RenderPass);
83
84 /**
85 * This serves as the base class for each RenderPass's Shader. It indicates what type of
86 * geometry the Impl should generate and provides implementation-independent code to process
87 * the inputs and calculate coverage in the fragment Shader.
88 */
89 class Shader {
90 public:
91 using TexelBufferHandle = GrGLSLGeometryProcessor::TexelBufferHandle;
92
93 // This enum specifies the type of geometry that should be generated for a Shader instance.
94 // Subclasses are limited to three built-in types of geometry to choose from:
95 enum class GeometryType {
96 // Generates a conservative raster hull around the input points. This is the geometry
97 // that causes a pixel to be rasterized if it is touched anywhere by the input polygon.
98 // Coverage is +1 all around.
99 //
100 // Logically, the conservative raster hull is equivalent to the convex hull of pixel
101 // size boxes centered around each input point.
102 kHull,
103
104 // Generates the conservative rasters of the input edges (i.e. convex hull of two
105 // pixel-size boxes centered on both endpoints). Coverage is -1 on the outside border of
106 // the edge geometry and 0 on the inside. This is the only geometry type that associates
107 // coverage values with the output points. It effectively converts a jagged conservative
108 // raster edge into a smooth antialiased edge.
109 kEdges,
110
111 // Generates the conservative rasters of the corners specified by the geometry provider
112 // (i.e. pixel-size box centered on the corner point). Coverage is +1 all around.
113 kCorners
114 };
115
116 virtual GeometryType getGeometryType() const = 0;
117 virtual int getNumInputPoints() const = 0;
118
119 // Returns the number of independent geometric segments to generate for the render pass
120 // (number of wedges for a hull, number of edges, or number of corners.)
121 virtual int getNumSegments() const = 0;
122
123 // Appends an expression that fetches input point # "pointId" from the texel buffer.
124 virtual void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
125 const TexelBufferHandle& pointsBuffer,
126 const char* pointId) const = 0;
127
128 // Determines the winding direction of the primitive. The subclass must write a value of
129 // either -1, 0, or +1 to "outputWind" (e.g. "sign(area)"). Fractional values are not valid.
130 virtual void emitWind(GrGLSLShaderBuilder*, const char* pts, const char* rtAdjust,
131 const char* outputWind) const = 0;
132
133 union GeometryVars {
134 struct {
135 const char* fAlternatePoints; // floatNx2 (if left null, will use input points).
136 const char* fAlternateMidpoint; // float2 (if left null, finds euclidean midpoint).
137 } fHullVars;
138
139 struct {
140 const char* fPoint; // float2
141 } fCornerVars;
142
143 GeometryVars() { memset(this, 0, sizeof(*this)); }
144 };
145
146 // Called before generating geometry. Subclasses must fill out the applicable fields in
147 // GeometryVars (if any), and may also use this opportunity to setup internal member
148 // variables that will be needed during onEmitVaryings (e.g. transformation matrices).
149 virtual void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
150 const char* bloat, const char* wind, const char* rtAdjust,
151 GeometryVars*) const {}
152
153 void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
154 const char* coverage, const char* wind);
155
156 void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
157 const char* skOutputColor, const char* skOutputCoverage) const;
158
159 // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
160 // border of a conservative raster edge and 0 on the inside (see emitEdgeGeometry).
161 static void EmitEdgeDistanceEquation(GrGLSLShaderBuilder*, const char* leftPt,
162 const char* rightPt,
163 const char* outputDistanceEquation);
164
165 // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
166 // center. Subclasses can use this for software multisampling.
167 //
168 // Returns the number of samples.
169 static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
170
171 virtual ~Shader() {}
172
173 protected:
174 enum class WindHandling : bool {
175 kHandled,
176 kNotHandled
177 };
178
179 // Here the subclass adds its internal varyings to the handler and produces code to
180 // initialize those varyings from a given position, coverage value, and wind.
181 //
182 // Returns whether the subclass will handle wind modulation or if this base class should
183 // take charge of multiplying the final coverage output by "wind".
184 //
185 // NOTE: the coverage parameter is only relevant for edges (see comments in GeometryType).
186 // Otherwise it is +1 all around.
187 virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code,
188 const char* position, const char* coverage,
189 const char* wind) = 0;
190
191 // Emits the fragment code that calculates a pixel's coverage value. If using
192 // WindHandling::kHandled, this value must be signed appropriately.
193 virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
194 const char* outputCoverage) const = 0;
195
196 private:
197 GrGLSLGeoToFrag fWind{kHalf_GrSLType};
198 };
199
200 GrCCPRCoverageProcessor(RenderPass, GrBuffer* pointsBuffer);
Chris Dalton1a325d22017-07-14 15:17:41 -0600201
202 const char* instanceAttrib() const { return fInstanceAttrib.fName; }
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600203 const char* name() const override { return GetRenderPassName(fRenderPass); }
Chris Dalton1a325d22017-07-14 15:17:41 -0600204 SkString dumpInfo() const override {
205 return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
206 }
Chris Dalton1a325d22017-07-14 15:17:41 -0600207 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
208 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
209
Chris Dalton7f578bf2017-09-05 16:46:48 -0600210#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -0700211 // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
Chris Dalton1a325d22017-07-14 15:17:41 -0600212 // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
Chris Daltona640c492017-09-11 22:04:03 -0700213 void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
214 bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
215 float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
Chris Dalton1a325d22017-07-14 15:17:41 -0600216
Robert Phillips2890fbf2017-07-26 15:48:41 -0400217 static void Validate(GrRenderTargetProxy* atlasProxy);
Chris Dalton1a325d22017-07-14 15:17:41 -0600218#endif
219
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600220 class GSImpl;
Chris Dalton1a325d22017-07-14 15:17:41 -0600221
222private:
Chris Dalton1a325d22017-07-14 15:17:41 -0600223 // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
224 // accidentally bleed into neighbor pixels.
225 static constexpr float kAABloatRadius = 0.491111f;
226
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600227 static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr<Shader>);
Chris Dalton1a325d22017-07-14 15:17:41 -0600228
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600229 int atlasOffsetIdx() const {
230 SkASSERT(kInt2_GrVertexAttribType == fInstanceAttrib.fType ||
231 kInt4_GrVertexAttribType == fInstanceAttrib.fType);
232 return kInt4_GrVertexAttribType == fInstanceAttrib.fType ? 3 : 1;
Chris Dalton1a325d22017-07-14 15:17:41 -0600233 }
234
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600235 const RenderPass fRenderPass;
236 const Attribute& fInstanceAttrib;
237 BufferAccess fPointsBufferAccess;
238 SkDEBUGCODE(float fDebugBloat = 0;)
Chris Dalton1a325d22017-07-14 15:17:41 -0600239
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600240 typedef GrGeometryProcessor INHERITED;
Chris Dalton1a325d22017-07-14 15:17:41 -0600241};
242
243#endif