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
16class GrGLConicEffect : public GrGLGeometryProcessor {
17public:
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
32private:
33    GrPrimitiveEdgeType fEdgeType;
34
35    typedef GrGLGeometryProcessor INHERITED;
36};
37
38GrGLConicEffect::GrGLConicEffect(const GrBackendProcessorFactory& factory,
39                                 const GrProcessor& effect)
40    : INHERITED (factory) {
41    const GrConicEffect& ce = effect.cast<GrConicEffect>();
42    fEdgeType = ce.getEdgeType();
43}
44
45void 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
122void 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
131GrConicEffect::~GrConicEffect() {}
132
133const GrBackendGeometryProcessorFactory& GrConicEffect::getFactory() const {
134    return GrTBackendGeometryProcessorFactory<GrConicEffect>::getInstance();
135}
136
137GrConicEffect::GrConicEffect(GrPrimitiveEdgeType edgeType)
138    : fEdgeType(edgeType)
139    , fInConicCoeffs(this->addVertexAttrib(GrShaderVar("inConicCoeffs",
140                                                       kVec4f_GrSLType,
141                                                       GrShaderVar::kAttribute_TypeModifier))) {
142}
143
144bool GrConicEffect::onIsEqual(const GrProcessor& other) const {
145    const GrConicEffect& ce = other.cast<GrConicEffect>();
146    return (ce.fEdgeType == fEdgeType);
147}
148
149//////////////////////////////////////////////////////////////////////////////
150
151GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
152
153GrGeometryProcessor* 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
170class GrGLQuadEffect : public GrGLGeometryProcessor {
171public:
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
186private:
187    GrPrimitiveEdgeType fEdgeType;
188
189    typedef GrGLGeometryProcessor INHERITED;
190};
191
192GrGLQuadEffect::GrGLQuadEffect(const GrBackendProcessorFactory& factory,
193                                 const GrProcessor& effect)
194    : INHERITED (factory) {
195    const GrQuadEffect& ce = effect.cast<GrQuadEffect>();
196    fEdgeType = ce.getEdgeType();
197}
198
199void 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
260void 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
269GrQuadEffect::~GrQuadEffect() {}
270
271const GrBackendGeometryProcessorFactory& GrQuadEffect::getFactory() const {
272    return GrTBackendGeometryProcessorFactory<GrQuadEffect>::getInstance();
273}
274
275GrQuadEffect::GrQuadEffect(GrPrimitiveEdgeType edgeType)
276    : fEdgeType(edgeType)
277    , fInHairQuadEdge(this->addVertexAttrib(GrShaderVar("inCubicCoeffs",
278                                                        kVec4f_GrSLType,
279                                                        GrShaderVar::kAttribute_TypeModifier))) {
280}
281
282bool GrQuadEffect::onIsEqual(const GrProcessor& other) const {
283    const GrQuadEffect& ce = other.cast<GrQuadEffect>();
284    return (ce.fEdgeType == fEdgeType);
285}
286
287//////////////////////////////////////////////////////////////////////////////
288
289GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
290
291GrGeometryProcessor* 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
308class GrGLCubicEffect : public GrGLGeometryProcessor {
309public:
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
324private:
325    GrPrimitiveEdgeType fEdgeType;
326
327    typedef GrGLGeometryProcessor INHERITED;
328};
329
330GrGLCubicEffect::GrGLCubicEffect(const GrBackendProcessorFactory& factory,
331                                 const GrProcessor& processor)
332    : INHERITED (factory) {
333    const GrCubicEffect& ce = processor.cast<GrCubicEffect>();
334    fEdgeType = ce.getEdgeType();
335}
336
337void 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
440void 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
449GrCubicEffect::~GrCubicEffect() {}
450
451const GrBackendGeometryProcessorFactory& GrCubicEffect::getFactory() const {
452    return GrTBackendGeometryProcessorFactory<GrCubicEffect>::getInstance();
453}
454
455GrCubicEffect::GrCubicEffect(GrPrimitiveEdgeType edgeType)
456    : fEdgeType(edgeType)
457    , fInCubicCoeffs(this->addVertexAttrib(GrShaderVar("inCubicCoeffs",
458                                                       kVec4f_GrSLType,
459                                                       GrShaderVar::kAttribute_TypeModifier))) {
460}
461
462bool GrCubicEffect::onIsEqual(const GrProcessor& other) const {
463    const GrCubicEffect& ce = other.cast<GrCubicEffect>();
464    return (ce.fEdgeType == fEdgeType);
465}
466
467//////////////////////////////////////////////////////////////////////////////
468
469GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrCubicEffect);
470
471GrGeometryProcessor* 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
484