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