Home | History | Annotate | Download | only in effects
      1 
      2 /*
      3  * Copyright 2014 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "effects/GrCoverageSetOpXP.h"
     10 #include "GrColor.h"
     11 #include "GrDrawTargetCaps.h"
     12 #include "GrProcessor.h"
     13 #include "GrProcOptInfo.h"
     14 #include "gl/GrGLXferProcessor.h"
     15 #include "gl/builders/GrGLFragmentShaderBuilder.h"
     16 #include "gl/builders/GrGLProgramBuilder.h"
     17 
     18 class CoverageSetOpXP : public GrXferProcessor {
     19 public:
     20     static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
     21         return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage));
     22     }
     23 
     24     ~CoverageSetOpXP() override;
     25 
     26     const char* name() const override { return "Coverage Set Op"; }
     27 
     28     GrGLXferProcessor* createGLInstance() const override;
     29 
     30     bool hasSecondaryOutput() const override { return false; }
     31 
     32     bool invertCoverage() const { return fInvertCoverage; }
     33 
     34 private:
     35     CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
     36 
     37     GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
     38                                                  const GrProcOptInfo& coveragePOI,
     39                                                  bool doesStencilWrite,
     40                                                  GrColor* color,
     41                                                  const GrDrawTargetCaps& caps) override;
     42 
     43     void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
     44 
     45     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
     46 
     47     bool onIsEqual(const GrXferProcessor& xpBase) const override {
     48         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
     49         return (fRegionOp == xp.fRegionOp &&
     50                 fInvertCoverage == xp.fInvertCoverage);
     51     }
     52 
     53     SkRegion::Op fRegionOp;
     54     bool         fInvertCoverage;
     55 
     56     typedef GrXferProcessor INHERITED;
     57 };
     58 
     59 ///////////////////////////////////////////////////////////////////////////////
     60 
     61 class GLCoverageSetOpXP : public GrGLXferProcessor {
     62 public:
     63     GLCoverageSetOpXP(const GrProcessor&) {}
     64 
     65     ~GLCoverageSetOpXP() override {}
     66 
     67     static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
     68                        GrProcessorKeyBuilder* b) {
     69         const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
     70         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
     71         b->add32(key);
     72     };
     73 
     74 private:
     75     void onEmitCode(const EmitArgs& args) override {
     76         const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
     77         GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
     78 
     79         if (xp.invertCoverage()) {
     80             fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
     81         } else {
     82             fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
     83         }
     84     }
     85 
     86     void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {};
     87 
     88     typedef GrGLXferProcessor INHERITED;
     89 };
     90 
     91 ///////////////////////////////////////////////////////////////////////////////
     92 
     93 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
     94     : fRegionOp(regionOp)
     95     , fInvertCoverage(invertCoverage) {
     96     this->initClassID<CoverageSetOpXP>();
     97 }
     98 
     99 CoverageSetOpXP::~CoverageSetOpXP() {
    100 }
    101 
    102 void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
    103     GLCoverageSetOpXP::GenKey(*this, caps, b);
    104 }
    105 
    106 GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const {
    107     return SkNEW_ARGS(GLCoverageSetOpXP, (*this));
    108 }
    109 
    110 GrXferProcessor::OptFlags
    111 CoverageSetOpXP::onGetOptimizations(const GrProcOptInfo& colorPOI,
    112                                     const GrProcOptInfo& coveragePOI,
    113                                     bool doesStencilWrite,
    114                                     GrColor* color,
    115                                     const GrDrawTargetCaps& caps) {
    116     // We never look at the color input
    117     return GrXferProcessor::kIgnoreColor_OptFlag;
    118 }
    119 
    120 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
    121     switch (fRegionOp) {
    122         case SkRegion::kReplace_Op:
    123             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    124             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    125             break;
    126         case SkRegion::kIntersect_Op:
    127             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
    128             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    129             break;
    130         case SkRegion::kUnion_Op:
    131             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    132             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    133             break;
    134         case SkRegion::kXOR_Op:
    135             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    136             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    137             break;
    138         case SkRegion::kDifference_Op:
    139             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
    140             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    141             break;
    142         case SkRegion::kReverseDifference_Op:
    143             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    144             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    145             break;
    146     }
    147     blendInfo->fBlendConstant = 0;
    148 }
    149 
    150 ///////////////////////////////////////////////////////////////////////////////
    151 
    152 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
    153     : fRegionOp(regionOp)
    154     , fInvertCoverage(invertCoverage) {
    155     this->initClassID<GrCoverageSetOpXPFactory>();
    156 }
    157 
    158 GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
    159     switch (regionOp) {
    160         case SkRegion::kReplace_Op: {
    161             if (invertCoverage) {
    162                 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
    163                 return SkRef(&gReplaceCDXPFI);
    164             } else {
    165                 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
    166                 return SkRef(&gReplaceCDXPF);
    167             }
    168             break;
    169         }
    170         case SkRegion::kIntersect_Op: {
    171             if (invertCoverage) {
    172                 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
    173                 return SkRef(&gIntersectCDXPFI);
    174             } else {
    175                 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
    176                 return SkRef(&gIntersectCDXPF);
    177             }
    178             break;
    179         }
    180         case SkRegion::kUnion_Op: {
    181             if (invertCoverage) {
    182                 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
    183                 return SkRef(&gUnionCDXPFI);
    184             } else {
    185                 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
    186                 return SkRef(&gUnionCDXPF);
    187             }
    188             break;
    189         }
    190         case SkRegion::kXOR_Op: {
    191             if (invertCoverage) {
    192                 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
    193                 return SkRef(&gXORCDXPFI);
    194             } else {
    195                 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
    196                 return SkRef(&gXORCDXPF);
    197             }
    198             break;
    199         }
    200         case SkRegion::kDifference_Op: {
    201             if (invertCoverage) {
    202                 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
    203                 return SkRef(&gDifferenceCDXPFI);
    204             } else {
    205                 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
    206                 return SkRef(&gDifferenceCDXPF);
    207             }
    208             break;
    209         }
    210         case SkRegion::kReverseDifference_Op: {
    211             if (invertCoverage) {
    212                 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
    213                 return SkRef(&gRevDiffCDXPFI);
    214             } else {
    215                 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
    216                 return SkRef(&gRevDiffCDXPF);
    217             }
    218             break;
    219         }
    220         default:
    221             return NULL;
    222     }
    223 }
    224 
    225 GrXferProcessor*
    226 GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps,
    227                                                 const GrProcOptInfo& colorPOI,
    228                                                 const GrProcOptInfo& covPOI,
    229                                                 const GrDeviceCoordTexture* dstCopy) const {
    230     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
    231 }
    232 
    233 void GrCoverageSetOpXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
    234                                                   const GrProcOptInfo& coveragePOI,
    235                                                   GrXPFactory::InvariantOutput* output) const {
    236     if (SkRegion::kReplace_Op == fRegionOp) {
    237         if (coveragePOI.isSolidWhite()) {
    238             output->fBlendedColor = GrColor_WHITE;
    239             output->fBlendedColorFlags = kRGBA_GrColorComponentFlags;
    240         } else {
    241             output->fBlendedColorFlags = 0;
    242         }
    243 
    244         output->fWillBlendWithDst = false;
    245     } else {
    246         output->fBlendedColorFlags = 0;
    247         output->fWillBlendWithDst = true;
    248     }
    249 }
    250 
    251 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
    252 
    253 GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random,
    254                                                   GrContext*,
    255                                                   const GrDrawTargetCaps&,
    256                                                   GrTexture*[]) {
    257     SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1));
    258     bool invertCoverage = random->nextBool();
    259     return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
    260 }
    261 
    262