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 "glsl/GrGLSLFragmentShaderBuilder.h"
     11 #include "glsl/GrGLSLGeometryProcessor.h"
     12 #include "glsl/GrGLSLProgramDataManager.h"
     13 #include "glsl/GrGLSLUniformHandler.h"
     14 #include "glsl/GrGLSLUtil.h"
     15 #include "glsl/GrGLSLVarying.h"
     16 #include "glsl/GrGLSLVertexShaderBuilder.h"
     17 
     18 class GrGLConicEffect : public GrGLSLGeometryProcessor {
     19 public:
     20     GrGLConicEffect(const GrGeometryProcessor&);
     21 
     22     void onEmitCode(EmitArgs&, GrGPArgs*) override;
     23 
     24     static inline void GenKey(const GrGeometryProcessor&,
     25                               const GrGLSLCaps&,
     26                               GrProcessorKeyBuilder*);
     27 
     28     void setData(const GrGLSLProgramDataManager& pdman,
     29                  const GrPrimitiveProcessor& primProc) override {
     30         const GrConicEffect& ce = primProc.cast<GrConicEffect>();
     31 
     32         if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
     33             fViewMatrix = ce.viewMatrix();
     34             float viewMatrix[3 * 3];
     35             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
     36             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
     37         }
     38 
     39         if (ce.color() != fColor) {
     40             float c[4];
     41             GrColorToRGBAFloat(ce.color(), c);
     42             pdman.set4fv(fColorUniform, 1, c);
     43             fColor = ce.color();
     44         }
     45 
     46         if (ce.coverageScale() != 0xff && ce.coverageScale() != fCoverageScale) {
     47             pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
     48             fCoverageScale = ce.coverageScale();
     49         }
     50     }
     51 
     52     void setTransformData(const GrPrimitiveProcessor& primProc,
     53                           const GrGLSLProgramDataManager& pdman,
     54                           int index,
     55                           const SkTArray<const GrCoordTransform*, true>& transforms) override {
     56         this->setTransformDataHelper<GrConicEffect>(primProc, pdman, index, transforms);
     57     }
     58 
     59 private:
     60     SkMatrix fViewMatrix;
     61     GrColor fColor;
     62     uint8_t fCoverageScale;
     63     GrPrimitiveEdgeType fEdgeType;
     64     UniformHandle fColorUniform;
     65     UniformHandle fCoverageScaleUniform;
     66     UniformHandle fViewMatrixUniform;
     67 
     68     typedef GrGLSLGeometryProcessor INHERITED;
     69 };
     70 
     71 GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor)
     72     : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
     73     const GrConicEffect& ce = processor.cast<GrConicEffect>();
     74     fEdgeType = ce.getEdgeType();
     75 }
     76 
     77 void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
     78     GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
     79     const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
     80     GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
     81     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
     82 
     83     // emit attributes
     84     varyingHandler->emitAttributes(gp);
     85 
     86     GrGLSLVertToFrag v(kVec4f_GrSLType);
     87     varyingHandler->addVarying("ConicCoeffs", &v, kHigh_GrSLPrecision);
     88     vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
     89 
     90     GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
     91     // Setup pass through color
     92     if (!gp.colorIgnored()) {
     93         this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
     94     }
     95 
     96     // Setup position
     97     this->setupPosition(vertBuilder,
     98                         uniformHandler,
     99                         gpArgs,
    100                         gp.inPosition()->fName,
    101                         gp.viewMatrix(),
    102                         &fViewMatrixUniform);
    103 
    104     // emit transforms with position
    105     this->emitTransforms(vertBuilder,
    106                          varyingHandler,
    107                          uniformHandler,
    108                          gpArgs->fPositionVar,
    109                          gp.inPosition()->fName,
    110                          gp.localMatrix(),
    111                          args.fTransformsIn,
    112                          args.fTransformsOut);
    113 
    114     // TODO: this precision check should actually be a check on the number of bits
    115     // high and medium provide and the selection of the lowest level that suffices.
    116     // Additionally we should assert that the upstream code only lets us get here if
    117     // either high or medium provides the required number of bits.
    118     GrSLPrecision precision = kHigh_GrSLPrecision;
    119     const GrShaderCaps::PrecisionInfo& highP = args.fGLSLCaps->getFloatShaderPrecisionInfo(
    120                                                              kFragment_GrShaderType,
    121                                                              kHigh_GrSLPrecision);
    122     if (!highP.supported()) {
    123         precision = kMedium_GrSLPrecision;
    124     }
    125 
    126     GrGLSLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, precision);
    127     GrGLSLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, precision);
    128     GrGLSLShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, precision);
    129     GrGLSLShaderVar dfdx("dfdx", kFloat_GrSLType, 0, precision);
    130     GrGLSLShaderVar dfdy("dfdy", kFloat_GrSLType, 0, precision);
    131     GrGLSLShaderVar gF("gF", kVec2f_GrSLType, 0, precision);
    132     GrGLSLShaderVar gFM("gFM", kFloat_GrSLType, 0, precision);
    133     GrGLSLShaderVar func("func", kFloat_GrSLType, 0, precision);
    134 
    135     fragBuilder->declAppend(edgeAlpha);
    136     fragBuilder->declAppend(dklmdx);
    137     fragBuilder->declAppend(dklmdy);
    138     fragBuilder->declAppend(dfdx);
    139     fragBuilder->declAppend(dfdy);
    140     fragBuilder->declAppend(gF);
    141     fragBuilder->declAppend(gFM);
    142     fragBuilder->declAppend(func);
    143 
    144     switch (fEdgeType) {
    145         case kHairlineAA_GrProcessorEdgeType: {
    146             SkAssertResult(fragBuilder->enableFeature(
    147                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    148             fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
    149             fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
    150             fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    151                                      dfdx.c_str(),
    152                                      v.fsIn(), dklmdx.c_str(),
    153                                      v.fsIn(), dklmdx.c_str(),
    154                                      v.fsIn(), dklmdx.c_str());
    155             fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    156                                      dfdy.c_str(),
    157                                      v.fsIn(), dklmdy.c_str(),
    158                                      v.fsIn(), dklmdy.c_str(),
    159                                      v.fsIn(), dklmdy.c_str());
    160             fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
    161             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
    162                                      gFM.c_str(), gF.c_str(), gF.c_str());
    163             fragBuilder->codeAppendf("%s = %s.x*%s.x - %s.y*%s.z;",
    164                                      func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
    165             fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
    166             fragBuilder->codeAppendf("%s = %s / %s;",
    167                                      edgeAlpha.c_str(), func.c_str(), gFM.c_str());
    168             fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
    169                                      edgeAlpha.c_str(), edgeAlpha.c_str());
    170             // Add line below for smooth cubic ramp
    171             // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
    172             break;
    173         }
    174         case kFillAA_GrProcessorEdgeType: {
    175             SkAssertResult(fragBuilder->enableFeature(
    176                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    177             fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
    178             fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
    179             fragBuilder->codeAppendf("%s ="
    180                                      "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    181                                      dfdx.c_str(),
    182                                      v.fsIn(), dklmdx.c_str(),
    183                                      v.fsIn(), dklmdx.c_str(),
    184                                      v.fsIn(), dklmdx.c_str());
    185             fragBuilder->codeAppendf("%s ="
    186                                      "2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    187                                      dfdy.c_str(),
    188                                      v.fsIn(), dklmdy.c_str(),
    189                                      v.fsIn(), dklmdy.c_str(),
    190                                      v.fsIn(), dklmdy.c_str());
    191             fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
    192             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
    193                                      gFM.c_str(), gF.c_str(), gF.c_str());
    194             fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
    195                                      func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
    196             fragBuilder->codeAppendf("%s = %s / %s;",
    197                                      edgeAlpha.c_str(), func.c_str(), gFM.c_str());
    198             fragBuilder->codeAppendf("%s = clamp(1.0 - %s, 0.0, 1.0);",
    199                                      edgeAlpha.c_str(), edgeAlpha.c_str());
    200             // Add line below for smooth cubic ramp
    201             // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
    202             break;
    203         }
    204         case kFillBW_GrProcessorEdgeType: {
    205             fragBuilder->codeAppendf("%s = %s.x * %s.x - %s.y * %s.z;",
    206                                      edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
    207             fragBuilder->codeAppendf("%s = float(%s < 0.0);",
    208                                      edgeAlpha.c_str(), edgeAlpha.c_str());
    209             break;
    210         }
    211         default:
    212             SkFAIL("Shouldn't get here");
    213     }
    214 
    215     // TODO should we really be doing this?
    216     if (gp.coverageScale() != 0xff) {
    217         const char* coverageScale;
    218         fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
    219                                                            kFloat_GrSLType,
    220                                                            kHigh_GrSLPrecision,
    221                                                            "Coverage",
    222                                                            &coverageScale);
    223         fragBuilder->codeAppendf("%s = vec4(%s * %s);",
    224                                  args.fOutputCoverage, coverageScale, edgeAlpha.c_str());
    225     } else {
    226         fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
    227     }
    228 }
    229 
    230 void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
    231                              const GrGLSLCaps&,
    232                              GrProcessorKeyBuilder* b) {
    233     const GrConicEffect& ce = gp.cast<GrConicEffect>();
    234     uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    235     key |= GrColor_ILLEGAL != ce.color() ? 0x4 : 0x0;
    236     key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
    237     key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
    238     key |= ComputePosKey(ce.viewMatrix()) << 5;
    239     b->add32(key);
    240 }
    241 
    242 //////////////////////////////////////////////////////////////////////////////
    243 
    244 GrConicEffect::~GrConicEffect() {}
    245 
    246 void GrConicEffect::getGLSLProcessorKey(const GrGLSLCaps& caps,
    247                                         GrProcessorKeyBuilder* b) const {
    248     GrGLConicEffect::GenKey(*this, caps, b);
    249 }
    250 
    251 GrGLSLPrimitiveProcessor* GrConicEffect::createGLSLInstance(const GrGLSLCaps&) const {
    252     return new GrGLConicEffect(*this);
    253 }
    254 
    255 GrConicEffect::GrConicEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage,
    256                              GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix,
    257                              bool usesLocalCoords)
    258     : fColor(color)
    259     , fViewMatrix(viewMatrix)
    260     , fLocalMatrix(viewMatrix)
    261     , fUsesLocalCoords(usesLocalCoords)
    262     , fCoverageScale(coverage)
    263     , fEdgeType(edgeType) {
    264     this->initClassID<GrConicEffect>();
    265     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
    266                                                    kHigh_GrSLPrecision));
    267     fInConicCoeffs = &this->addVertexAttrib(Attribute("inConicCoeffs",
    268                                                       kVec4f_GrVertexAttribType));
    269 }
    270 
    271 //////////////////////////////////////////////////////////////////////////////
    272 
    273 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
    274 
    275 const GrGeometryProcessor* GrConicEffect::TestCreate(GrProcessorTestData* d) {
    276     GrGeometryProcessor* gp;
    277     do {
    278         GrPrimitiveEdgeType edgeType =
    279                 static_cast<GrPrimitiveEdgeType>(
    280                         d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
    281         gp = GrConicEffect::Create(GrRandomColor(d->fRandom), GrTest::TestMatrix(d->fRandom),
    282                                    edgeType, *d->fCaps,
    283                                    GrTest::TestMatrix(d->fRandom), d->fRandom->nextBool());
    284     } while (nullptr == gp);
    285     return gp;
    286 }
    287 
    288 //////////////////////////////////////////////////////////////////////////////
    289 // Quad
    290 //////////////////////////////////////////////////////////////////////////////
    291 
    292 class GrGLQuadEffect : public GrGLSLGeometryProcessor {
    293 public:
    294     GrGLQuadEffect(const GrGeometryProcessor&);
    295 
    296     void onEmitCode(EmitArgs&, GrGPArgs*) override;
    297 
    298     static inline void GenKey(const GrGeometryProcessor&,
    299                               const GrGLSLCaps&,
    300                               GrProcessorKeyBuilder*);
    301 
    302     void setData(const GrGLSLProgramDataManager& pdman,
    303                  const GrPrimitiveProcessor& primProc) override {
    304         const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
    305 
    306         if (!qe.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(qe.viewMatrix())) {
    307             fViewMatrix = qe.viewMatrix();
    308             float viewMatrix[3 * 3];
    309             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
    310             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
    311         }
    312 
    313         if (qe.color() != fColor) {
    314             float c[4];
    315             GrColorToRGBAFloat(qe.color(), c);
    316             pdman.set4fv(fColorUniform, 1, c);
    317             fColor = qe.color();
    318         }
    319 
    320         if (qe.coverageScale() != 0xff && qe.coverageScale() != fCoverageScale) {
    321             pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
    322             fCoverageScale = qe.coverageScale();
    323         }
    324     }
    325 
    326     void setTransformData(const GrPrimitiveProcessor& primProc,
    327                           const GrGLSLProgramDataManager& pdman,
    328                           int index,
    329                           const SkTArray<const GrCoordTransform*, true>& transforms) override {
    330         this->setTransformDataHelper<GrQuadEffect>(primProc, pdman, index, transforms);
    331     }
    332 
    333 private:
    334     SkMatrix fViewMatrix;
    335     GrColor fColor;
    336     uint8_t fCoverageScale;
    337     GrPrimitiveEdgeType fEdgeType;
    338     UniformHandle fColorUniform;
    339     UniformHandle fCoverageScaleUniform;
    340     UniformHandle fViewMatrixUniform;
    341 
    342     typedef GrGLSLGeometryProcessor INHERITED;
    343 };
    344 
    345 GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor)
    346     : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
    347     const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
    348     fEdgeType = ce.getEdgeType();
    349 }
    350 
    351 void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
    352     GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
    353     const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
    354     GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
    355     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    356 
    357     // emit attributes
    358     varyingHandler->emitAttributes(gp);
    359 
    360     GrGLSLVertToFrag v(kVec4f_GrSLType);
    361     varyingHandler->addVarying("HairQuadEdge", &v);
    362     vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
    363 
    364     GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
    365     // Setup pass through color
    366     if (!gp.colorIgnored()) {
    367         this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
    368     }
    369 
    370     // Setup position
    371     this->setupPosition(vertBuilder,
    372                         uniformHandler,
    373                         gpArgs,
    374                         gp.inPosition()->fName,
    375                         gp.viewMatrix(),
    376                         &fViewMatrixUniform);
    377 
    378     // emit transforms with position
    379     this->emitTransforms(vertBuilder,
    380                          varyingHandler,
    381                          uniformHandler,
    382                          gpArgs->fPositionVar,
    383                          gp.inPosition()->fName,
    384                          gp.localMatrix(),
    385                          args.fTransformsIn,
    386                          args.fTransformsOut);
    387 
    388     fragBuilder->codeAppendf("float edgeAlpha;");
    389 
    390     switch (fEdgeType) {
    391         case kHairlineAA_GrProcessorEdgeType: {
    392             SkAssertResult(fragBuilder->enableFeature(
    393                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    394             fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
    395             fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
    396             fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
    397                                      "               2.0 * %s.x * duvdy.x - duvdy.y);",
    398                                      v.fsIn(), v.fsIn());
    399             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
    400                                      v.fsIn(), v.fsIn(), v.fsIn());
    401             fragBuilder->codeAppend("edgeAlpha = sqrt(edgeAlpha * edgeAlpha / dot(gF, gF));");
    402             fragBuilder->codeAppend("edgeAlpha = max(1.0 - edgeAlpha, 0.0);");
    403             // Add line below for smooth cubic ramp
    404             // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
    405             break;
    406         }
    407         case kFillAA_GrProcessorEdgeType: {
    408             SkAssertResult(fragBuilder->enableFeature(
    409                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    410             fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
    411             fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
    412             fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
    413                                      "               2.0 * %s.x * duvdy.x - duvdy.y);",
    414                                      v.fsIn(), v.fsIn());
    415             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
    416                                      v.fsIn(), v.fsIn(), v.fsIn());
    417             fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));");
    418             fragBuilder->codeAppend("edgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);");
    419             // Add line below for smooth cubic ramp
    420             // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);");
    421             break;
    422         }
    423         case kFillBW_GrProcessorEdgeType: {
    424             fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);",
    425                                      v.fsIn(), v.fsIn(), v.fsIn());
    426             fragBuilder->codeAppend("edgeAlpha = float(edgeAlpha < 0.0);");
    427             break;
    428         }
    429         default:
    430             SkFAIL("Shouldn't get here");
    431     }
    432 
    433     if (0xff != gp.coverageScale()) {
    434         const char* coverageScale;
    435         fCoverageScaleUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
    436                                                            kFloat_GrSLType,
    437                                                            kDefault_GrSLPrecision,
    438                                                            "Coverage",
    439                                                            &coverageScale);
    440         fragBuilder->codeAppendf("%s = vec4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
    441     } else {
    442         fragBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
    443     }
    444 }
    445 
    446 void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
    447                             const GrGLSLCaps&,
    448                             GrProcessorKeyBuilder* b) {
    449     const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
    450     uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    451     key |= ce.color() != GrColor_ILLEGAL ? 0x4 : 0x0;
    452     key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
    453     key |= ce.usesLocalCoords() && ce.localMatrix().hasPerspective() ? 0x10 : 0x0;
    454     key |= ComputePosKey(ce.viewMatrix()) << 5;
    455     b->add32(key);
    456 }
    457 
    458 //////////////////////////////////////////////////////////////////////////////
    459 
    460 GrQuadEffect::~GrQuadEffect() {}
    461 
    462 void GrQuadEffect::getGLSLProcessorKey(const GrGLSLCaps& caps,
    463                                        GrProcessorKeyBuilder* b) const {
    464     GrGLQuadEffect::GenKey(*this, caps, b);
    465 }
    466 
    467 GrGLSLPrimitiveProcessor* GrQuadEffect::createGLSLInstance(const GrGLSLCaps&) const {
    468     return new GrGLQuadEffect(*this);
    469 }
    470 
    471 GrQuadEffect::GrQuadEffect(GrColor color, const SkMatrix& viewMatrix, uint8_t coverage,
    472                            GrPrimitiveEdgeType edgeType, const SkMatrix& localMatrix,
    473                            bool usesLocalCoords)
    474     : fColor(color)
    475     , fViewMatrix(viewMatrix)
    476     , fLocalMatrix(localMatrix)
    477     , fUsesLocalCoords(usesLocalCoords)
    478     , fCoverageScale(coverage)
    479     , fEdgeType(edgeType) {
    480     this->initClassID<GrQuadEffect>();
    481     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
    482                                                    kHigh_GrSLPrecision));
    483     fInHairQuadEdge = &this->addVertexAttrib(Attribute("inHairQuadEdge",
    484                                                         kVec4f_GrVertexAttribType));
    485 }
    486 
    487 //////////////////////////////////////////////////////////////////////////////
    488 
    489 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
    490 
    491 const GrGeometryProcessor* GrQuadEffect::TestCreate(GrProcessorTestData* d) {
    492     GrGeometryProcessor* gp;
    493     do {
    494         GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
    495                 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
    496         gp = GrQuadEffect::Create(GrRandomColor(d->fRandom),
    497                                   GrTest::TestMatrix(d->fRandom),
    498                                   edgeType, *d->fCaps,
    499                                   GrTest::TestMatrix(d->fRandom),
    500                                   d->fRandom->nextBool());
    501     } while (nullptr == gp);
    502     return gp;
    503 }
    504 
    505 //////////////////////////////////////////////////////////////////////////////
    506 // Cubic
    507 //////////////////////////////////////////////////////////////////////////////
    508 
    509 class GrGLCubicEffect : public GrGLSLGeometryProcessor {
    510 public:
    511     GrGLCubicEffect(const GrGeometryProcessor&);
    512 
    513     void onEmitCode(EmitArgs&, GrGPArgs*) override;
    514 
    515     static inline void GenKey(const GrGeometryProcessor&,
    516                               const GrGLSLCaps&,
    517                               GrProcessorKeyBuilder*);
    518 
    519     void setData(const GrGLSLProgramDataManager& pdman,
    520                  const GrPrimitiveProcessor& primProc) override {
    521         const GrCubicEffect& ce = primProc.cast<GrCubicEffect>();
    522 
    523         if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
    524             fViewMatrix = ce.viewMatrix();
    525             float viewMatrix[3 * 3];
    526             GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
    527             pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
    528         }
    529 
    530         if (ce.color() != fColor) {
    531             float c[4];
    532             GrColorToRGBAFloat(ce.color(), c);
    533             pdman.set4fv(fColorUniform, 1, c);
    534             fColor = ce.color();
    535         }
    536     }
    537 
    538 private:
    539     SkMatrix fViewMatrix;
    540     GrColor fColor;
    541     GrPrimitiveEdgeType fEdgeType;
    542     UniformHandle fColorUniform;
    543     UniformHandle fViewMatrixUniform;
    544 
    545     typedef GrGLSLGeometryProcessor INHERITED;
    546 };
    547 
    548 GrGLCubicEffect::GrGLCubicEffect(const GrGeometryProcessor& processor)
    549     : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL) {
    550     const GrCubicEffect& ce = processor.cast<GrCubicEffect>();
    551     fEdgeType = ce.getEdgeType();
    552 }
    553 
    554 void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
    555     GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
    556     const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>();
    557     GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
    558     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    559 
    560     // emit attributes
    561     varyingHandler->emitAttributes(gp);
    562 
    563     GrGLSLVertToFrag v(kVec4f_GrSLType);
    564     varyingHandler->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
    565     vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName);
    566 
    567     GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
    568     // Setup pass through color
    569     if (!gp.colorIgnored()) {
    570         this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
    571     }
    572 
    573     // Setup position
    574     this->setupPosition(vertBuilder,
    575                         uniformHandler,
    576                         gpArgs,
    577                         gp.inPosition()->fName,
    578                         gp.viewMatrix(),
    579                         &fViewMatrixUniform);
    580 
    581     // emit transforms with position
    582     this->emitTransforms(vertBuilder,
    583                          varyingHandler,
    584                          uniformHandler,
    585                          gpArgs->fPositionVar,
    586                          gp.inPosition()->fName,
    587                          args.fTransformsIn,
    588                          args.fTransformsOut);
    589 
    590 
    591     GrGLSLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
    592     GrGLSLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
    593     GrGLSLShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
    594     GrGLSLShaderVar dfdx("dfdx", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
    595     GrGLSLShaderVar dfdy("dfdy", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
    596     GrGLSLShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision);
    597     GrGLSLShaderVar gFM("gFM", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
    598     GrGLSLShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
    599 
    600     fragBuilder->declAppend(edgeAlpha);
    601     fragBuilder->declAppend(dklmdx);
    602     fragBuilder->declAppend(dklmdy);
    603     fragBuilder->declAppend(dfdx);
    604     fragBuilder->declAppend(dfdy);
    605     fragBuilder->declAppend(gF);
    606     fragBuilder->declAppend(gFM);
    607     fragBuilder->declAppend(func);
    608 
    609     switch (fEdgeType) {
    610         case kHairlineAA_GrProcessorEdgeType: {
    611             SkAssertResult(fragBuilder->enableFeature(
    612                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    613             fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
    614             fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
    615             fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    616                                      dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
    617                                      dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
    618             fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    619                                      dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
    620                                      dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
    621             fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
    622             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
    623                                      gFM.c_str(), gF.c_str(), gF.c_str());
    624             fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
    625                                      func.c_str(), v.fsIn(), v.fsIn(),
    626                                      v.fsIn(), v.fsIn(), v.fsIn());
    627             fragBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
    628             fragBuilder->codeAppendf("%s = %s / %s;",
    629                                      edgeAlpha.c_str(), func.c_str(), gFM.c_str());
    630             fragBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
    631                                      edgeAlpha.c_str(), edgeAlpha.c_str());
    632             // Add line below for smooth cubic ramp
    633             // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
    634             //                        edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
    635             //                        edgeAlpha.c_str());
    636             break;
    637         }
    638         case kFillAA_GrProcessorEdgeType: {
    639             SkAssertResult(fragBuilder->enableFeature(
    640                     GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
    641             fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
    642             fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
    643             fragBuilder->codeAppendf("%s ="
    644                                      "3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    645                                      dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
    646                                      dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
    647             fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
    648                                      dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
    649                                      dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
    650             fragBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
    651             fragBuilder->codeAppendf("%s = sqrt(dot(%s, %s));",
    652                                      gFM.c_str(), gF.c_str(), gF.c_str());
    653             fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
    654                                      func.c_str(),
    655                                      v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
    656             fragBuilder->codeAppendf("%s = %s / %s;",
    657                                      edgeAlpha.c_str(), func.c_str(), gFM.c_str());
    658             fragBuilder->codeAppendf("%s = clamp(1.0 - %s, 0.0, 1.0);",
    659                                      edgeAlpha.c_str(), edgeAlpha.c_str());
    660             // Add line below for smooth cubic ramp
    661             // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
    662             //                        edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
    663             //                        edgeAlpha.c_str());
    664             break;
    665         }
    666         case kFillBW_GrProcessorEdgeType: {
    667             fragBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
    668                                      edgeAlpha.c_str(), v.fsIn(), v.fsIn(),
    669                                      v.fsIn(), v.fsIn(), v.fsIn());
    670             fragBuilder->codeAppendf("%s = float(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
    671             break;
    672         }
    673         default:
    674             SkFAIL("Shouldn't get here");
    675     }
    676 
    677 
    678     fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, edgeAlpha.c_str());
    679 }
    680 
    681 void GrGLCubicEffect::GenKey(const GrGeometryProcessor& gp,
    682                              const GrGLSLCaps&,
    683                              GrProcessorKeyBuilder* b) {
    684     const GrCubicEffect& ce = gp.cast<GrCubicEffect>();
    685     uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
    686     key |= ce.color() != GrColor_ILLEGAL ? 0x4 : 0x8;
    687     key |= ComputePosKey(ce.viewMatrix()) << 5;
    688     b->add32(key);
    689 }
    690 
    691 //////////////////////////////////////////////////////////////////////////////
    692 
    693 GrCubicEffect::~GrCubicEffect() {}
    694 
    695 void GrCubicEffect::getGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
    696     GrGLCubicEffect::GenKey(*this, caps, b);
    697 }
    698 
    699 GrGLSLPrimitiveProcessor* GrCubicEffect::createGLSLInstance(const GrGLSLCaps&) const {
    700     return new GrGLCubicEffect(*this);
    701 }
    702 
    703 GrCubicEffect::GrCubicEffect(GrColor color, const SkMatrix& viewMatrix,
    704                              GrPrimitiveEdgeType edgeType)
    705     : fColor(color)
    706     , fViewMatrix(viewMatrix)
    707     , fEdgeType(edgeType) {
    708     this->initClassID<GrCubicEffect>();
    709     fInPosition = &this->addVertexAttrib(Attribute("inPosition", kVec2f_GrVertexAttribType,
    710                                                    kHigh_GrSLPrecision));
    711     fInCubicCoeffs = &this->addVertexAttrib(Attribute("inCubicCoeffs",
    712                                                         kVec4f_GrVertexAttribType));
    713 }
    714 
    715 //////////////////////////////////////////////////////////////////////////////
    716 
    717 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrCubicEffect);
    718 
    719 const GrGeometryProcessor* GrCubicEffect::TestCreate(GrProcessorTestData* d) {
    720     GrGeometryProcessor* gp;
    721     do {
    722         GrPrimitiveEdgeType edgeType =
    723                 static_cast<GrPrimitiveEdgeType>(
    724                         d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
    725         gp = GrCubicEffect::Create(GrRandomColor(d->fRandom),
    726                                    GrTest::TestMatrix(d->fRandom), edgeType, *d->fCaps);
    727     } while (nullptr == gp);
    728     return gp;
    729 }
    730 
    731