blob: 17aaba59f03a194e232420c3b92444ac553abfdd [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:
Chris Dalton1a325d22017-07-14 15:17:41 -060037 static constexpr GrPrimitiveType kTrianglesGrPrimitiveType = GrPrimitiveType::kTriangles;
38 static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles;
39 static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency;
40
Chris Daltonc1e59632017-09-05 00:30:07 -060041 struct TriangleInstance {
42 int32_t fPt0Idx;
43 int32_t fPt1Idx;
44 int32_t fPt2Idx;
Chris Dalton1a325d22017-07-14 15:17:41 -060045 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
46 };
47
Chris Daltonc1e59632017-09-05 00:30:07 -060048 GR_STATIC_ASSERT(4 * 4 == sizeof(TriangleInstance));
49
50 struct CurveInstance {
51 int32_t fPtsIdx;
52 int32_t fPackedAtlasOffset; // (offsetY << 16) | (offsetX & 0xffff)
53 };
54
55 GR_STATIC_ASSERT(2 * 4 == sizeof(CurveInstance));
Chris Dalton1a325d22017-07-14 15:17:41 -060056
Chris Dalton6a3dbee2017-10-16 10:44:41 -060057 /**
58 * All primitive shapes (triangles and convex closed curve segments) require more than one
59 * render pass. Here we enumerate every render pass needed in order to produce a complete
60 * coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
61 */
62 enum class RenderPass {
Chris Dalton1a325d22017-07-14 15:17:41 -060063 // Triangles.
64 kTriangleHulls,
65 kTriangleEdges,
Chris Dalton1a325d22017-07-14 15:17:41 -060066 kTriangleCorners,
67
68 // Quadratics.
69 kQuadraticHulls,
Chris Daltonb072bb62017-08-07 09:00:46 -060070 kQuadraticCorners,
Chris Dalton1a325d22017-07-14 15:17:41 -060071
72 // Cubics.
Chris Dalton7f578bf2017-09-05 16:46:48 -060073 kSerpentineHulls,
74 kLoopHulls,
75 kSerpentineCorners,
76 kLoopCorners
Chris Dalton1a325d22017-07-14 15:17:41 -060077 };
Chris Dalton1a325d22017-07-14 15:17:41 -060078
Chris Dalton6a3dbee2017-10-16 10:44:41 -060079 static const char* GetRenderPassName(RenderPass);
80
81 /**
82 * This serves as the base class for each RenderPass's Shader. It indicates what type of
83 * geometry the Impl should generate and provides implementation-independent code to process
84 * the inputs and calculate coverage in the fragment Shader.
85 */
86 class Shader {
87 public:
88 using TexelBufferHandle = GrGLSLGeometryProcessor::TexelBufferHandle;
89
90 // This enum specifies the type of geometry that should be generated for a Shader instance.
91 // Subclasses are limited to three built-in types of geometry to choose from:
92 enum class GeometryType {
93 // Generates a conservative raster hull around the input points. This is the geometry
94 // that causes a pixel to be rasterized if it is touched anywhere by the input polygon.
95 // Coverage is +1 all around.
96 //
97 // Logically, the conservative raster hull is equivalent to the convex hull of pixel
98 // size boxes centered around each input point.
99 kHull,
100
101 // Generates the conservative rasters of the input edges (i.e. convex hull of two
102 // pixel-size boxes centered on both endpoints). Coverage is -1 on the outside border of
103 // the edge geometry and 0 on the inside. This is the only geometry type that associates
104 // coverage values with the output points. It effectively converts a jagged conservative
105 // raster edge into a smooth antialiased edge.
106 kEdges,
107
108 // Generates the conservative rasters of the corners specified by the geometry provider
109 // (i.e. pixel-size box centered on the corner point). Coverage is +1 all around.
110 kCorners
111 };
112
113 virtual GeometryType getGeometryType() const = 0;
114 virtual int getNumInputPoints() const = 0;
115
116 // Returns the number of independent geometric segments to generate for the render pass
117 // (number of wedges for a hull, number of edges, or number of corners.)
118 virtual int getNumSegments() const = 0;
119
120 // Appends an expression that fetches input point # "pointId" from the texel buffer.
121 virtual void appendInputPointFetch(const GrCCPRCoverageProcessor&, GrGLSLShaderBuilder*,
122 const TexelBufferHandle& pointsBuffer,
123 const char* pointId) const = 0;
124
125 // Determines the winding direction of the primitive. The subclass must write a value of
126 // either -1, 0, or +1 to "outputWind" (e.g. "sign(area)"). Fractional values are not valid.
Chris Daltonc17bf322017-10-24 10:59:03 -0600127 virtual void emitWind(GrGLSLShaderBuilder*, const char* pts,
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600128 const char* outputWind) const = 0;
129
130 union GeometryVars {
131 struct {
132 const char* fAlternatePoints; // floatNx2 (if left null, will use input points).
133 const char* fAlternateMidpoint; // float2 (if left null, finds euclidean midpoint).
134 } fHullVars;
135
136 struct {
137 const char* fPoint; // float2
138 } fCornerVars;
139
140 GeometryVars() { memset(this, 0, sizeof(*this)); }
141 };
142
143 // Called before generating geometry. Subclasses must fill out the applicable fields in
144 // GeometryVars (if any), and may also use this opportunity to setup internal member
145 // variables that will be needed during onEmitVaryings (e.g. transformation matrices).
146 virtual void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
Chris Daltonc17bf322017-10-24 10:59:03 -0600147 const char* wind, GeometryVars*) const {}
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600148
149 void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
150 const char* coverage, const char* wind);
151
152 void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
153 const char* skOutputColor, const char* skOutputCoverage) const;
154
155 // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
156 // border of a conservative raster edge and 0 on the inside (see emitEdgeGeometry).
157 static void EmitEdgeDistanceEquation(GrGLSLShaderBuilder*, const char* leftPt,
158 const char* rightPt,
159 const char* outputDistanceEquation);
160
161 // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
162 // center. Subclasses can use this for software multisampling.
163 //
164 // Returns the number of samples.
165 static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
166
167 virtual ~Shader() {}
168
169 protected:
170 enum class WindHandling : bool {
171 kHandled,
172 kNotHandled
173 };
174
175 // Here the subclass adds its internal varyings to the handler and produces code to
176 // initialize those varyings from a given position, coverage value, and wind.
177 //
178 // Returns whether the subclass will handle wind modulation or if this base class should
179 // take charge of multiplying the final coverage output by "wind".
180 //
181 // NOTE: the coverage parameter is only relevant for edges (see comments in GeometryType).
182 // Otherwise it is +1 all around.
183 virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code,
184 const char* position, const char* coverage,
185 const char* wind) = 0;
186
187 // Emits the fragment code that calculates a pixel's coverage value. If using
188 // WindHandling::kHandled, this value must be signed appropriately.
189 virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
190 const char* outputCoverage) const = 0;
191
192 private:
193 GrGLSLGeoToFrag fWind{kHalf_GrSLType};
194 };
195
196 GrCCPRCoverageProcessor(RenderPass, GrBuffer* pointsBuffer);
Chris Dalton1a325d22017-07-14 15:17:41 -0600197
198 const char* instanceAttrib() const { return fInstanceAttrib.fName; }
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600199 const char* name() const override { return GetRenderPassName(fRenderPass); }
Chris Dalton1a325d22017-07-14 15:17:41 -0600200 SkString dumpInfo() const override {
201 return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
202 }
Chris Dalton1a325d22017-07-14 15:17:41 -0600203 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
204 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
205
Chris Dalton7f578bf2017-09-05 16:46:48 -0600206#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -0700207 // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
Chris Dalton1a325d22017-07-14 15:17:41 -0600208 // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
Chris Daltona640c492017-09-11 22:04:03 -0700209 void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
210 bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
211 float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
Chris Dalton1a325d22017-07-14 15:17:41 -0600212#endif
213
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600214 class GSImpl;
Chris Dalton1a325d22017-07-14 15:17:41 -0600215
216private:
Chris Dalton1a325d22017-07-14 15:17:41 -0600217 // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
218 // accidentally bleed into neighbor pixels.
219 static constexpr float kAABloatRadius = 0.491111f;
220
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600221 static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr<Shader>);
Chris Dalton1a325d22017-07-14 15:17:41 -0600222
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600223 int atlasOffsetIdx() const {
224 SkASSERT(kInt2_GrVertexAttribType == fInstanceAttrib.fType ||
225 kInt4_GrVertexAttribType == fInstanceAttrib.fType);
226 return kInt4_GrVertexAttribType == fInstanceAttrib.fType ? 3 : 1;
Chris Dalton1a325d22017-07-14 15:17:41 -0600227 }
228
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600229 const RenderPass fRenderPass;
230 const Attribute& fInstanceAttrib;
231 BufferAccess fPointsBufferAccess;
232 SkDEBUGCODE(float fDebugBloat = 0;)
Chris Dalton1a325d22017-07-14 15:17:41 -0600233
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600234 typedef GrGeometryProcessor INHERITED;
Chris Dalton1a325d22017-07-14 15:17:41 -0600235};
236
237#endif