blob: f4cebd40632e7d9f07a3ef23cd10de08065db622 [file] [log] [blame]
commit-bot@chromium.org89ff6372013-08-22 17:31:06 +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#include "GrBezierEffect.h"
9
10#include "gl/GrGLEffect.h"
11#include "gl/GrGLSL.h"
12#include "GrTBackendEffectFactory.h"
13
14class GrGLConicEffect : public GrGLEffect {
15public:
16 GrGLConicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
17
18 virtual void emitCode(GrGLShaderBuilder* builder,
19 const GrDrawEffect& drawEffect,
20 EffectKey key,
21 const char* outputColor,
22 const char* inputColor,
23 const TextureSamplerArray&) SK_OVERRIDE;
24
25 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
26
27 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
28
29private:
30 GrBezierEdgeType fEdgeType;
31
32 typedef GrGLEffect INHERITED;
33};
34
35GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory,
36 const GrDrawEffect& drawEffect)
37 : INHERITED (factory) {
38 const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
39 fEdgeType = ce.getEdgeType();
40}
41
42void GrGLConicEffect::emitCode(GrGLShaderBuilder* builder,
43 const GrDrawEffect& drawEffect,
44 EffectKey key,
45 const char* outputColor,
46 const char* inputColor,
47 const TextureSamplerArray& samplers) {
48 const char *vsName, *fsName;
49
50 const bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
51 const bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
52
53 if (antiAlias) {
54 SkAssertResult(builder->enableFeature(
55 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
56 }
57 builder->addVarying(kVec4f_GrSLType, "ConicCoeffs",
58 &vsName, &fsName);
59 const SkString* attr0Name =
60 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
61 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
62
63 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
64
65 if (antiAlias) {
66 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
67 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
68 builder->fsCodeAppendf("\t\tfloat dfdx =\n"
69 "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
70 fsName, fsName, fsName);
71 builder->fsCodeAppendf("\t\tfloat dfdy =\n"
72 "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
73 fsName, fsName, fsName);
74 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
75 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
76 }
77 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x - %s.y*%s.z;\n", fsName, fsName,
78 fsName, fsName);
79 if (!fill) {
80 builder->fsCodeAppend("\t\tfunc = abs(func);\n");
81 }
82 if (antiAlias) {
83 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
84 }
85 if (fill) {
86 if (antiAlias) {
87 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
88 // Add line below for smooth cubic ramp
89 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
90 } else {
91 builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
92 }
93 } else {
94 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
95 // Add line below for smooth cubic ramp
96 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
97 }
98
99 SkString modulate;
100 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
101 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
102}
103
104GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
105 const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
106 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
107}
108
109//////////////////////////////////////////////////////////////////////////////
110
111GrConicEffect::~GrConicEffect() {}
112
113const GrBackendEffectFactory& GrConicEffect::getFactory() const {
114 return GrTBackendEffectFactory<GrConicEffect>::getInstance();
115}
116
117GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrEffect() {
118 this->addVertexAttrib(kVec4f_GrSLType);
119 fEdgeType = edgeType;
120}
121
122bool GrConicEffect::onIsEqual(const GrEffect& other) const {
123 const GrConicEffect& ce = CastEffect<GrConicEffect>(other);
124 return (ce.fEdgeType == fEdgeType);
125}
126
127//////////////////////////////////////////////////////////////////////////////
128
129GR_DEFINE_EFFECT_TEST(GrConicEffect);
130
131GrEffectRef* GrConicEffect::TestCreate(SkMWCRandom* random,
132 GrContext*,
133 const GrDrawTargetCaps& caps,
134 GrTexture*[]) {
135 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
136 return GrConicEffect::Create(edgeType, caps);
137}
138
139//////////////////////////////////////////////////////////////////////////////
140// Quad
141//////////////////////////////////////////////////////////////////////////////
142
143class GrGLQuadEffect : public GrGLEffect {
144public:
145 GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
146
147 virtual void emitCode(GrGLShaderBuilder* builder,
148 const GrDrawEffect& drawEffect,
149 EffectKey key,
150 const char* outputColor,
151 const char* inputColor,
152 const TextureSamplerArray&) SK_OVERRIDE;
153
154 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
155
156 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
157
158private:
159 GrBezierEdgeType fEdgeType;
160
161 typedef GrGLEffect INHERITED;
162};
163
164GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory,
165 const GrDrawEffect& drawEffect)
166 : INHERITED (factory) {
167 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
168 fEdgeType = ce.getEdgeType();
169}
170
171void GrGLQuadEffect::emitCode(GrGLShaderBuilder* builder,
172 const GrDrawEffect& drawEffect,
173 EffectKey key,
174 const char* outputColor,
175 const char* inputColor,
176 const TextureSamplerArray& samplers) {
177 const char *vsName, *fsName;
178
179 bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
180 bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
181
182 const SkString* attrName =
183 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
184 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
185
186 if (antiAlias) {
187 SkAssertResult(builder->enableFeature(
188 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
189 }
190 builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
191
192 if (antiAlias) {
193 builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
194 builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
195 builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
196 "\t\t 2.0*%s.x*duvdy.x - duvdy.y);\n",
197 fsName, fsName);
198 }
199 builder->fsCodeAppendf("\t\tfloat func = (%s.x*%s.x - %s.y);\n", fsName, fsName,
200 fsName);
201 if (!fill) {
202 builder->fsCodeAppend("\t\tfunc = abs(func);\n");
203 }
204 if (antiAlias) {
205 builder->fsCodeAppend("\t\tedgeAlpha = func / sqrt(dot(gF, gF));\n");
206 }
207 if (fill) {
208 if (antiAlias) {
209 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
210 // Add line below for smooth cubic ramp
211 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
212 } else {
213 builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
214 }
215 } else {
216 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
217 // Add line below for smooth cubic ramp
218 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
219 }
220
221 SkString modulate;
222 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
223 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
224
225 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
226}
227
228GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
229 const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
230 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
231}
232
233//////////////////////////////////////////////////////////////////////////////
234
235GrQuadEffect::~GrQuadEffect() {}
236
237const GrBackendEffectFactory& GrQuadEffect::getFactory() const {
238 return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
239}
240
241GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrEffect() {
242 this->addVertexAttrib(kVec4f_GrSLType);
243 fEdgeType = edgeType;
244}
245
246bool GrQuadEffect::onIsEqual(const GrEffect& other) const {
247 const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other);
248 return (ce.fEdgeType == fEdgeType);
249}
250
251//////////////////////////////////////////////////////////////////////////////
252
253GR_DEFINE_EFFECT_TEST(GrQuadEffect);
254
255GrEffectRef* GrQuadEffect::TestCreate(SkMWCRandom* random,
256 GrContext*,
257 const GrDrawTargetCaps& caps,
258 GrTexture*[]) {
259 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
260 return GrQuadEffect::Create(edgeType, caps);
261}
262
263//////////////////////////////////////////////////////////////////////////////
264// Cubic
265//////////////////////////////////////////////////////////////////////////////
266
267class GrGLCubicEffect : public GrGLEffect {
268public:
269 GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
270
271 virtual void emitCode(GrGLShaderBuilder* builder,
272 const GrDrawEffect& drawEffect,
273 EffectKey key,
274 const char* outputColor,
275 const char* inputColor,
276 const TextureSamplerArray&) SK_OVERRIDE;
277
278 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
279
280 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
281
282private:
283 GrBezierEdgeType fEdgeType;
284
285 typedef GrGLEffect INHERITED;
286};
287
288GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory,
289 const GrDrawEffect& drawEffect)
290 : INHERITED (factory) {
291 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
292 fEdgeType = ce.getEdgeType();
293}
294
295void GrGLCubicEffect::emitCode(GrGLShaderBuilder* builder,
296 const GrDrawEffect& drawEffect,
297 EffectKey key,
298 const char* outputColor,
299 const char* inputColor,
300 const TextureSamplerArray& samplers) {
301 const char *vsName, *fsName;
302
303 bool antiAlias = GrBezierEdgeTypeIsAA(fEdgeType);
304 bool fill = GrBezierEdgeTypeIsFill(fEdgeType);
305
306 if (antiAlias) {
307 SkAssertResult(builder->enableFeature(
308 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
309 }
310 builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
311 &vsName, &fsName);
312 const SkString* attr0Name =
313 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
314 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
315
316 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
317
318 if (antiAlias) {
319 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
320 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
321 builder->fsCodeAppendf("\t\tfloat dfdx =\n"
322 "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
323 fsName, fsName, fsName, fsName);
324 builder->fsCodeAppendf("\t\tfloat dfdy =\n"
325 "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
326 fsName, fsName, fsName, fsName);
327 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
328 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
329 }
330 builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
331 fsName, fsName, fsName, fsName, fsName);
332 if (!fill) {
333 builder->fsCodeAppend("\t\tfunc = abs(func);\n");
334 }
335 if (antiAlias) {
336 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
337 }
338 if (fill) {
339 if (antiAlias) {
340 builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
341 // Add line below for smooth cubic ramp
342 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
343 } else {
344 builder->fsCodeAppend("\t\tedgeAlpha = float(func < 0.0);\n");
345 }
346 } else {
347 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
348 // Add line below for smooth cubic ramp
349 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
350 }
351
352 SkString modulate;
353 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
354 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
355}
356
357GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
358 const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
359 return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
360}
361
362//////////////////////////////////////////////////////////////////////////////
363
364GrCubicEffect::~GrCubicEffect() {}
365
366const GrBackendEffectFactory& GrCubicEffect::getFactory() const {
367 return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
368}
369
370GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrEffect() {
371 this->addVertexAttrib(kVec4f_GrSLType);
372 fEdgeType = edgeType;
373}
374
375bool GrCubicEffect::onIsEqual(const GrEffect& other) const {
376 const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other);
377 return (ce.fEdgeType == fEdgeType);
378}
379
380//////////////////////////////////////////////////////////////////////////////
381
382GR_DEFINE_EFFECT_TEST(GrCubicEffect);
383
384GrEffectRef* GrCubicEffect::TestCreate(SkMWCRandom* random,
385 GrContext*,
386 const GrDrawTargetCaps& caps,
387 GrTexture*[]) {
388 const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
389 return GrCubicEffect::Create(edgeType, caps);
390}