Home | History | Annotate | Download | only in effects
      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 
     15 class GrGLConicEffect : public GrGLVertexEffect {
     16 public:
     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 
     31 private:
     32     GrEffectEdgeType fEdgeType;
     33 
     34     typedef GrGLVertexEffect INHERITED;
     35 };
     36 
     37 GrGLConicEffect::GrGLConicEffect(const GrBackendEffectFactory& factory,
     38                                  const GrDrawEffect& drawEffect)
     39     : INHERITED (factory) {
     40     const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
     41     fEdgeType = ce.getEdgeType();
     42 }
     43 
     44 void 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 
    119 GrGLEffect::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 
    126 GrConicEffect::~GrConicEffect() {}
    127 
    128 const GrBackendEffectFactory& GrConicEffect::getFactory() const {
    129     return GrTBackendEffectFactory<GrConicEffect>::getInstance();
    130 }
    131 
    132 GrConicEffect::GrConicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
    133     this->addVertexAttrib(kVec4f_GrSLType);
    134     fEdgeType = edgeType;
    135 }
    136 
    137 bool GrConicEffect::onIsEqual(const GrEffect& other) const {
    138     const GrConicEffect& ce = CastEffect<GrConicEffect>(other);
    139     return (ce.fEdgeType == fEdgeType);
    140 }
    141 
    142 //////////////////////////////////////////////////////////////////////////////
    143 
    144 GR_DEFINE_EFFECT_TEST(GrConicEffect);
    145 
    146 GrEffectRef* 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 
    163 class GrGLQuadEffect : public GrGLVertexEffect {
    164 public:
    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 
    179 private:
    180     GrEffectEdgeType fEdgeType;
    181 
    182     typedef GrGLVertexEffect INHERITED;
    183 };
    184 
    185 GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory,
    186                                  const GrDrawEffect& drawEffect)
    187     : INHERITED (factory) {
    188     const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
    189     fEdgeType = ce.getEdgeType();
    190 }
    191 
    192 void 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 
    257 GrGLEffect::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 
    264 GrQuadEffect::~GrQuadEffect() {}
    265 
    266 const GrBackendEffectFactory& GrQuadEffect::getFactory() const {
    267     return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
    268 }
    269 
    270 GrQuadEffect::GrQuadEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
    271     this->addVertexAttrib(kVec4f_GrSLType);
    272     fEdgeType = edgeType;
    273 }
    274 
    275 bool GrQuadEffect::onIsEqual(const GrEffect& other) const {
    276     const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other);
    277     return (ce.fEdgeType == fEdgeType);
    278 }
    279 
    280 //////////////////////////////////////////////////////////////////////////////
    281 
    282 GR_DEFINE_EFFECT_TEST(GrQuadEffect);
    283 
    284 GrEffectRef* 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 
    301 class GrGLCubicEffect : public GrGLVertexEffect {
    302 public:
    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 
    317 private:
    318     GrEffectEdgeType fEdgeType;
    319 
    320     typedef GrGLVertexEffect INHERITED;
    321 };
    322 
    323 GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory,
    324                                  const GrDrawEffect& drawEffect)
    325     : INHERITED (factory) {
    326     const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
    327     fEdgeType = ce.getEdgeType();
    328 }
    329 
    330 void 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 
    405 GrGLEffect::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 
    412 GrCubicEffect::~GrCubicEffect() {}
    413 
    414 const GrBackendEffectFactory& GrCubicEffect::getFactory() const {
    415     return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
    416 }
    417 
    418 GrCubicEffect::GrCubicEffect(GrEffectEdgeType edgeType) : GrVertexEffect() {
    419     this->addVertexAttrib(kVec4f_GrSLType);
    420     fEdgeType = edgeType;
    421 }
    422 
    423 bool GrCubicEffect::onIsEqual(const GrEffect& other) const {
    424     const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other);
    425     return (ce.fEdgeType == fEdgeType);
    426 }
    427 
    428 //////////////////////////////////////////////////////////////////////////////
    429 
    430 GR_DEFINE_EFFECT_TEST(GrCubicEffect);
    431 
    432 GrEffectRef* 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