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     GrBezierEdgeType 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 kHairAA_GrBezierEdgeType: {
     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_GrBezierEdgeType: {
     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 kFillNoAA_GrBezierEdgeType: {
    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     }
    112 
    113     builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    114                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    115 }
    116 
    117 GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    118     const GrConicEffect& ce = drawEffect.castEffect<GrConicEffect>();
    119     return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    120 }
    121 
    122 //////////////////////////////////////////////////////////////////////////////
    123 
    124 GrConicEffect::~GrConicEffect() {}
    125 
    126 const GrBackendEffectFactory& GrConicEffect::getFactory() const {
    127     return GrTBackendEffectFactory<GrConicEffect>::getInstance();
    128 }
    129 
    130 GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
    131     this->addVertexAttrib(kVec4f_GrSLType);
    132     fEdgeType = edgeType;
    133 }
    134 
    135 bool GrConicEffect::onIsEqual(const GrEffect& other) const {
    136     const GrConicEffect& ce = CastEffect<GrConicEffect>(other);
    137     return (ce.fEdgeType == fEdgeType);
    138 }
    139 
    140 //////////////////////////////////////////////////////////////////////////////
    141 
    142 GR_DEFINE_EFFECT_TEST(GrConicEffect);
    143 
    144 GrEffectRef* GrConicEffect::TestCreate(SkRandom* random,
    145                                              GrContext*,
    146                                              const GrDrawTargetCaps& caps,
    147                                              GrTexture*[]) {
    148     const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
    149     return GrConicEffect::Create(edgeType, caps);
    150 }
    151 
    152 //////////////////////////////////////////////////////////////////////////////
    153 // Quad
    154 //////////////////////////////////////////////////////////////////////////////
    155 
    156 class GrGLQuadEffect : public GrGLVertexEffect {
    157 public:
    158     GrGLQuadEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
    159 
    160     virtual void emitCode(GrGLFullShaderBuilder* builder,
    161                           const GrDrawEffect& drawEffect,
    162                           EffectKey key,
    163                           const char* outputColor,
    164                           const char* inputColor,
    165                           const TransformedCoordsArray&,
    166                           const TextureSamplerArray&) SK_OVERRIDE;
    167 
    168     static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
    169 
    170     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
    171 
    172 private:
    173     GrBezierEdgeType fEdgeType;
    174 
    175     typedef GrGLVertexEffect INHERITED;
    176 };
    177 
    178 GrGLQuadEffect::GrGLQuadEffect(const GrBackendEffectFactory& factory,
    179                                  const GrDrawEffect& drawEffect)
    180     : INHERITED (factory) {
    181     const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
    182     fEdgeType = ce.getEdgeType();
    183 }
    184 
    185 void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
    186                               const GrDrawEffect& drawEffect,
    187                               EffectKey key,
    188                               const char* outputColor,
    189                               const char* inputColor,
    190                               const TransformedCoordsArray&,
    191                               const TextureSamplerArray& samplers) {
    192     const char *vsName, *fsName;
    193 
    194     const SkString* attrName =
    195         builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    196     builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
    197 
    198     builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
    199 
    200     switch (fEdgeType) {
    201         case kHairAA_GrBezierEdgeType: {
    202             SkAssertResult(builder->enableFeature(
    203                     GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
    204             builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
    205             builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
    206             builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
    207                                    "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
    208                                    fsName, fsName);
    209             builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
    210                                    fsName);
    211             builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / dot(gF, gF));\n");
    212             builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
    213             // Add line below for smooth cubic ramp
    214             // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
    215             break;
    216         }
    217         case kFillAA_GrBezierEdgeType: {
    218             SkAssertResult(builder->enableFeature(
    219                     GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
    220             builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
    221             builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
    222             builder->fsCodeAppendf("\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
    223                                    "\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
    224                                    fsName, fsName);
    225             builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
    226                                    fsName);
    227             builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha / sqrt(dot(gF, gF));\n");
    228             builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
    229             // Add line below for smooth cubic ramp
    230             // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
    231             break;
    232         }
    233         case kFillNoAA_GrBezierEdgeType: {
    234             builder->fsCodeAppendf("\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
    235                                    fsName);
    236             builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
    237             break;
    238         }
    239     }
    240 
    241     builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    242                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    243 
    244 
    245     builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
    246 }
    247 
    248 GrGLEffect::EffectKey GrGLQuadEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    249     const GrQuadEffect& ce = drawEffect.castEffect<GrQuadEffect>();
    250     return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    251 }
    252 
    253 //////////////////////////////////////////////////////////////////////////////
    254 
    255 GrQuadEffect::~GrQuadEffect() {}
    256 
    257 const GrBackendEffectFactory& GrQuadEffect::getFactory() const {
    258     return GrTBackendEffectFactory<GrQuadEffect>::getInstance();
    259 }
    260 
    261 GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
    262     this->addVertexAttrib(kVec4f_GrSLType);
    263     fEdgeType = edgeType;
    264 }
    265 
    266 bool GrQuadEffect::onIsEqual(const GrEffect& other) const {
    267     const GrQuadEffect& ce = CastEffect<GrQuadEffect>(other);
    268     return (ce.fEdgeType == fEdgeType);
    269 }
    270 
    271 //////////////////////////////////////////////////////////////////////////////
    272 
    273 GR_DEFINE_EFFECT_TEST(GrQuadEffect);
    274 
    275 GrEffectRef* GrQuadEffect::TestCreate(SkRandom* random,
    276                                              GrContext*,
    277                                              const GrDrawTargetCaps& caps,
    278                                              GrTexture*[]) {
    279     const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
    280     return GrQuadEffect::Create(edgeType, caps);
    281 }
    282 
    283 //////////////////////////////////////////////////////////////////////////////
    284 // Cubic
    285 //////////////////////////////////////////////////////////////////////////////
    286 
    287 class GrGLCubicEffect : public GrGLVertexEffect {
    288 public:
    289     GrGLCubicEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
    290 
    291     virtual void emitCode(GrGLFullShaderBuilder* builder,
    292                           const GrDrawEffect& drawEffect,
    293                           EffectKey key,
    294                           const char* outputColor,
    295                           const char* inputColor,
    296                           const TransformedCoordsArray&,
    297                           const TextureSamplerArray&) SK_OVERRIDE;
    298 
    299     static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
    300 
    301     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
    302 
    303 private:
    304     GrBezierEdgeType fEdgeType;
    305 
    306     typedef GrGLVertexEffect INHERITED;
    307 };
    308 
    309 GrGLCubicEffect::GrGLCubicEffect(const GrBackendEffectFactory& factory,
    310                                  const GrDrawEffect& drawEffect)
    311     : INHERITED (factory) {
    312     const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
    313     fEdgeType = ce.getEdgeType();
    314 }
    315 
    316 void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
    317                                const GrDrawEffect& drawEffect,
    318                                EffectKey key,
    319                                const char* outputColor,
    320                                const char* inputColor,
    321                                const TransformedCoordsArray&,
    322                                const TextureSamplerArray& samplers) {
    323     const char *vsName, *fsName;
    324 
    325     builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
    326                               &vsName, &fsName);
    327     const SkString* attr0Name =
    328         builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    329     builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
    330 
    331     builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
    332 
    333     switch (fEdgeType) {
    334         case kHairAA_GrBezierEdgeType: {
    335             SkAssertResult(builder->enableFeature(
    336                     GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
    337             builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
    338             builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
    339             builder->fsCodeAppendf("\t\tfloat dfdx =\n"
    340                                    "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
    341                                    fsName, fsName, fsName, fsName);
    342             builder->fsCodeAppendf("\t\tfloat dfdy =\n"
    343                                    "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
    344                                    fsName, fsName, fsName, fsName);
    345             builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
    346             builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
    347             builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
    348                                    fsName, fsName, fsName, fsName, fsName);
    349             builder->fsCodeAppend("\t\tfunc = abs(func);\n");
    350             builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
    351             builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
    352             // Add line below for smooth cubic ramp
    353             // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
    354             break;
    355         }
    356         case kFillAA_GrBezierEdgeType: {
    357             SkAssertResult(builder->enableFeature(
    358                     GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
    359             builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
    360             builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
    361             builder->fsCodeAppendf("\t\tfloat dfdx =\n"
    362                                    "\t\t3.0*%s.x*%s.x*dklmdx.x - %s.y*dklmdx.z - %s.z*dklmdx.y;\n",
    363                                    fsName, fsName, fsName, fsName);
    364             builder->fsCodeAppendf("\t\tfloat dfdy =\n"
    365                                    "\t\t3.0*%s.x*%s.x*dklmdy.x - %s.y*dklmdy.z - %s.z*dklmdy.y;\n",
    366                                    fsName, fsName, fsName, fsName);
    367             builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
    368             builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
    369             builder->fsCodeAppendf("\t\tfloat func = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
    370                                    fsName, fsName, fsName, fsName, fsName);
    371             builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
    372             builder->fsCodeAppend("\t\tedgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);\n");
    373             // Add line below for smooth cubic ramp
    374             // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);\n");
    375             break;
    376         }
    377         case kFillNoAA_GrBezierEdgeType: {
    378             builder->fsCodeAppendf("\t\tedgeAlpha = %s.x*%s.x*%s.x - %s.y*%s.z;\n",
    379                                    fsName, fsName, fsName, fsName, fsName);
    380             builder->fsCodeAppend("\t\tedgeAlpha = float(edgeAlpha < 0.0);\n");
    381             break;
    382         }
    383     }
    384 
    385     builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    386                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    387 }
    388 
    389 GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    390     const GrCubicEffect& ce = drawEffect.castEffect<GrCubicEffect>();
    391     return ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    392 }
    393 
    394 //////////////////////////////////////////////////////////////////////////////
    395 
    396 GrCubicEffect::~GrCubicEffect() {}
    397 
    398 const GrBackendEffectFactory& GrCubicEffect::getFactory() const {
    399     return GrTBackendEffectFactory<GrCubicEffect>::getInstance();
    400 }
    401 
    402 GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() {
    403     this->addVertexAttrib(kVec4f_GrSLType);
    404     fEdgeType = edgeType;
    405 }
    406 
    407 bool GrCubicEffect::onIsEqual(const GrEffect& other) const {
    408     const GrCubicEffect& ce = CastEffect<GrCubicEffect>(other);
    409     return (ce.fEdgeType == fEdgeType);
    410 }
    411 
    412 //////////////////////////////////////////////////////////////////////////////
    413 
    414 GR_DEFINE_EFFECT_TEST(GrCubicEffect);
    415 
    416 GrEffectRef* GrCubicEffect::TestCreate(SkRandom* random,
    417                                              GrContext*,
    418                                              const GrDrawTargetCaps& caps,
    419                                              GrTexture*[]) {
    420     const GrBezierEdgeType edgeType = static_cast<GrBezierEdgeType>(random->nextULessThan(3));
    421     return GrCubicEffect::Create(edgeType, caps);
    422 }
    423