Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2014 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 "gl/builders/GrGLProgramBuilder.h"
      9 #include "GrOvalEffect.h"
     10 
     11 #include "gl/GrGLProcessor.h"
     12 #include "gl/GrGLSL.h"
     13 #include "GrTBackendProcessorFactory.h"
     14 
     15 #include "SkRect.h"
     16 
     17 //////////////////////////////////////////////////////////////////////////////
     18 
     19 class GLCircleEffect;
     20 
     21 class CircleEffect : public GrFragmentProcessor {
     22 public:
     23     static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
     24 
     25     virtual ~CircleEffect() {};
     26     static const char* Name() { return "Circle"; }
     27 
     28     const SkPoint& getCenter() const { return fCenter; }
     29     SkScalar getRadius() const { return fRadius; }
     30 
     31     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
     32 
     33     typedef GLCircleEffect GLProcessor;
     34 
     35     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
     36 
     37     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
     38 
     39 private:
     40     CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
     41 
     42     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
     43 
     44     SkPoint             fCenter;
     45     SkScalar            fRadius;
     46     GrPrimitiveEdgeType    fEdgeType;
     47 
     48     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     49 
     50     typedef GrFragmentProcessor INHERITED;
     51 };
     52 
     53 GrFragmentProcessor* CircleEffect::Create(GrPrimitiveEdgeType edgeType, const SkPoint& center,
     54                                           SkScalar radius) {
     55     SkASSERT(radius >= 0);
     56     return SkNEW_ARGS(CircleEffect, (edgeType, center, radius));
     57 }
     58 
     59 void CircleEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
     60     *validFlags = 0;
     61 }
     62 
     63 const GrBackendFragmentProcessorFactory& CircleEffect::getFactory() const {
     64     return GrTBackendFragmentProcessorFactory<CircleEffect>::getInstance();
     65 }
     66 
     67 CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
     68     : fCenter(c)
     69     , fRadius(r)
     70     , fEdgeType(edgeType) {
     71     this->setWillReadFragmentPosition();
     72 }
     73 
     74 bool CircleEffect::onIsEqual(const GrProcessor& other) const {
     75     const CircleEffect& ce = other.cast<CircleEffect>();
     76     return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
     77 }
     78 
     79 //////////////////////////////////////////////////////////////////////////////
     80 
     81 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect);
     82 
     83 GrFragmentProcessor* CircleEffect::TestCreate(SkRandom* random,
     84                                               GrContext*,
     85                                               const GrDrawTargetCaps& caps,
     86                                               GrTexture*[]) {
     87     SkPoint center;
     88     center.fX = random->nextRangeScalar(0.f, 1000.f);
     89     center.fY = random->nextRangeScalar(0.f, 1000.f);
     90     SkScalar radius = random->nextRangeF(0.f, 1000.f);
     91     GrPrimitiveEdgeType et;
     92     do {
     93         et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt);
     94     } while (kHairlineAA_GrProcessorEdgeType == et);
     95     return CircleEffect::Create(et, center, radius);
     96 }
     97 
     98 //////////////////////////////////////////////////////////////////////////////
     99 
    100 class GLCircleEffect : public GrGLFragmentProcessor {
    101 public:
    102     GLCircleEffect(const GrBackendProcessorFactory&, const GrProcessor&);
    103 
    104     virtual void emitCode(GrGLProgramBuilder* builder,
    105                           const GrFragmentProcessor& fp,
    106                           const GrProcessorKey& key,
    107                           const char* outputColor,
    108                           const char* inputColor,
    109                           const TransformedCoordsArray&,
    110                           const TextureSamplerArray&) SK_OVERRIDE;
    111 
    112     static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
    113 
    114     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
    115 
    116 private:
    117     GrGLProgramDataManager::UniformHandle fCircleUniform;
    118     SkPoint                               fPrevCenter;
    119     SkScalar                              fPrevRadius;
    120 
    121     typedef GrGLFragmentProcessor INHERITED;
    122 };
    123 
    124 GLCircleEffect::GLCircleEffect(const GrBackendProcessorFactory& factory,
    125                                const GrProcessor&)
    126     : INHERITED (factory) {
    127     fPrevRadius = -1.f;
    128 }
    129 
    130 void GLCircleEffect::emitCode(GrGLProgramBuilder* builder,
    131                               const GrFragmentProcessor& fp,
    132                               const GrProcessorKey& key,
    133                               const char* outputColor,
    134                               const char* inputColor,
    135                               const TransformedCoordsArray&,
    136                               const TextureSamplerArray& samplers) {
    137     const CircleEffect& ce = fp.cast<CircleEffect>();
    138     const char *circleName;
    139     // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and
    140     // (... ,radius - 0.5) for inverse fills.
    141     fCircleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
    142                                          kVec3f_GrSLType,
    143                                          "circle",
    144                                          &circleName);
    145 
    146     GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    147     const char* fragmentPos = fsBuilder->fragmentPosition();
    148 
    149     SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
    150     if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
    151         fsBuilder->codeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n",
    152                                 circleName, fragmentPos, circleName);
    153     } else {
    154         fsBuilder->codeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n",
    155                                circleName, fragmentPos, circleName);
    156     }
    157     if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
    158         fsBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
    159     } else {
    160         fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
    161     }
    162 
    163     fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
    164                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str());
    165 }
    166 
    167 void GLCircleEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
    168                             GrProcessorKeyBuilder* b) {
    169     const CircleEffect& ce = processor.cast<CircleEffect>();
    170     b->add32(ce.getEdgeType());
    171 }
    172 
    173 void GLCircleEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
    174     const CircleEffect& ce = processor.cast<CircleEffect>();
    175     if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
    176         SkScalar radius = ce.getRadius();
    177         if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
    178             radius -= 0.5f;
    179         } else {
    180             radius += 0.5f;
    181         }
    182         pdman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius);
    183         fPrevCenter = ce.getCenter();
    184         fPrevRadius = ce.getRadius();
    185     }
    186 }
    187 
    188 //////////////////////////////////////////////////////////////////////////////
    189 
    190 class GLEllipseEffect;
    191 
    192 class EllipseEffect : public GrFragmentProcessor {
    193 public:
    194     static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx,
    195                                        SkScalar ry);
    196 
    197     virtual ~EllipseEffect() {};
    198     static const char* Name() { return "Ellipse"; }
    199 
    200     const SkPoint& getCenter() const { return fCenter; }
    201     SkVector getRadii() const { return fRadii; }
    202 
    203     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
    204 
    205     typedef GLEllipseEffect GLProcessor;
    206 
    207     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
    208 
    209     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
    210 
    211 private:
    212     EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
    213 
    214     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
    215 
    216     SkPoint             fCenter;
    217     SkVector            fRadii;
    218     GrPrimitiveEdgeType    fEdgeType;
    219 
    220     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
    221 
    222     typedef GrFragmentProcessor INHERITED;
    223 };
    224 
    225 GrFragmentProcessor* EllipseEffect::Create(GrPrimitiveEdgeType edgeType,
    226                                            const SkPoint& center,
    227                                            SkScalar rx,
    228                                            SkScalar ry) {
    229     SkASSERT(rx >= 0 && ry >= 0);
    230     return SkNEW_ARGS(EllipseEffect, (edgeType, center, rx, ry));
    231 }
    232 
    233 void EllipseEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
    234     *validFlags = 0;
    235 }
    236 
    237 const GrBackendFragmentProcessorFactory& EllipseEffect::getFactory() const {
    238     return GrTBackendFragmentProcessorFactory<EllipseEffect>::getInstance();
    239 }
    240 
    241 EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry)
    242     : fCenter(c)
    243     , fRadii(SkVector::Make(rx, ry))
    244     , fEdgeType(edgeType) {
    245     this->setWillReadFragmentPosition();
    246 }
    247 
    248 bool EllipseEffect::onIsEqual(const GrProcessor& other) const {
    249     const EllipseEffect& ee = other.cast<EllipseEffect>();
    250     return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
    251 }
    252 
    253 //////////////////////////////////////////////////////////////////////////////
    254 
    255 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
    256 
    257 GrFragmentProcessor* EllipseEffect::TestCreate(SkRandom* random,
    258                                                GrContext*,
    259                                                const GrDrawTargetCaps& caps,
    260                                                GrTexture*[]) {
    261     SkPoint center;
    262     center.fX = random->nextRangeScalar(0.f, 1000.f);
    263     center.fY = random->nextRangeScalar(0.f, 1000.f);
    264     SkScalar rx = random->nextRangeF(0.f, 1000.f);
    265     SkScalar ry = random->nextRangeF(0.f, 1000.f);
    266     GrPrimitiveEdgeType et;
    267     do {
    268         et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt);
    269     } while (kHairlineAA_GrProcessorEdgeType == et);
    270     return EllipseEffect::Create(et, center, rx, ry);
    271 }
    272 
    273 //////////////////////////////////////////////////////////////////////////////
    274 
    275 class GLEllipseEffect : public GrGLFragmentProcessor {
    276 public:
    277     GLEllipseEffect(const GrBackendProcessorFactory&, const GrProcessor&);
    278 
    279     virtual void emitCode(GrGLProgramBuilder* builder,
    280                           const GrFragmentProcessor& fp,
    281                           const GrProcessorKey& key,
    282                           const char* outputColor,
    283                           const char* inputColor,
    284                           const TransformedCoordsArray&,
    285                           const TextureSamplerArray&) SK_OVERRIDE;
    286 
    287     static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
    288 
    289     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
    290 
    291 private:
    292     GrGLProgramDataManager::UniformHandle fEllipseUniform;
    293     SkPoint                               fPrevCenter;
    294     SkVector                              fPrevRadii;
    295 
    296     typedef GrGLFragmentProcessor INHERITED;
    297 };
    298 
    299 GLEllipseEffect::GLEllipseEffect(const GrBackendProcessorFactory& factory,
    300                                  const GrProcessor& effect)
    301     : INHERITED (factory) {
    302     fPrevRadii.fX = -1.f;
    303 }
    304 
    305 void GLEllipseEffect::emitCode(GrGLProgramBuilder* builder,
    306                                const GrFragmentProcessor& fp,
    307                                const GrProcessorKey& key,
    308                                const char* outputColor,
    309                                const char* inputColor,
    310                                const TransformedCoordsArray&,
    311                                const TextureSamplerArray& samplers) {
    312     const EllipseEffect& ee = fp.cast<EllipseEffect>();
    313     const char *ellipseName;
    314     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
    315     fEllipseUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
    316                                          kVec4f_GrSLType,
    317                                          "ellipse",
    318                                          &ellipseName);
    319 
    320     GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    321     const char* fragmentPos = fsBuilder->fragmentPosition();
    322 
    323     // d is the offset to the ellipse center
    324     fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
    325     fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
    326     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
    327     fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
    328     // grad_dot is the squared length of the gradient of the implicit.
    329     fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
    330     // avoid calling inversesqrt on zero.
    331     fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
    332     fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
    333 
    334     switch (ee.getEdgeType()) {
    335         case kFillAA_GrProcessorEdgeType:
    336             fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
    337             break;
    338         case kInverseFillAA_GrProcessorEdgeType:
    339             fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
    340             break;
    341         case kFillBW_GrProcessorEdgeType:
    342             fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
    343             break;
    344         case kInverseFillBW_GrProcessorEdgeType:
    345             fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
    346             break;
    347         case kHairlineAA_GrProcessorEdgeType:
    348             SkFAIL("Hairline not expected here.");
    349     }
    350 
    351     fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
    352                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
    353 }
    354 
    355 void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrGLCaps&,
    356                              GrProcessorKeyBuilder* b) {
    357     const EllipseEffect& ee = effect.cast<EllipseEffect>();
    358     b->add32(ee.getEdgeType());
    359 }
    360 
    361 void GLEllipseEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
    362     const EllipseEffect& ee = effect.cast<EllipseEffect>();
    363     if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
    364         SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
    365         SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
    366         pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
    367         fPrevCenter = ee.getCenter();
    368         fPrevRadii = ee.getRadii();
    369     }
    370 }
    371 
    372 //////////////////////////////////////////////////////////////////////////////
    373 
    374 GrFragmentProcessor* GrOvalEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
    375     if (kHairlineAA_GrProcessorEdgeType == edgeType) {
    376         return NULL;
    377     }
    378     SkScalar w = oval.width();
    379     SkScalar h = oval.height();
    380     if (SkScalarNearlyEqual(w, h)) {
    381         w /= 2;
    382         return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
    383     } else {
    384         w /= 2;
    385         h /= 2;
    386         return EllipseEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
    387     }
    388 
    389     return NULL;
    390 }
    391