blob: 3c4050a73bbb9e1e28cb4587fe612587536cff74 [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;
120 virtual int getNumInputPoints() const = 0;
121
122 // Returns the number of independent geometric segments to generate for the render pass
123 // (number of wedges for a hull, number of edges, or number of corners.)
124 virtual int getNumSegments() const = 0;
125
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600126 // Determines the winding direction of the primitive. The subclass must write a value of
127 // either -1, 0, or +1 to "outputWind" (e.g. "sign(area)"). Fractional values are not valid.
Chris Daltonc17bf322017-10-24 10:59:03 -0600128 virtual void emitWind(GrGLSLShaderBuilder*, const char* pts,
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600129 const char* outputWind) const = 0;
130
131 union GeometryVars {
132 struct {
133 const char* fAlternatePoints; // floatNx2 (if left null, will use input points).
134 const char* fAlternateMidpoint; // float2 (if left null, finds euclidean midpoint).
135 } fHullVars;
136
137 struct {
138 const char* fPoint; // float2
139 } fCornerVars;
140
141 GeometryVars() { memset(this, 0, sizeof(*this)); }
142 };
143
144 // Called before generating geometry. Subclasses must fill out the applicable fields in
145 // GeometryVars (if any), and may also use this opportunity to setup internal member
146 // variables that will be needed during onEmitVaryings (e.g. transformation matrices).
147 virtual void emitSetupCode(GrGLSLShaderBuilder*, const char* pts, const char* segmentId,
Chris Daltonc17bf322017-10-24 10:59:03 -0600148 const char* wind, GeometryVars*) const {}
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600149
150 void emitVaryings(GrGLSLVaryingHandler*, SkString* code, const char* position,
151 const char* coverage, const char* wind);
152
153 void emitFragmentCode(const GrCCPRCoverageProcessor& proc, GrGLSLPPFragmentBuilder*,
154 const char* skOutputColor, const char* skOutputCoverage) const;
155
156 // Defines an equation ("dot(float3(pt, 1), distance_equation)") that is -1 on the outside
Chris Daltoncc0ab7e2017-10-24 14:16:52 -0600157 // border of a conservative raster edge and 0 on the inside. 'leftPt' and 'rightPt' must be
158 // ordered clockwise.
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600159 static void EmitEdgeDistanceEquation(GrGLSLShaderBuilder*, const char* leftPt,
160 const char* rightPt,
161 const char* outputDistanceEquation);
162
163 // Defines a global float2 array that contains MSAA sample locations as offsets from pixel
164 // center. Subclasses can use this for software multisampling.
165 //
166 // Returns the number of samples.
167 static int DefineSoftSampleLocations(GrGLSLPPFragmentBuilder* f, const char* samplesName);
168
169 virtual ~Shader() {}
170
171 protected:
172 enum class WindHandling : bool {
173 kHandled,
174 kNotHandled
175 };
176
177 // Here the subclass adds its internal varyings to the handler and produces code to
178 // initialize those varyings from a given position, coverage value, and wind.
179 //
180 // Returns whether the subclass will handle wind modulation or if this base class should
181 // take charge of multiplying the final coverage output by "wind".
182 //
183 // NOTE: the coverage parameter is only relevant for edges (see comments in GeometryType).
184 // Otherwise it is +1 all around.
185 virtual WindHandling onEmitVaryings(GrGLSLVaryingHandler*, SkString* code,
186 const char* position, const char* coverage,
187 const char* wind) = 0;
188
189 // Emits the fragment code that calculates a pixel's coverage value. If using
190 // WindHandling::kHandled, this value must be signed appropriately.
191 virtual void onEmitFragmentCode(GrGLSLPPFragmentBuilder*,
192 const char* outputCoverage) const = 0;
193
194 private:
195 GrGLSLGeoToFrag fWind{kHalf_GrSLType};
196 };
197
Chris Daltona3e92712017-12-04 11:45:51 -0700198 GrCCPRCoverageProcessor(RenderPass);
Chris Dalton1a325d22017-07-14 15:17:41 -0600199
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600200 const char* name() const override { return GetRenderPassName(fRenderPass); }
Chris Dalton1a325d22017-07-14 15:17:41 -0600201 SkString dumpInfo() const override {
202 return SkStringPrintf("%s\n%s", this->name(), this->INHERITED::dumpInfo().c_str());
203 }
Chris Daltona3e92712017-12-04 11:45:51 -0700204 const Attribute& getInstanceAttrib(InstanceAttribs attribID) const {
205 return this->getAttrib((int)attribID);
206 }
207
Chris Dalton1a325d22017-07-14 15:17:41 -0600208 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
209 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
210
Chris Dalton7f578bf2017-09-05 16:46:48 -0600211#ifdef SK_DEBUG
Chris Daltona640c492017-09-11 22:04:03 -0700212 // Increases the 1/2 pixel AA bloat by a factor of debugBloat and outputs color instead of
Chris Dalton1a325d22017-07-14 15:17:41 -0600213 // coverage (coverage=+1 -> green, coverage=0 -> black, coverage=-1 -> red).
Chris Daltona640c492017-09-11 22:04:03 -0700214 void enableDebugVisualizations(float debugBloat) { fDebugBloat = debugBloat; }
215 bool debugVisualizationsEnabled() const { return fDebugBloat > 0; }
216 float debugBloat() const { SkASSERT(this->debugVisualizationsEnabled()); return fDebugBloat; }
Chris Dalton1a325d22017-07-14 15:17:41 -0600217#endif
218
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600219 class GSImpl;
Chris Dalton1a325d22017-07-14 15:17:41 -0600220
221private:
Chris Dalton1a325d22017-07-14 15:17:41 -0600222 // Slightly undershoot a bloat radius of 0.5 so vertices that fall on integer boundaries don't
223 // accidentally bleed into neighbor pixels.
224 static constexpr float kAABloatRadius = 0.491111f;
225
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600226 static GrGLSLPrimitiveProcessor* CreateGSImpl(std::unique_ptr<Shader>);
Chris Dalton1a325d22017-07-14 15:17:41 -0600227
Chris Daltona3e92712017-12-04 11:45:51 -0700228 const RenderPass fRenderPass;
229 SkDEBUGCODE(float fDebugBloat = 0;)
Chris Dalton1a325d22017-07-14 15:17:41 -0600230
Chris Dalton6a3dbee2017-10-16 10:44:41 -0600231 typedef GrGeometryProcessor INHERITED;
Chris Dalton1a325d22017-07-14 15:17:41 -0600232};
233
Chris Daltona3e92712017-12-04 11:45:51 -0700234inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint p[3], const Sk2f& trans) {
235 this->set(p[0], p[1], p[2], trans);
236}
237
238inline void GrCCPRCoverageProcessor::TriangleInstance::set(const SkPoint& p0, const SkPoint& p1,
239 const SkPoint& p2, const Sk2f& trans) {
240 Sk2f P0 = Sk2f::Load(&p0) + trans;
241 Sk2f P1 = Sk2f::Load(&p1) + trans;
242 Sk2f P2 = Sk2f::Load(&p2) + trans;
243 Sk2f::Store3(this, P0, P1, P2);
244}
245
246inline void GrCCPRCoverageProcessor::CubicInstance::set(const SkPoint p[4], float dx, float dy) {
247 Sk4f X,Y;
248 Sk4f::Load2(p, &X, &Y);
249 (X + dx).store(&fX);
250 (Y + dy).store(&fY);
251}
252
Chris Dalton1a325d22017-07-14 15:17:41 -0600253#endif