blob: 4da16fe88b3dc9474990256133ab24b5b606c923 [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"
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +000012#include "GrEffect.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:
bsalomon83d081a2014-07-08 09:56:10 -070060 static GrEffect* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000061 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:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000081 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000082 }
83 }
84
85 virtual ~GrConicEffect();
86
87 static const char* Name() { return "Conic"; }
88
joshualitt249af152014-09-15 11:41:13 -070089 inline const GrShaderVar& inConicCoeffs() const { return fInConicCoeffs; }
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000090 inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
91 inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
92 inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000093
94 typedef GrGLConicEffect GLEffect;
95
96 virtual void getConstantColorComponents(GrColor* color,
97 uint32_t* validFlags) const SK_OVERRIDE {
98 *validFlags = 0;
99 }
100
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000101 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000102
103private:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000104 GrConicEffect(GrEffectEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000105
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000106 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000107
joshualitt249af152014-09-15 11:41:13 -0700108 GrEffectEdgeType fEdgeType;
109 const GrShaderVar& fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000110
111 GR_DECLARE_EFFECT_TEST;
112
joshualitt249af152014-09-15 11:41:13 -0700113 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000114};
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 */
125class GrGLQuadEffect;
126
joshualitt249af152014-09-15 11:41:13 -0700127class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000128public:
bsalomon83d081a2014-07-08 09:56:10 -0700129 static GrEffect* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000130 GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrEffectEdgeType));
131 GR_CREATE_STATIC_EFFECT(gQuadHairAA, GrQuadEffect, (kHairlineAA_GrEffectEdgeType));
132 GR_CREATE_STATIC_EFFECT(gQuadFillBW, GrQuadEffect, (kFillBW_GrEffectEdgeType));
133 switch (edgeType) {
134 case kFillAA_GrEffectEdgeType:
135 if (!caps.shaderDerivativeSupport()) {
136 return NULL;
137 }
138 gQuadFillAA->ref();
139 return gQuadFillAA;
140 case kHairlineAA_GrEffectEdgeType:
141 if (!caps.shaderDerivativeSupport()) {
142 return NULL;
143 }
144 gQuadHairAA->ref();
145 return gQuadHairAA;
146 case kFillBW_GrEffectEdgeType:
147 gQuadFillBW->ref();
148 return gQuadFillBW;
149 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000150 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000151 }
152 }
153
154 virtual ~GrQuadEffect();
155
156 static const char* Name() { return "Quad"; }
157
joshualitt249af152014-09-15 11:41:13 -0700158 inline const GrShaderVar& inHairQuadEdge() const { return fInHairQuadEdge; }
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000159 inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
160 inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
161 inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000162
163 typedef GrGLQuadEffect GLEffect;
164
165 virtual void getConstantColorComponents(GrColor* color,
166 uint32_t* validFlags) const SK_OVERRIDE {
167 *validFlags = 0;
168 }
169
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000170 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000171
172private:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000173 GrQuadEffect(GrEffectEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000174
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000175 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000176
joshualitt249af152014-09-15 11:41:13 -0700177 GrEffectEdgeType fEdgeType;
178 const GrShaderVar& fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000179
180 GR_DECLARE_EFFECT_TEST;
181
joshualitt249af152014-09-15 11:41:13 -0700182 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000183};
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 */
196class GrGLCubicEffect;
197
joshualitt249af152014-09-15 11:41:13 -0700198class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000199public:
bsalomon83d081a2014-07-08 09:56:10 -0700200 static GrEffect* Create(const GrEffectEdgeType edgeType, const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000201 GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrEffectEdgeType));
202 GR_CREATE_STATIC_EFFECT(gCubicHairAA, GrCubicEffect, (kHairlineAA_GrEffectEdgeType));
203 GR_CREATE_STATIC_EFFECT(gCubicFillBW, GrCubicEffect, (kFillBW_GrEffectEdgeType));
204 switch (edgeType) {
205 case kFillAA_GrEffectEdgeType:
206 if (!caps.shaderDerivativeSupport()) {
207 return NULL;
208 }
209 gCubicFillAA->ref();
210 return gCubicFillAA;
211 case kHairlineAA_GrEffectEdgeType:
212 if (!caps.shaderDerivativeSupport()) {
213 return NULL;
214 }
215 gCubicHairAA->ref();
216 return gCubicHairAA;
217 case kFillBW_GrEffectEdgeType:
218 gCubicFillBW->ref();
219 return gCubicFillBW;
220 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000221 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000222 }
223 }
224
225 virtual ~GrCubicEffect();
226
227 static const char* Name() { return "Cubic"; }
228
joshualitt249af152014-09-15 11:41:13 -0700229 inline const GrShaderVar& inCubicCoeffs() const { return fInCubicCoeffs; }
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000230 inline bool isAntiAliased() const { return GrEffectEdgeTypeIsAA(fEdgeType); }
231 inline bool isFilled() const { return GrEffectEdgeTypeIsFill(fEdgeType); }
232 inline GrEffectEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000233
234 typedef GrGLCubicEffect GLEffect;
235
236 virtual void getConstantColorComponents(GrColor* color,
237 uint32_t* validFlags) const SK_OVERRIDE {
238 *validFlags = 0;
239 }
240
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000241 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000242
243private:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000244 GrCubicEffect(GrEffectEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000245
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +0000246 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000247
joshualitt249af152014-09-15 11:41:13 -0700248 GrEffectEdgeType fEdgeType;
249 const GrShaderVar& fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000250
251 GR_DECLARE_EFFECT_TEST;
252
joshualitt249af152014-09-15 11:41:13 -0700253 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000254};
255
256#endif