• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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
9 #define GrBezierEffect_DEFINED
10 
11 #include "GrDrawTargetCaps.h"
12 #include "GrEffect.h"
13 #include "GrVertexEffect.h"
14 #include "GrTypesPriv.h"
15 
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  */
56 class GrGLConicEffect;
57 
58 class GrConicEffect : public GrVertexEffect {
59 public:
Create(const GrEffectEdgeType edgeType,const GrDrawTargetCaps & caps)60     static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
61         GR_CREATE_STATIC_EFFECT(gConicFillAA, GrConicEffect, (kFillAA_GrEffectEdgeType));
62         GR_CREATE_STATIC_EFFECT(gConicHairAA, GrConicEffect, (kHairlineAA_GrEffectEdgeType));
63         GR_CREATE_STATIC_EFFECT(gConicFillBW, GrConicEffect, (kFillBW_GrEffectEdgeType));
64         switch (edgeType) {
65             case kFillAA_GrEffectEdgeType:
66                 if (!caps.shaderDerivativeSupport()) {
67                     return NULL;
68                 }
69                 gConicFillAA->ref();
70                 return gConicFillAA;
71             case kHairlineAA_GrEffectEdgeType:
72                 if (!caps.shaderDerivativeSupport()) {
73                     return NULL;
74                 }
75                 gConicHairAA->ref();
76                 return gConicHairAA;
77             case kFillBW_GrEffectEdgeType:
78                 gConicFillBW->ref();
79                 return gConicFillBW;
80             default:
81                 return NULL;
82         }
83     }
84 
85     virtual ~GrConicEffect();
86 
Name()87     static const char* Name() { return "Conic"; }
88 
isAntiAliased()89     inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
isFilled()90     inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
getEdgeType()91     inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
92 
93     typedef GrGLConicEffect GLEffect;
94 
getConstantColorComponents(GrColor * color,uint32_t * validFlags)95     virtual void getConstantColorComponents(GrColor* color,
96                                             uint32_t* validFlags) const SK_OVERRIDE {
97         *validFlags = 0;
98     }
99 
100     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
101 
102 private:
103     GrConicEffect(GrEffectEdgeType);
104 
105     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
106 
107     GrEffectEdgeType fEdgeType;
108 
109     GR_DECLARE_EFFECT_TEST;
110 
111     typedef GrVertexEffect INHERITED;
112 };
113 
114 ///////////////////////////////////////////////////////////////////////////////
115 /**
116  * The output of this effect is a hairline edge for quadratics.
117  * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
118  * two components of the vertex attribute. At the three control points that define
119  * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
120  * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
121  * Requires shader derivative instruction support.
122  */
123 class GrGLQuadEffect;
124 
125 class GrQuadEffect : public GrVertexEffect {
126 public:
Create(const GrEffectEdgeType edgeType,const GrDrawTargetCaps & caps)127     static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
128         GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrEffectEdgeType));
129         GR_CREATE_STATIC_EFFECT(gQuadHairAA, GrQuadEffect, (kHairlineAA_GrEffectEdgeType));
130         GR_CREATE_STATIC_EFFECT(gQuadFillBW, GrQuadEffect, (kFillBW_GrEffectEdgeType));
131         switch (edgeType) {
132             case kFillAA_GrEffectEdgeType:
133                 if (!caps.shaderDerivativeSupport()) {
134                     return NULL;
135                 }
136                 gQuadFillAA->ref();
137                 return gQuadFillAA;
138             case kHairlineAA_GrEffectEdgeType:
139                 if (!caps.shaderDerivativeSupport()) {
140                     return NULL;
141                 }
142                 gQuadHairAA->ref();
143                 return gQuadHairAA;
144             case kFillBW_GrEffectEdgeType:
145                 gQuadFillBW->ref();
146                 return gQuadFillBW;
147             default:
148                 return NULL;
149         }
150     }
151 
152     virtual ~GrQuadEffect();
153 
Name()154     static const char* Name() { return "Quad"; }
155 
isAntiAliased()156     inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
isFilled()157     inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
getEdgeType()158     inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
159 
160     typedef GrGLQuadEffect GLEffect;
161 
getConstantColorComponents(GrColor * color,uint32_t * validFlags)162     virtual void getConstantColorComponents(GrColor* color,
163                                             uint32_t* validFlags) const SK_OVERRIDE {
164         *validFlags = 0;
165     }
166 
167     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
168 
169 private:
170     GrQuadEffect(GrEffectEdgeType);
171 
172     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
173 
174     GrEffectEdgeType fEdgeType;
175 
176     GR_DECLARE_EFFECT_TEST;
177 
178     typedef GrVertexEffect INHERITED;
179 };
180 
181 //////////////////////////////////////////////////////////////////////////////
182 /**
183  * Shader is based off of "Resolution Independent Curve Rendering using
184  * Programmable Graphics Hardware" by Loop and Blinn.
185  * The output of this effect is a hairline edge for non rational cubics.
186  * Cubics are specified by implicit equation K^3 - LM.
187  * K, L, and M, are the first three values of the vertex attribute,
188  * the fourth value is not used. Distance is calculated using a
189  * first order approximation from the taylor series.
190  * Coverage for AA is max(0, 1-distance).
191  */
192 class GrGLCubicEffect;
193 
194 class GrCubicEffect : public GrVertexEffect {
195 public:
Create(const GrEffectEdgeType edgeType,const GrDrawTargetCaps & caps)196     static GrEffectRef* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
197         GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrEffectEdgeType));
198         GR_CREATE_STATIC_EFFECT(gCubicHairAA, GrCubicEffect, (kHairlineAA_GrEffectEdgeType));
199         GR_CREATE_STATIC_EFFECT(gCubicFillBW, GrCubicEffect, (kFillBW_GrEffectEdgeType));
200         switch (edgeType) {
201             case kFillAA_GrEffectEdgeType:
202                 if (!caps.shaderDerivativeSupport()) {
203                     return NULL;
204                 }
205                 gCubicFillAA->ref();
206                 return gCubicFillAA;
207             case kHairlineAA_GrEffectEdgeType:
208                 if (!caps.shaderDerivativeSupport()) {
209                     return NULL;
210                 }
211                 gCubicHairAA->ref();
212                 return gCubicHairAA;
213             case kFillBW_GrEffectEdgeType:
214                 gCubicFillBW->ref();
215                 return gCubicFillBW;
216             default:
217                 return NULL;
218         }
219     }
220 
221     virtual ~GrCubicEffect();
222 
Name()223     static const char* Name() { return "Cubic"; }
224 
isAntiAliased()225     inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
isFilled()226     inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
getEdgeType()227     inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
228 
229     typedef GrGLCubicEffect GLEffect;
230 
getConstantColorComponents(GrColor * color,uint32_t * validFlags)231     virtual void getConstantColorComponents(GrColor* color,
232                                             uint32_t* validFlags) const SK_OVERRIDE {
233         *validFlags = 0;
234     }
235 
236     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
237 
238 private:
239     GrCubicEffect(GrEffectEdgeType);
240 
241     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
242 
243     GrEffectEdgeType fEdgeType;
244 
245     GR_DECLARE_EFFECT_TEST;
246 
247     typedef GrVertexEffect INHERITED;
248 };
249 
250 #endif
251