blob: cb79ac39c5cf8fb98a1172a755787902a0c9fb50 [file] [log] [blame]
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +00001/*
2 * Copyright 2013 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 GrBezierEffect_DEFINED
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +00009#define GrBezierEffect_DEFINED
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000010
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000011#include "GrDrawTargetCaps.h"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "GrProcessor.h"
joshualitt249af152014-09-15 11:41:13 -070013#include "GrGeometryProcessor.h"
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000014#include "GrTypesPriv.h"
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000015
16/**
17 * Shader is based off of Loop-Blinn Quadratic GPU Rendering
18 * The output of this effect is a hairline edge for conics.
19 * Conics specified by implicit equation K^2 - LM.
20 * K, L, and M, are the first three values of the vertex attribute,
21 * the fourth value is not used. Distance is calculated using a
22 * first order approximation from the taylor series.
23 * Coverage for AA is max(0, 1-distance).
24 *
25 * Test were also run using a second order distance approximation.
26 * There were two versions of the second order approx. The first version
27 * is of roughly the form:
28 * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2.
29 * The second is similar:
30 * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2.
31 * The exact version of the equations can be found in the paper
32 * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin
33 *
34 * In both versions we solve the quadratic for ||q-p||.
35 * Version 1:
36 * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as derived from paper)
37 * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2.0*gF2M);\n");
38 * Version 2:
39 * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2.0*gF2M);\n");
40 *
41 * Also note that 2nd partials of k,l,m are zero
42 *
43 * When comparing the two second order approximations to the first order approximations,
44 * the following results were found. Version 1 tends to underestimate the distances, thus it
45 * basically increases all the error that we were already seeing in the first order
46 * approx. So this version is not the one to use. Version 2 has the opposite effect
47 * and tends to overestimate the distances. This is much closer to what we are
48 * looking for. It is able to render ellipses (even thin ones) without the need to chop.
49 * However, it can not handle thin hyperbolas well and thus would still rely on
50 * chopping to tighten the clipping. Another side effect of the overestimating is
51 * that the curves become much thinner and "ropey". If all that was ever rendered
52 * were "not too thin" curves and ellipses then 2nd order may have an advantage since
53 * only one geometry would need to be rendered. However no benches were run comparing
54 * chopped first order and non chopped 2nd order.
55 */
56class GrGLConicEffect;
57
joshualitt249af152014-09-15 11:41:13 -070058class GrConicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000059public:
joshualittb0a8a372014-09-23 09:50:21 -070060 static GrGeometryProcessor* Create(const GrPrimitiveEdgeType edgeType,
61 const GrDrawTargetCaps& caps) {
62 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gConicFillAA, GrConicEffect,
63 (kFillAA_GrProcessorEdgeType));
64 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gConicHairAA, GrConicEffect,
65 (kHairlineAA_GrProcessorEdgeType));
66 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gConicFillBW, GrConicEffect,
67 (kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000068 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -070069 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000070 if (!caps.shaderDerivativeSupport()) {
71 return NULL;
72 }
73 gConicFillAA->ref();
74 return gConicFillAA;
joshualittb0a8a372014-09-23 09:50:21 -070075 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000076 if (!caps.shaderDerivativeSupport()) {
77 return NULL;
78 }
79 gConicHairAA->ref();
80 return gConicHairAA;
joshualittb0a8a372014-09-23 09:50:21 -070081 case kFillBW_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000082 gConicFillBW->ref();
83 return gConicFillBW;
84 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000085 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000086 }
87 }
88
89 virtual ~GrConicEffect();
90
91 static const char* Name() { return "Conic"; }
92
joshualitt249af152014-09-15 11:41:13 -070093 inline const GrShaderVar& inConicCoeffs() const { return fInConicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -070094 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
95 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
96 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000097
joshualittb0a8a372014-09-23 09:50:21 -070098 typedef GrGLConicEffect GLProcessor;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000099
robertphillipsb4b7a4c2014-10-02 12:12:48 -0700100 virtual void getConstantColorComponents(GrColor* color,
101 uint32_t* validFlags) const SK_OVERRIDE {
102 *validFlags = 0;
103 }
104
joshualittb0a8a372014-09-23 09:50:21 -0700105 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000106
107private:
joshualittb0a8a372014-09-23 09:50:21 -0700108 GrConicEffect(GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000109
joshualittb0a8a372014-09-23 09:50:21 -0700110 virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000111
joshualittb0a8a372014-09-23 09:50:21 -0700112 GrPrimitiveEdgeType fEdgeType;
joshualitt249af152014-09-15 11:41:13 -0700113 const GrShaderVar& fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000114
joshualittb0a8a372014-09-23 09:50:21 -0700115 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000116
joshualitt249af152014-09-15 11:41:13 -0700117 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000118};
119
120///////////////////////////////////////////////////////////////////////////////
121/**
122 * The output of this effect is a hairline edge for quadratics.
123 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
124 * two components of the vertex attribute. At the three control points that define
125 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
126 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
127 * Requires shader derivative instruction support.
128 */
129class GrGLQuadEffect;
130
joshualitt249af152014-09-15 11:41:13 -0700131class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000132public:
joshualittb0a8a372014-09-23 09:50:21 -0700133 static GrGeometryProcessor* Create(const GrPrimitiveEdgeType edgeType,
134 const GrDrawTargetCaps& caps) {
135 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gQuadFillAA, GrQuadEffect,
136 (kFillAA_GrProcessorEdgeType));
137 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gQuadHairAA, GrQuadEffect,
138 (kHairlineAA_GrProcessorEdgeType));
139 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gQuadFillBW, GrQuadEffect,
140 (kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000141 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700142 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000143 if (!caps.shaderDerivativeSupport()) {
144 return NULL;
145 }
146 gQuadFillAA->ref();
147 return gQuadFillAA;
joshualittb0a8a372014-09-23 09:50:21 -0700148 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000149 if (!caps.shaderDerivativeSupport()) {
150 return NULL;
151 }
152 gQuadHairAA->ref();
153 return gQuadHairAA;
joshualittb0a8a372014-09-23 09:50:21 -0700154 case kFillBW_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000155 gQuadFillBW->ref();
156 return gQuadFillBW;
157 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000158 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000159 }
160 }
161
162 virtual ~GrQuadEffect();
163
164 static const char* Name() { return "Quad"; }
165
joshualitt249af152014-09-15 11:41:13 -0700166 inline const GrShaderVar& inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700167 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
168 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
169 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000170
joshualittb0a8a372014-09-23 09:50:21 -0700171 typedef GrGLQuadEffect GLProcessor;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000172
robertphillipsb4b7a4c2014-10-02 12:12:48 -0700173 virtual void getConstantColorComponents(GrColor* color,
174 uint32_t* validFlags) const SK_OVERRIDE {
175 *validFlags = 0;
176 }
177
joshualittb0a8a372014-09-23 09:50:21 -0700178 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000179
180private:
joshualittb0a8a372014-09-23 09:50:21 -0700181 GrQuadEffect(GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000182
joshualittb0a8a372014-09-23 09:50:21 -0700183 virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000184
joshualittb0a8a372014-09-23 09:50:21 -0700185 GrPrimitiveEdgeType fEdgeType;
joshualitt249af152014-09-15 11:41:13 -0700186 const GrShaderVar& fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000187
joshualittb0a8a372014-09-23 09:50:21 -0700188 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000189
joshualitt249af152014-09-15 11:41:13 -0700190 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000191};
192
193//////////////////////////////////////////////////////////////////////////////
194/**
195 * Shader is based off of "Resolution Independent Curve Rendering using
196 * Programmable Graphics Hardware" by Loop and Blinn.
197 * The output of this effect is a hairline edge for non rational cubics.
198 * Cubics are specified by implicit equation K^3 - LM.
199 * K, L, and M, are the first three values of the vertex attribute,
200 * the fourth value is not used. Distance is calculated using a
201 * first order approximation from the taylor series.
202 * Coverage for AA is max(0, 1-distance).
203 */
204class GrGLCubicEffect;
205
joshualitt249af152014-09-15 11:41:13 -0700206class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000207public:
joshualittb0a8a372014-09-23 09:50:21 -0700208 static GrGeometryProcessor* Create(const GrPrimitiveEdgeType edgeType,
209 const GrDrawTargetCaps& caps) {
210 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gCubicFillAA, GrCubicEffect,
211 (kFillAA_GrProcessorEdgeType));
212 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gCubicHairAA, GrCubicEffect,
213 (kHairlineAA_GrProcessorEdgeType));
214 GR_CREATE_STATIC_GEOMETRY_PROCESSOR(gCubicFillBW, GrCubicEffect,
215 (kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000216 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700217 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000218 if (!caps.shaderDerivativeSupport()) {
219 return NULL;
220 }
221 gCubicFillAA->ref();
222 return gCubicFillAA;
joshualittb0a8a372014-09-23 09:50:21 -0700223 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000224 if (!caps.shaderDerivativeSupport()) {
225 return NULL;
226 }
227 gCubicHairAA->ref();
228 return gCubicHairAA;
joshualittb0a8a372014-09-23 09:50:21 -0700229 case kFillBW_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000230 gCubicFillBW->ref();
231 return gCubicFillBW;
232 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000233 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000234 }
235 }
236
237 virtual ~GrCubicEffect();
238
239 static const char* Name() { return "Cubic"; }
240
joshualitt249af152014-09-15 11:41:13 -0700241 inline const GrShaderVar& inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700242 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
243 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
244 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000245
joshualittb0a8a372014-09-23 09:50:21 -0700246 typedef GrGLCubicEffect GLProcessor;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000247
robertphillipsb4b7a4c2014-10-02 12:12:48 -0700248 virtual void getConstantColorComponents(GrColor* color,
249 uint32_t* validFlags) const SK_OVERRIDE {
250 *validFlags = 0;
251 }
252
joshualittb0a8a372014-09-23 09:50:21 -0700253 virtual const GrBackendGeometryProcessorFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000254
255private:
joshualittb0a8a372014-09-23 09:50:21 -0700256 GrCubicEffect(GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000257
joshualittb0a8a372014-09-23 09:50:21 -0700258 virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000259
joshualittb0a8a372014-09-23 09:50:21 -0700260 GrPrimitiveEdgeType fEdgeType;
joshualitt249af152014-09-15 11:41:13 -0700261 const GrShaderVar& fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000262
joshualittb0a8a372014-09-23 09:50:21 -0700263 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000264
joshualitt249af152014-09-15 11:41:13 -0700265 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000266};
267
268#endif