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 "effects/GrCoverageSetOpXP.h"
      9 #include "GrCaps.h"
     10 #include "GrColor.h"
     11 #include "GrPipeline.h"
     12 #include "GrProcessor.h"
     13 #include "GrRenderTargetContext.h"
     14 #include "glsl/GrGLSLBlend.h"
     15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     16 #include "glsl/GrGLSLUniformHandler.h"
     17 #include "glsl/GrGLSLXferProcessor.h"
     18 
     19 class CoverageSetOpXP : public GrXferProcessor {
     20 public:
     21     static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
     22         return new CoverageSetOpXP(regionOp, invertCoverage);
     23     }
     24 
     25     ~CoverageSetOpXP() override;
     26 
     27     const char* name() const override { return "Coverage Set Op"; }
     28 
     29     GrGLSLXferProcessor* createGLSLInstance() const override;
     30 
     31     bool invertCoverage() const { return fInvertCoverage; }
     32 
     33 private:
     34     CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
     35 
     36     GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override;
     37 
     38     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
     39 
     40     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
     41 
     42     bool onIsEqual(const GrXferProcessor& xpBase) const override {
     43         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
     44         return (fRegionOp == xp.fRegionOp &&
     45                 fInvertCoverage == xp.fInvertCoverage);
     46     }
     47 
     48     SkRegion::Op fRegionOp;
     49     bool         fInvertCoverage;
     50 
     51     typedef GrXferProcessor INHERITED;
     52 };
     53 
     54 ///////////////////////////////////////////////////////////////////////////////
     55 
     56 class GLCoverageSetOpXP : public GrGLSLXferProcessor {
     57 public:
     58     GLCoverageSetOpXP(const GrProcessor&) {}
     59 
     60     ~GLCoverageSetOpXP() override {}
     61 
     62     static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps,
     63                        GrProcessorKeyBuilder* b) {
     64         const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
     65         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
     66         b->add32(key);
     67     }
     68 
     69 private:
     70     void emitOutputsForBlendState(const EmitArgs& args) override {
     71         const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
     72         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
     73 
     74         if (xp.invertCoverage()) {
     75             fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
     76         } else {
     77             fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
     78         }
     79     }
     80 
     81     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
     82 
     83     typedef GrGLSLXferProcessor INHERITED;
     84 };
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 
     88 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
     89     : fRegionOp(regionOp)
     90     , fInvertCoverage(invertCoverage) {
     91     this->initClassID<CoverageSetOpXP>();
     92 }
     93 
     94 CoverageSetOpXP::~CoverageSetOpXP() {
     95 }
     96 
     97 void CoverageSetOpXP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
     98                                             GrProcessorKeyBuilder* b) const {
     99     GLCoverageSetOpXP::GenKey(*this, caps, b);
    100 }
    101 
    102 GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
    103     return new GLCoverageSetOpXP(*this);
    104 }
    105 
    106 GrXferProcessor::OptFlags CoverageSetOpXP::onGetOptimizations(
    107         const FragmentProcessorAnalysis&) const {
    108     // We never look at the color input
    109     return GrXferProcessor::kIgnoreColor_OptFlag;
    110 }
    111 
    112 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
    113     switch (fRegionOp) {
    114         case SkRegion::kReplace_Op:
    115             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    116             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    117             break;
    118         case SkRegion::kIntersect_Op:
    119             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
    120             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    121             break;
    122         case SkRegion::kUnion_Op:
    123             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    124             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    125             break;
    126         case SkRegion::kXOR_Op:
    127             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    128             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    129             break;
    130         case SkRegion::kDifference_Op:
    131             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
    132             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    133             break;
    134         case SkRegion::kReverseDifference_Op:
    135             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    136             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    137             break;
    138     }
    139     blendInfo->fBlendConstant = 0;
    140 }
    141 
    142 ///////////////////////////////////////////////////////////////////////////////
    143 
    144 constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
    145                                                              bool invertCoverage)
    146         : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
    147 
    148 const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) {
    149     // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are
    150     // null.
    151 #ifdef SK_BUILD_FOR_WIN
    152 #define _CONSTEXPR_
    153 #else
    154 #define _CONSTEXPR_ constexpr
    155 #endif
    156     switch (regionOp) {
    157         case SkRegion::kReplace_Op: {
    158             if (invertCoverage) {
    159                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPFI(
    160                         SkRegion::kReplace_Op, true);
    161                 return &gReplaceCDXPFI;
    162             } else {
    163                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gReplaceCDXPF(
    164                         SkRegion::kReplace_Op, false);
    165                 return &gReplaceCDXPF;
    166             }
    167         }
    168         case SkRegion::kIntersect_Op: {
    169             if (invertCoverage) {
    170                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPFI(
    171                         SkRegion::kIntersect_Op, true);
    172                 return &gIntersectCDXPFI;
    173             } else {
    174                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gIntersectCDXPF(
    175                         SkRegion::kIntersect_Op, false);
    176                 return &gIntersectCDXPF;
    177             }
    178         }
    179         case SkRegion::kUnion_Op: {
    180             if (invertCoverage) {
    181                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op,
    182                                                                                true);
    183                 return &gUnionCDXPFI;
    184             } else {
    185                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op,
    186                                                                               false);
    187                 return &gUnionCDXPF;
    188             }
    189         }
    190         case SkRegion::kXOR_Op: {
    191             if (invertCoverage) {
    192                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op,
    193                                                                              true);
    194                 return &gXORCDXPFI;
    195             } else {
    196                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op,
    197                                                                             false);
    198                 return &gXORCDXPF;
    199             }
    200         }
    201         case SkRegion::kDifference_Op: {
    202             if (invertCoverage) {
    203                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPFI(
    204                         SkRegion::kDifference_Op, true);
    205                 return &gDifferenceCDXPFI;
    206             } else {
    207                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gDifferenceCDXPF(
    208                         SkRegion::kDifference_Op, false);
    209                 return &gDifferenceCDXPF;
    210             }
    211         }
    212         case SkRegion::kReverseDifference_Op: {
    213             if (invertCoverage) {
    214                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPFI(
    215                         SkRegion::kReverseDifference_Op, true);
    216                 return &gRevDiffCDXPFI;
    217             } else {
    218                 static _CONSTEXPR_ const GrCoverageSetOpXPFactory gRevDiffCDXPF(
    219                         SkRegion::kReverseDifference_Op, false);
    220                 return &gRevDiffCDXPF;
    221             }
    222         }
    223     }
    224 #undef _CONSTEXPR_
    225     SkFAIL("Unknown region op.");
    226     return nullptr;
    227 }
    228 
    229 GrXferProcessor* GrCoverageSetOpXPFactory::onCreateXferProcessor(
    230         const GrCaps& caps,
    231         const FragmentProcessorAnalysis& analysis,
    232         bool hasMixedSamples,
    233         const DstTexture* dst) const {
    234     // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
    235     // the future, however we could at some point make this work using an inverted coverage
    236     // modulation table. Note that an inverted table still won't work if there are coverage procs.
    237     if (fInvertCoverage && hasMixedSamples) {
    238         SkASSERT(false);
    239         return nullptr;
    240     }
    241 
    242     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
    243 }
    244 
    245 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
    246 
    247 #if GR_TEST_UTILS
    248 const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) {
    249     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
    250     bool invertCoverage = !d->fRenderTargetContext->hasMixedSamples() && d->fRandom->nextBool();
    251     return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage);
    252 }
    253 #endif
    254