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