blob: 75cc45b8ebc60e26995210f12cb7da5db82373ce [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"
Chris Daltona3e92712017-12-04 11:45:51 -070012#include "SkNx.h"
Chris Dalton1a325d22017-07-14 15:17:41 -060013#include "glsl/GrGLSLGeometryProcessor.h"
14#include "glsl/GrGLSLVarying.h"
15
Chris Dalton6a3dbee2017-10-16 10:44:41 -060016class GrGLSLPPFragmentBuilder;
17class GrGLSLShaderBuilder;
Chris Dalton1a325d22017-07-14 15:17:41 -060018
19/**
20 * This is the geometry processor for the simple convex primitive shapes (triangles and closed curve
21 * segments) from which ccpr paths are composed. The output is a single-channel alpha value,
Chris Dalton6a3dbee2017-10-16 10:44:41 -060022 * positive for clockwise shapes and negative for counter-clockwise, that indicates coverage.
Chris Dalton1a325d22017-07-14 15:17:41 -060023 *
Chris Dalton6a3dbee2017-10-16 10:44:41 -060024 * The caller is responsible to execute all render passes for all applicable primitives into a
25 * cleared, floating point, alpha-only render target using SkBlendMode::kPlus (see RenderPass
26 * below). Once all of a path's primitives have been drawn, the render target contains a composite
27 * coverage count that can then be used to draw the path (see GrCCPRPathProcessor).
Chris Dalton1a325d22017-07-14 15:17:41 -060028 *
Chris Daltona3e92712017-12-04 11:45:51 -070029 * Draw calls are instanced. They use use the corresponding GrPrimitiveTypes as defined below.
30 * Caller fills out the primitives' atlas-space vertices and control points in instance arrays
31 * using the provided structs below. There are no vertex attribs.
Chris Dalton1a325d22017-07-14 15:17:41 -060032 */
33class GrCCPRCoverageProcessor : public GrGeometryProcessor {
34public:
Chris Dalton1a325d22017-07-14 15:17:41 -060035 static constexpr GrPrimitiveType kTrianglesGrPrimitiveType = GrPrimitiveType::kTriangles;
36 static constexpr GrPrimitiveType kQuadraticsGrPrimitiveType = GrPrimitiveType::kTriangles;
37 static constexpr GrPrimitiveType kCubicsGrPrimitiveType = GrPrimitiveType::kLinesAdjacency;
38
Chris Daltona3e92712017-12-04 11:45:51 -070039 enum class InstanceAttribs : int {
40 kX,
41 kY
Chris Dalton1a325d22017-07-14 15:17:41 -060042 };
43
Chris Daltona3e92712017-12-04 11:45:51 -070044 struct TriangleInstance { // Also used by quadratics.
45 float fX[3];
46 float fY[3];
Chris Daltonc1e59632017-09-05 00:30:07 -060047
Chris Daltona3e92712017-12-04 11:45:51 -070048 void set(const SkPoint[3], const Sk2f& trans);
49 void set(const SkPoint&, const SkPoint&, const SkPoint&, const Sk2f& trans);
Chris Daltonc1e59632017-09-05 00:30:07 -060050 };
51
Chris Daltona3e92712017-12-04 11:45:51 -070052 struct CubicInstance {
53 float fX[4];
54 float fY[4];
55
56 void set(const SkPoint[4], float dx, float dy);
57 };
Chris Dalton1a325d22017-07-14 15:17:41 -060058
Chris Dalton6a3dbee2017-10-16 10:44:41 -060059 /**
60 * All primitive shapes (triangles and convex closed curve segments) require more than one
61 * render pass. Here we enumerate every render pass needed in order to produce a complete
62 * coverage count mask. This is an exhaustive list of all ccpr coverage shaders.
63 */
64 enum class RenderPass {
Chris Dalton1a325d22017-07-14 15:17:41 -060065 // Triangles.
66 kTriangleHulls,
67 kTriangleEdges,
Chris Dalton1a325d22017-07-14 15:17:41 -060068 kTriangleCorners,
69
70 // Quadratics.
71 kQuadraticHulls,
Chris Daltonb072bb62017-08-07 09:00:46 -060072 kQuadraticCorners,
Chris Dalton1a325d22017-07-14 15:17:41 -060073
74 // Cubics.
Chris Dalton7f578bf2017-09-05 16:46:48 -060075 kSerpentineHulls,
76 kLoopHulls,
77 kSerpentineCorners,
78 kLoopCorners
Chris Dalton1a325d22017-07-14 15:17:41 -060079 };
Chris Dalton1a325d22017-07-14 15:17:41 -060080
Chris Daltona3e92712017-12-04 11:45:51 -070081 static constexpr bool RenderPassIsCubic(RenderPass pass) {
82 return pass >= RenderPass::kSerpentineHulls && pass <= RenderPass::kLoopCorners;
83 }
84
Chris Dalton6a3dbee2017-10-16 10:44:41 -060085 static const char* GetRenderPassName(RenderPass);
86
87 /**
88 * This serves as the base class for each RenderPass's Shader. It indicates what type of
89 * geometry the Impl should generate and provides implementation-independent code to process
90 * the inputs and calculate coverage in the fragment Shader.
91 */
92 class Shader {
93 public:
94 using TexelBufferHandle = GrGLSLGeometryProcessor::TexelBufferHandle;
95
96 // This enum specifies the type of geometry that should be generated for a Shader instance.
97 // Subclasses are limited to three built-in types of geometry to choose from:
98 enum class GeometryType {
99 // Generates a conservative raster hull around the input points. This is the geometry
100 // that causes a pixel to be rasterized if it is touched anywhere by the input polygon.
101 // Coverage is +1 all around.
102 //
103 // Logically, the conservative raster hull is equivalent to the convex hull of pixel
104 // size boxes centered around each input point.
105 kHull,
106
107 // Generates the conservative rasters of the input edges (i.e. convex hull of two
108 // pixel-size boxes centered on both endpoints). Coverage is -1 on the outside border of
109 // the edge geometry and 0 on the inside. This is the only geometry type that associates
110 // coverage values with the output points. It effectively converts a jagged conservative
111 // raster edge into a smooth antialiased edge.
112 kEdges,
113
114 // Generates the conservative rasters of the corners specified by the geometry provider
115 // (i.e. pixel-size box centered on the corner point). Coverage is +1 all around.
116 kCorners
117 };
118
119 virtual GeometryType getGeometryType() const = 0;
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600120
121 // Returns the number of independent geometric segments to generate for the render pass
122 // (number of wedges for a hull, number of edges, or number of corners.)
123 virtual int getNumSegments() const = 0;
124
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600125 union GeometryVars {
126 struct {
127 const char* fAlternatePoints; // floatNx2 (if left null, will use input points).
128 const char* fAlternateMidpoint; // float2 (if left null, finds euclidean midpoint).
129 } fHullVars;
130
131 struct {
132 const char* fPoint; // float2
133 } fCornerVars;
134
135 GeometryVars() { memset(this, 0, sizeof(*this)); }
136 };
137
138 // Called before generating geometry. Subclasses must fill out the applicable fields in
139 // GeometryVars (if any), and may also use this opportunity to setup internal member
140 // variables that will be needed during onEmitVaryings (e.g. transformation matrices).
141 virtual void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
Chris Daltonc17bf322017-10-24 10:59:03 -0600142 const char* wind, GeometryVars*) const {}
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600143
144 void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
145 const char* coverage, const char* wind);
146
147 void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
148 const char* skOutputColor, const char* skOutputCoverage) const;
149
150 // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
Chris Daltoncc0ab7e2017-10-24 14:16:52 -0600151 // border of a conservative raster edge and 0 on the inside. 'leftPt' and 'rightPt' must be
152 // ordered clockwise.
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600153 static void EmitEdgeDistanceEquation(GrGLSLShaderBuilder*, const char* leftPt,
154 const char* rightPt,
155 const char* outputDistanceEquation);
156
157 // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
158 // center. Subclasses can use this for software multisampling.
159 //
160 // Returns the number of samples.
161 static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
162
163 virtual ~Shader() {}
164
165 protected:
166 enum class WindHandling : bool {
167 kHandled,
168 kNotHandled
169 };
170
171 // Here the subclass adds its internal varyings to the handler and produces code to
172 // initialize those varyings from a given position, coverage value, and wind.
173 //
174 // Returns whether the subclass will handle wind modulation or if this base class should
175 // take charge of multiplying the final coverage output by "wind".
176 //
177 // NOTE: the coverage parameter is only relevant for edges (see comments in GeometryType).
178 // Otherwise it is +1 all around.
179 virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code,
180 const char* position, const char* coverage,
181 const char* wind) = 0;
182
183 // Emits the fragment code that calculates a pixel's coverage value. If using
184 // WindHandling::kHandled, this value must be signed appropriately.
185 virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
186 const char* outputCoverage) const = 0;
187
188 private:
189 GrGLSLGeoToFrag fWind{kHalf_GrSLType};
190 };
191
Chris Daltona3e92712017-12-04 11:45:51 -0700192 GrCCPRCoverageProcessor(RenderPass);
Chris Dalton1a325d22017-07-14 15:17:41 -0600193
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600194 const char* name() const override { return GetRenderPassName(fRenderPass); }
Chris Dalton1a325d22017-07-14 15:17:41 -0600195 SkString dumpInfo() const override {
196 return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
197 }
Chris Daltona3e92712017-12-04 11:45:51 -0700198 const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
199 return this->getAttrib((int)attribID);
200 }
201
Chris Dalton1a325d22017-07-14 15:17:41 -0600202 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
203 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
204
Chris Dalton7f578bf2017-09-05 16:46:48 -0600205#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -0700206 // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
Chris Dalton1a325d22017-07-14 15:17:41 -0600207 // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
Chris Daltona640c492017-09-11 22:04:03 -0700208 void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
209 bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
210 float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
Chris Dalton1a325d22017-07-14 15:17:41 -0600211#endif
212
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600213 class GSImpl;
Chris Dalton1a325d22017-07-14 15:17:41 -0600214
215private:
Chris Dalton1a325d22017-07-14 15:17:41 -0600216 // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
217 // accidentally bleed into neighbor pixels.
218 static constexpr float kAABloatRadius = 0.491111f;
219
Chris Dalton43646532017-12-07 12:47:02 -0700220 int numInputPoints() const {
221 return RenderPassIsCubic(fRenderPass) ? 4 : 3;
222 }
223
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600224 static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr<Shader>);
Chris Dalton1a325d22017-07-14 15:17:41 -0600225
Chris Daltona3e92712017-12-04 11:45:51 -0700226 const RenderPass fRenderPass;
227 SkDEBUGCODE(float fDebugBloat = 0;)
Chris Dalton1a325d22017-07-14 15:17:41 -0600228
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600229 typedef GrGeometryProcessor INHERITED;
Chris Dalton1a325d22017-07-14 15:17:41 -0600230};
231
Chris Daltona3e92712017-12-04 11:45:51 -0700232inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) {
233 this->set(p[0], p[1], p[2], trans);
234}
235
236inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
237 const SkPoint& p2, const Sk2f& trans) {
238 Sk2f P0 = Sk2f::Load(&p0) + trans;
239 Sk2f P1 = Sk2f::Load(&p1) + trans;
240 Sk2f P2 = Sk2f::Load(&p2) + trans;
241 Sk2f::Store3(this, P0, P1, P2);
242}
243
244inline void GrCCPRCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) {
245 Sk4f X,Y;
246 Sk4f::Load2(p, &X, &Y);
247 (X + dx).store(&fX);
248 (Y + dy).store(&fY);
249}
250
Chris Dalton1a325d22017-07-14 15:17:41 -0600251#endif