LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/effects - GrConvexPolyEffect.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 170 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 32 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 "GrConvexPolyEffect.h"
       9             : #include "SkPathPriv.h"
      10             : #include "effects/GrConstColorProcessor.h"
      11             : #include "glsl/GrGLSLFragmentProcessor.h"
      12             : #include "glsl/GrGLSLFragmentShaderBuilder.h"
      13             : #include "glsl/GrGLSLProgramDataManager.h"
      14             : #include "glsl/GrGLSLUniformHandler.h"
      15             : #include "../private/GrGLSL.h"
      16             : 
      17             : //////////////////////////////////////////////////////////////////////////////
      18           0 : class AARectEffect : public GrFragmentProcessor {
      19             : public:
      20           0 :     const SkRect& getRect() const { return fRect; }
      21             : 
      22           0 :     static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
      23           0 :         return sk_sp<GrFragmentProcessor>(new AARectEffect(edgeType, rect));
      24             :     }
      25             : 
      26           0 :     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
      27             : 
      28           0 :     const char* name() const override { return "AARect"; }
      29             : 
      30             :     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
      31             : 
      32             : private:
      33           0 :     AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
      34           0 :             : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
      35             :             , fRect(rect)
      36           0 :             , fEdgeType(edgeType) {
      37           0 :         this->initClassID<AARectEffect>();
      38           0 :     }
      39             : 
      40             :     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
      41             : 
      42           0 :     bool onIsEqual(const GrFragmentProcessor& other) const override {
      43           0 :         const AARectEffect& aare = other.cast<AARectEffect>();
      44           0 :         return fRect == aare.fRect;
      45             :     }
      46             : 
      47             :     SkRect              fRect;
      48             :     GrPrimitiveEdgeType fEdgeType;
      49             : 
      50             :     typedef GrFragmentProcessor INHERITED;
      51             : 
      52             :     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
      53             : 
      54             : };
      55             : 
      56             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
      57             : 
      58             : #if GR_TEST_UTILS
      59           0 : sk_sp<GrFragmentProcessor> AARectEffect::TestCreate(GrProcessorTestData* d) {
      60           0 :     SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(),
      61           0 :                                    d->fRandom->nextSScalar1(),
      62           0 :                                    d->fRandom->nextSScalar1(),
      63           0 :                                    d->fRandom->nextSScalar1());
      64           0 :     sk_sp<GrFragmentProcessor> fp;
      65           0 :     do {
      66             :         GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
      67           0 :                 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
      68             : 
      69           0 :         fp = AARectEffect::Make(edgeType, rect);
      70             :     } while (nullptr == fp);
      71           0 :     return fp;
      72             : }
      73             : #endif
      74             : 
      75             : //////////////////////////////////////////////////////////////////////////////
      76             : 
      77           0 : class GLAARectEffect : public GrGLSLFragmentProcessor {
      78             : public:
      79           0 :     GLAARectEffect() {
      80           0 :         fPrevRect.fLeft = SK_ScalarNaN;
      81           0 :     }
      82             : 
      83             :     void emitCode(EmitArgs&) override;
      84             : 
      85             :     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
      86             : 
      87             : protected:
      88             :     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
      89             : 
      90             : private:
      91             :     GrGLSLProgramDataManager::UniformHandle fRectUniform;
      92             :     SkRect                                  fPrevRect;
      93             : 
      94             :     typedef GrGLSLFragmentProcessor INHERITED;
      95             : };
      96             : 
      97           0 : void GLAARectEffect::emitCode(EmitArgs& args) {
      98           0 :     const AARectEffect& aare = args.fFp.cast<AARectEffect>();
      99             :     const char *rectName;
     100             :     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
     101             :     // respectively.
     102           0 :     fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
     103             :                                                     kVec4f_GrSLType,
     104             :                                                     kDefault_GrSLPrecision,
     105             :                                                     "rect",
     106           0 :                                                     &rectName);
     107             : 
     108           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     109           0 :     if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
     110             :         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
     111             :         // numbers, xSub and ySub.
     112           0 :         fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
     113           0 :         fragBuilder->codeAppendf("\t\txSub = min(sk_FragCoord.x - %s.x, 0.0);\n", rectName);
     114           0 :         fragBuilder->codeAppendf("\t\txSub += min(%s.z - sk_FragCoord.x, 0.0);\n", rectName);
     115           0 :         fragBuilder->codeAppendf("\t\tySub = min(sk_FragCoord.y - %s.y, 0.0);\n", rectName);
     116           0 :         fragBuilder->codeAppendf("\t\tySub += min(%s.w - sk_FragCoord.y, 0.0);\n", rectName);
     117             :         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
     118             :         // covered.
     119           0 :         fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
     120             :     } else {
     121           0 :         fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
     122           0 :         fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.x - %s.x) > -0.5 ? 1.0 : 0.0;\n",
     123           0 :                                  rectName);
     124           0 :         fragBuilder->codeAppendf("\t\talpha *= (%s.z - sk_FragCoord.x) > -0.5 ? 1.0 : 0.0;\n",
     125           0 :                                  rectName);
     126           0 :         fragBuilder->codeAppendf("\t\talpha *= (sk_FragCoord.y - %s.y) > -0.5 ? 1.0 : 0.0;\n",
     127           0 :                                  rectName);
     128           0 :         fragBuilder->codeAppendf("\t\talpha *= (%s.w - sk_FragCoord.y) > -0.5 ? 1.0 : 0.0;\n",
     129           0 :                                  rectName);
     130             :     }
     131             : 
     132           0 :     if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
     133           0 :         fragBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
     134             :     }
     135           0 :     fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
     136           0 :                              (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
     137           0 : }
     138             : 
     139           0 : void GLAARectEffect::onSetData(const GrGLSLProgramDataManager& pdman,
     140             :                                const GrFragmentProcessor& processor) {
     141           0 :     const AARectEffect& aare = processor.cast<AARectEffect>();
     142           0 :     const SkRect& rect = aare.getRect();
     143           0 :     if (rect != fPrevRect) {
     144           0 :         pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
     145           0 :                    rect.fRight - 0.5f, rect.fBottom - 0.5f);
     146           0 :         fPrevRect = rect;
     147             :     }
     148           0 : }
     149             : 
     150           0 : void GLAARectEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
     151             :                             GrProcessorKeyBuilder* b) {
     152           0 :     const AARectEffect& aare = processor.cast<AARectEffect>();
     153           0 :     b->add32(aare.getEdgeType());
     154           0 : }
     155             : 
     156           0 : void AARectEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
     157           0 :     GLAARectEffect::GenKey(*this, caps, b);
     158           0 : }
     159             : 
     160           0 : GrGLSLFragmentProcessor* AARectEffect::onCreateGLSLInstance() const  {
     161           0 :     return new GLAARectEffect;
     162             : }
     163             : 
     164             : //////////////////////////////////////////////////////////////////////////////
     165             : 
     166           0 : class GrGLConvexPolyEffect : public GrGLSLFragmentProcessor {
     167             : public:
     168           0 :     GrGLConvexPolyEffect() {
     169           0 :         for (size_t i = 0; i < SK_ARRAY_COUNT(fPrevEdges); ++i) {
     170           0 :             fPrevEdges[i] = SK_ScalarNaN;
     171             :         }
     172           0 :     }
     173             : 
     174             :     void emitCode(EmitArgs&) override;
     175             : 
     176             :     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
     177             : 
     178             : protected:
     179             :     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
     180             : 
     181             : private:
     182             :     GrGLSLProgramDataManager::UniformHandle fEdgeUniform;
     183             :     SkScalar                                fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
     184             :     typedef GrGLSLFragmentProcessor INHERITED;
     185             : };
     186             : 
     187           0 : void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
     188           0 :     const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
     189             : 
     190             :     const char *edgeArrayName;
     191           0 :     fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
     192             :                                                          kVec3f_GrSLType,
     193             :                                                          kDefault_GrSLPrecision,
     194             :                                                          "edges",
     195             :                                                          cpe.getEdgeCount(),
     196           0 :                                                          &edgeArrayName);
     197           0 :     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     198           0 :     fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
     199           0 :     fragBuilder->codeAppend("\t\tfloat edge;\n");
     200           0 :     for (int i = 0; i < cpe.getEdgeCount(); ++i) {
     201           0 :         fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(sk_FragCoord.x, sk_FragCoord.y, "
     202             :                                                              "1));\n",
     203           0 :                                  edgeArrayName, i);
     204           0 :         if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
     205           0 :             fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
     206             :         } else {
     207           0 :             fragBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
     208             :         }
     209           0 :         fragBuilder->codeAppend("\t\talpha *= edge;\n");
     210             :     }
     211             : 
     212           0 :     if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
     213           0 :         fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
     214             :     }
     215           0 :     fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
     216           0 :                              (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
     217           0 : }
     218             : 
     219           0 : void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
     220             :                                      const GrFragmentProcessor& effect) {
     221           0 :     const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
     222           0 :     size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
     223           0 :     if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
     224           0 :         pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
     225           0 :         memcpy(fPrevEdges, cpe.getEdges(), byteSize);
     226             :     }
     227           0 : }
     228             : 
     229           0 : void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
     230             :                                   GrProcessorKeyBuilder* b) {
     231           0 :     const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
     232             :     GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
     233           0 :     uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
     234           0 :     b->add32(key);
     235           0 : }
     236             : 
     237             : //////////////////////////////////////////////////////////////////////////////
     238             : 
     239           0 : sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType type, const SkPath& path) {
     240           0 :     if (kHairlineAA_GrProcessorEdgeType == type) {
     241           0 :         return nullptr;
     242             :     }
     243           0 :     if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
     244           0 :         !path.isConvex()) {
     245           0 :         return nullptr;
     246             :     }
     247             : 
     248             :     SkPathPriv::FirstDirection dir;
     249             :     // The only way this should fail is if the clip is effectively a infinitely thin line. In that
     250             :     // case nothing is inside the clip. It'd be nice to detect this at a higher level and either
     251             :     // skip the draw or omit the clip element.
     252           0 :     if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
     253           0 :         if (GrProcessorEdgeTypeIsInverseFill(type)) {
     254             :             return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
     255           0 :                                                GrConstColorProcessor::kModulateRGBA_InputMode);
     256             :         }
     257             :         // This could use kIgnore instead of kModulateRGBA but it would trigger a debug print
     258             :         // about a coverage processor not being compatible with the alpha-as-coverage optimization.
     259             :         // We don't really care about this unlikely case so we just use kModulateRGBA to suppress
     260             :         // the print.
     261             :         return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
     262           0 :                                            GrConstColorProcessor::kModulateRGBA_InputMode);
     263             :     }
     264             : 
     265             :     SkScalar        edges[3 * kMaxEdges];
     266             :     SkPoint         pts[4];
     267             :     SkPath::Verb    verb;
     268           0 :     SkPath::Iter    iter(path, true);
     269             : 
     270             :     // SkPath considers itself convex so long as there is a convex contour within it,
     271             :     // regardless of any degenerate contours such as a string of moveTos before it.
     272             :     // Iterate here to consume any degenerate contours and only process the points
     273             :     // on the actual convex contour.
     274           0 :     int n = 0;
     275           0 :     while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) {
     276           0 :         switch (verb) {
     277             :             case SkPath::kMove_Verb:
     278           0 :                 SkASSERT(n == 0);
     279             :             case SkPath::kClose_Verb:
     280           0 :                 break;
     281             :             case SkPath::kLine_Verb: {
     282           0 :                 if (n >= kMaxEdges) {
     283           0 :                     return nullptr;
     284             :                 }
     285           0 :                 SkVector v = pts[1] - pts[0];
     286           0 :                 v.normalize();
     287           0 :                 if (SkPathPriv::kCCW_FirstDirection == dir) {
     288           0 :                     edges[3 * n] = v.fY;
     289           0 :                     edges[3 * n + 1] = -v.fX;
     290             :                 } else {
     291           0 :                     edges[3 * n] = -v.fY;
     292           0 :                     edges[3 * n + 1] = v.fX;
     293             :                 }
     294           0 :                 edges[3 * n + 2] = -(edges[3 * n] * pts[1].fX + edges[3 * n + 1] * pts[1].fY);
     295           0 :                 ++n;
     296           0 :                 break;
     297             :             }
     298             :             default:
     299           0 :                 return nullptr;
     300             :         }
     301             :     }
     302             : 
     303           0 :     if (path.isInverseFillType()) {
     304           0 :         type = GrInvertProcessorEdgeType(type);
     305             :     }
     306           0 :     return Make(type, n, edges);
     307             : }
     308             : 
     309           0 : sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType edgeType,
     310             :                                                     const SkRect& rect) {
     311           0 :     if (kHairlineAA_GrProcessorEdgeType == edgeType){
     312           0 :         return nullptr;
     313             :     }
     314           0 :     return AARectEffect::Make(edgeType, rect);
     315             : }
     316             : 
     317           0 : GrConvexPolyEffect::~GrConvexPolyEffect() {}
     318             : 
     319           0 : void GrConvexPolyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     320             :                                                GrProcessorKeyBuilder* b) const {
     321           0 :     GrGLConvexPolyEffect::GenKey(*this, caps, b);
     322           0 : }
     323             : 
     324           0 : GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const  {
     325           0 :     return new GrGLConvexPolyEffect;
     326             : }
     327             : 
     328           0 : GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
     329             :         : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
     330             :         , fEdgeType(edgeType)
     331           0 :         , fEdgeCount(n) {
     332           0 :     this->initClassID<GrConvexPolyEffect>();
     333             :     // Factory function should have already ensured this.
     334           0 :     SkASSERT(n <= kMaxEdges);
     335           0 :     memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
     336             :     // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
     337             :     // and 100% covered in the non-AA case.
     338           0 :     for (int i = 0; i < n; ++i) {
     339           0 :         fEdges[3 * i + 2] += SK_ScalarHalf;
     340             :     }
     341           0 : }
     342             : 
     343           0 : bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
     344           0 :     const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
     345             :     // ignore the fact that 0 == -0 and just use memcmp.
     346           0 :     return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
     347           0 :             0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
     348             : }
     349             : 
     350             : //////////////////////////////////////////////////////////////////////////////
     351             : 
     352             : GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
     353             : 
     354             : #if GR_TEST_UTILS
     355           0 : sk_sp<GrFragmentProcessor> GrConvexPolyEffect::TestCreate(GrProcessorTestData* d) {
     356           0 :     int count = d->fRandom->nextULessThan(kMaxEdges) + 1;
     357             :     SkScalar edges[kMaxEdges * 3];
     358           0 :     for (int i = 0; i < 3 * count; ++i) {
     359           0 :         edges[i] = d->fRandom->nextSScalar1();
     360             :     }
     361             : 
     362           0 :     sk_sp<GrFragmentProcessor> fp;
     363           0 :     do {
     364             :         GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
     365           0 :                 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
     366           0 :         fp = GrConvexPolyEffect::Make(edgeType, count, edges);
     367             :     } while (nullptr == fp);
     368           0 :     return fp;
     369             : }
     370             : #endif

Generated by: LCOV version 1.13