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