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