LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/effects - GrOvalEffect.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 163 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "GrOvalEffect.h"
       9             : 
      10             : #include "GrFragmentProcessor.h"
      11             : #include "SkRect.h"
      12             : #include "GrShaderCaps.h"
      13             : #include "glsl/GrGLSLFragmentProcessor.h"
      14             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      15             : #include "glsl/GrGLSLProgramDataManager.h"
      16             : #include "glsl/GrGLSLUniformHandler.h"
      17             : #include "../private/GrGLSL.h"
      18             : 
      19             : //////////////////////////////////////////////////////////////////////////////
      20             : 
      21             : class CircleEffect : public GrFragmentProcessor {
      22             : public:
      23             :     static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
      24             :                                            SkScalar radius);
      25             : 
      26           0 :     ~CircleEffect() override {}
      27             : 
      28           0 :     const char* name() const override { return "Circle"; }
      29             : 
      30           0 :     const SkPoint& getCenter() const { return fCenter; }
      31           0 :     SkScalar getRadius() const { return fRadius; }
      32             : 
      33           0 :     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
      34             : 
      35             : private:
      36             :     CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
      37             : 
      38             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
      39             : 
      40             :     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
      41             : 
      42             :     bool onIsEqual(const GrFragmentProcessor&) const 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           0 : sk_sp<GrFragmentProcessor> CircleEffect::Make(GrPrimitiveEdgeType edgeType, const SkPoint& center,
      54             :                                               SkScalar radius) {
      55           0 :     SkASSERT(radius >= 0);
      56           0 :     return sk_sp<GrFragmentProcessor>(new CircleEffect(edgeType, center, radius));
      57             : }
      58             : 
      59           0 : CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
      60             :         : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
      61             :         , fCenter(c)
      62             :         , fRadius(r)
      63           0 :         , fEdgeType(edgeType) {
      64           0 :     this->initClassID<CircleEffect>();
      65           0 : }
      66             : 
      67           0 : bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
      68           0 :     const CircleEffect& ce = other.cast<CircleEffect>();
      69           0 :     return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
      70             : }
      71             : 
      72             : //////////////////////////////////////////////////////////////////////////////
      73             : 
      74             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect);
      75             : 
      76             : #if GR_TEST_UTILS
      77           0 : sk_sp<GrFragmentProcessor> CircleEffect::TestCreate(GrProcessorTestData* d) {
      78             :     SkPoint center;
      79           0 :     center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
      80           0 :     center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
      81           0 :     SkScalar radius = d->fRandom->nextRangeF(0.f, 1000.f);
      82             :     GrPrimitiveEdgeType et;
      83           0 :     do {
      84           0 :         et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
      85           0 :     } while (kHairlineAA_GrProcessorEdgeType == et);
      86           0 :     return CircleEffect::Make(et, center, radius);
      87             : }
      88             : #endif
      89             : 
      90             : //////////////////////////////////////////////////////////////////////////////
      91             : 
      92           0 : class GLCircleEffect : public GrGLSLFragmentProcessor {
      93             : public:
      94           0 :     GLCircleEffect() : fPrevRadius(-1.0f) { }
      95             : 
      96             :     virtual void emitCode(EmitArgs&) override;
      97             : 
      98             :     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
      99             : 
     100             : protected:
     101             :     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
     102             : 
     103             : private:
     104             :     GrGLSLProgramDataManager::UniformHandle fCircleUniform;
     105             :     SkPoint                                 fPrevCenter;
     106             :     SkScalar                                fPrevRadius;
     107             : 
     108             :     typedef GrGLSLFragmentProcessor INHERITED;
     109             : };
     110             : 
     111           0 : void GLCircleEffect::emitCode(EmitArgs& args) {
     112           0 :     const CircleEffect& ce = args.fFp.cast<CircleEffect>();
     113             :     const char *circleName;
     114             :     // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
     115             :     // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
     116           0 :     fCircleUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     117             :                                                       kVec4f_GrSLType, kDefault_GrSLPrecision,
     118             :                                                       "circle",
     119           0 :                                                       &circleName);
     120             : 
     121           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     122             : 
     123           0 :     SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
     124             :     // TODO: Right now the distance to circle caclulation is performed in a space normalized to the
     125             :     // radius and then denormalized. This is to prevent overflow on devices that have a "real"
     126             :     // mediump. It'd be nice to only to this on mediump devices but we currently don't have the
     127             :     // caps here.
     128           0 :     if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
     129           0 :         fragBuilder->codeAppendf("float d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * "
     130             :                                             "%s.z;",
     131           0 :                                  circleName, circleName, circleName);
     132             :     } else {
     133           0 :         fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - sk_FragCoord.xy) *  %s.w)) * "
     134             :                                                   "%s.z;",
     135           0 :                                  circleName, circleName, circleName);
     136             :     }
     137           0 :     if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
     138           0 :         fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);");
     139             :     } else {
     140           0 :         fragBuilder->codeAppend("d = d > 0.5 ? 1.0 : 0.0;");
     141             :     }
     142             : 
     143           0 :     fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
     144           0 :                              (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("d")).c_str());
     145           0 : }
     146             : 
     147           0 : void GLCircleEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
     148             :                             GrProcessorKeyBuilder* b) {
     149           0 :     const CircleEffect& ce = processor.cast<CircleEffect>();
     150           0 :     b->add32(ce.getEdgeType());
     151           0 : }
     152             : 
     153           0 : void GLCircleEffect::onSetData(const GrGLSLProgramDataManager& pdman,
     154             :                                const GrFragmentProcessor& processor) {
     155           0 :     const CircleEffect& ce = processor.cast<CircleEffect>();
     156           0 :     if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
     157           0 :         SkScalar radius = ce.getRadius();
     158           0 :         if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
     159           0 :             radius -= 0.5f;
     160             :         } else {
     161           0 :             radius += 0.5f;
     162             :         }
     163           0 :         pdman.set4f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius,
     164           0 :                     SkScalarInvert(radius));
     165           0 :         fPrevCenter = ce.getCenter();
     166           0 :         fPrevRadius = ce.getRadius();
     167             :     }
     168           0 : }
     169             : 
     170             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     171             : 
     172           0 : void CircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     173             :                                          GrProcessorKeyBuilder* b) const {
     174           0 :     GLCircleEffect::GenKey(*this, caps, b);
     175           0 : }
     176             : 
     177           0 : GrGLSLFragmentProcessor* CircleEffect::onCreateGLSLInstance() const  {
     178           0 :     return new GLCircleEffect;
     179             : }
     180             : 
     181             : //////////////////////////////////////////////////////////////////////////////
     182             : 
     183             : class EllipseEffect : public GrFragmentProcessor {
     184             : public:
     185             :     static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
     186             :                                            SkScalar rx, SkScalar ry);
     187             : 
     188           0 :     ~EllipseEffect() override {}
     189             : 
     190           0 :     const char* name() const override { return "Ellipse"; }
     191             : 
     192           0 :     const SkPoint& getCenter() const { return fCenter; }
     193           0 :     SkVector getRadii() const { return fRadii; }
     194             : 
     195           0 :     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
     196             : 
     197             : private:
     198             :     EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
     199             : 
     200             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     201             : 
     202             :     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
     203             : 
     204             :     bool onIsEqual(const GrFragmentProcessor&) const override;
     205             : 
     206             :     SkPoint             fCenter;
     207             :     SkVector            fRadii;
     208             :     GrPrimitiveEdgeType    fEdgeType;
     209             : 
     210             :     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
     211             : 
     212             :     typedef GrFragmentProcessor INHERITED;
     213             : };
     214             : 
     215           0 : sk_sp<GrFragmentProcessor> EllipseEffect::Make(GrPrimitiveEdgeType edgeType,
     216             :                                                const SkPoint& center,
     217             :                                                SkScalar rx,
     218             :                                                SkScalar ry) {
     219           0 :     SkASSERT(rx >= 0 && ry >= 0);
     220           0 :     return sk_sp<GrFragmentProcessor>(new EllipseEffect(edgeType, center, rx, ry));
     221             : }
     222             : 
     223           0 : EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
     224           0 :                              SkScalar ry)
     225             :         : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
     226             :         , fCenter(c)
     227             :         , fRadii(SkVector::Make(rx, ry))
     228           0 :         , fEdgeType(edgeType) {
     229           0 :     this->initClassID<EllipseEffect>();
     230           0 : }
     231             : 
     232           0 : bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
     233           0 :     const EllipseEffect& ee = other.cast<EllipseEffect>();
     234           0 :     return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
     235             : }
     236             : 
     237             : //////////////////////////////////////////////////////////////////////////////
     238             : 
     239             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
     240             : 
     241             : #if GR_TEST_UTILS
     242           0 : sk_sp<GrFragmentProcessor> EllipseEffect::TestCreate(GrProcessorTestData* d) {
     243             :     SkPoint center;
     244           0 :     center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
     245           0 :     center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
     246           0 :     SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f);
     247           0 :     SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f);
     248             :     GrPrimitiveEdgeType et;
     249           0 :     do {
     250           0 :         et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
     251           0 :     } while (kHairlineAA_GrProcessorEdgeType == et);
     252           0 :     return EllipseEffect::Make(et, center, rx, ry);
     253             : }
     254             : #endif
     255             : 
     256             : //////////////////////////////////////////////////////////////////////////////
     257             : 
     258           0 : class GLEllipseEffect : public GrGLSLFragmentProcessor {
     259             : public:
     260           0 :     GLEllipseEffect() {
     261           0 :         fPrevRadii.fX = -1.0f;
     262           0 :     }
     263             : 
     264             :     void emitCode(EmitArgs&) override;
     265             : 
     266             :     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
     267             : 
     268             : protected:
     269             :     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
     270             : 
     271             : private:
     272             :     GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
     273             :     GrGLSLProgramDataManager::UniformHandle fScaleUniform;
     274             :     SkPoint                                 fPrevCenter;
     275             :     SkVector                                fPrevRadii;
     276             : 
     277             :     typedef GrGLSLFragmentProcessor INHERITED;
     278             : };
     279             : 
     280           0 : void GLEllipseEffect::emitCode(EmitArgs& args) {
     281           0 :     const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
     282             :     const char *ellipseName;
     283             :     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
     284             :     // The last two terms can underflow on mediump, so we use highp.
     285           0 :     fEllipseUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     286             :                                                        kVec4f_GrSLType, kHigh_GrSLPrecision,
     287             :                                                        "ellipse",
     288           0 :                                                        &ellipseName);
     289             :     // If we're on a device with a "real" mediump then we'll do the distance computation in a space
     290             :     // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
     291             :     // inverse squared radii uniform values are already in this normalized space. The center is
     292             :     // not.
     293           0 :     const char* scaleName = nullptr;
     294           0 :     if (args.fShaderCaps->floatPrecisionVaries()) {
     295           0 :         fScaleUniform = args.fUniformHandler->addUniform(
     296             :             kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision,
     297           0 :             "scale", &scaleName);
     298             :     }
     299             : 
     300           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     301             : 
     302             :     // d is the offset to the ellipse center
     303           0 :     fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName);
     304           0 :     if (scaleName) {
     305           0 :         fragBuilder->codeAppendf("d *= %s.y;", scaleName);
     306             :     }
     307           0 :     fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName);
     308             :     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
     309           0 :     fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;");
     310             :     // grad_dot is the squared length of the gradient of the implicit.
     311           0 :     fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);");
     312             :     // Avoid calling inversesqrt on zero.
     313           0 :     fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
     314           0 :     fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);");
     315           0 :     if (scaleName) {
     316           0 :         fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
     317             :     }
     318             : 
     319           0 :     switch (ee.getEdgeType()) {
     320             :         case kFillAA_GrProcessorEdgeType:
     321           0 :             fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
     322           0 :             break;
     323             :         case kInverseFillAA_GrProcessorEdgeType:
     324           0 :             fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
     325           0 :             break;
     326             :         case kFillBW_GrProcessorEdgeType:
     327           0 :             fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;");
     328           0 :             break;
     329             :         case kInverseFillBW_GrProcessorEdgeType:
     330           0 :             fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;");
     331           0 :             break;
     332             :         case kHairlineAA_GrProcessorEdgeType:
     333           0 :             SkFAIL("Hairline not expected here.");
     334             :     }
     335             : 
     336           0 :     fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
     337           0 :                              (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
     338           0 : }
     339             : 
     340           0 : void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&,
     341             :                              GrProcessorKeyBuilder* b) {
     342           0 :     const EllipseEffect& ee = effect.cast<EllipseEffect>();
     343           0 :     b->add32(ee.getEdgeType());
     344           0 : }
     345             : 
     346           0 : void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
     347             :                                 const GrFragmentProcessor& effect) {
     348           0 :     const EllipseEffect& ee = effect.cast<EllipseEffect>();
     349           0 :     if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
     350             :         float invRXSqd;
     351             :         float invRYSqd;
     352             :         // If we're using a scale factor to work around precision issues, choose the larger radius
     353             :         // as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
     354           0 :         if (fScaleUniform.isValid()) {
     355           0 :             if (ee.getRadii().fX > ee.getRadii().fY) {
     356           0 :                 invRXSqd = 1.f;
     357           0 :                 invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
     358           0 :                            (ee.getRadii().fY * ee.getRadii().fY);
     359           0 :                 pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
     360             :             } else {
     361           0 :                 invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
     362           0 :                            (ee.getRadii().fX * ee.getRadii().fX);
     363           0 :                 invRYSqd = 1.f;
     364           0 :                 pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
     365             :             }
     366             :         } else {
     367           0 :             invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
     368           0 :             invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
     369             :         }
     370           0 :         pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
     371           0 :         fPrevCenter = ee.getCenter();
     372           0 :         fPrevRadii = ee.getRadii();
     373             :     }
     374           0 : }
     375             : 
     376             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     377             : 
     378           0 : void EllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     379             :                                           GrProcessorKeyBuilder* b) const {
     380           0 :     GLEllipseEffect::GenKey(*this, caps, b);
     381           0 : }
     382             : 
     383           0 : GrGLSLFragmentProcessor* EllipseEffect::onCreateGLSLInstance() const  {
     384           0 :     return new GLEllipseEffect;
     385             : }
     386             : 
     387             : //////////////////////////////////////////////////////////////////////////////
     388             : 
     389           0 : sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
     390           0 :     if (kHairlineAA_GrProcessorEdgeType == edgeType) {
     391           0 :         return nullptr;
     392             :     }
     393           0 :     SkScalar w = oval.width();
     394           0 :     SkScalar h = oval.height();
     395           0 :     if (SkScalarNearlyEqual(w, h)) {
     396           0 :         w /= 2;
     397           0 :         return CircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
     398             :     } else {
     399           0 :         w /= 2;
     400           0 :         h /= 2;
     401           0 :         return EllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
     402             :     }
     403             : 
     404             :     return nullptr;
     405             : }

Generated by: LCOV version 1.13