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 "GrCaps.h"
     11 #include "GrColor.h"
     12 #include "GrPipeline.h"
     13 #include "GrProcessor.h"
     14 #include "GrProcOptInfo.h"
     15 #include "glsl/GrGLSLBlend.h"
     16 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     17 #include "glsl/GrGLSLUniformHandler.h"
     18 #include "glsl/GrGLSLXferProcessor.h"
     19 
     20 class CoverageSetOpXP : public GrXferProcessor {
     21 public:
     22     static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
     23         return new CoverageSetOpXP(regionOp, invertCoverage);
     24     }
     25 
     26     ~CoverageSetOpXP() override;
     27 
     28     const char* name() const override { return "Coverage Set Op"; }
     29 
     30     GrGLSLXferProcessor* createGLSLInstance() const override;
     31 
     32     bool invertCoverage() const { return fInvertCoverage; }
     33 
     34 private:
     35     CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
     36 
     37     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations,
     38                                                  bool doesStencilWrite,
     39                                                  GrColor* color,
     40                                                  const GrCaps& caps) const override;
     41 
     42     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
     43 
     44     void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override;
     45 
     46     bool onIsEqual(const GrXferProcessor& xpBase) const override {
     47         const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>();
     48         return (fRegionOp == xp.fRegionOp &&
     49                 fInvertCoverage == xp.fInvertCoverage);
     50     }
     51 
     52     SkRegion::Op fRegionOp;
     53     bool         fInvertCoverage;
     54 
     55     typedef GrXferProcessor INHERITED;
     56 };
     57 
     58 ///////////////////////////////////////////////////////////////////////////////
     59 
     60 class GLCoverageSetOpXP : public GrGLSLXferProcessor {
     61 public:
     62     GLCoverageSetOpXP(const GrProcessor&) {}
     63 
     64     ~GLCoverageSetOpXP() override {}
     65 
     66     static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps,
     67                        GrProcessorKeyBuilder* b) {
     68         const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>();
     69         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
     70         b->add32(key);
     71     };
     72 
     73 private:
     74     void emitOutputsForBlendState(const EmitArgs& args) override {
     75         const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>();
     76         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
     77 
     78         if (xp.invertCoverage()) {
     79             fragBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
     80         } else {
     81             fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
     82         }
     83     }
     84 
     85     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {};
     86 
     87     typedef GrGLSLXferProcessor INHERITED;
     88 };
     89 
     90 ///////////////////////////////////////////////////////////////////////////////
     91 
     92 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
     93     : fRegionOp(regionOp)
     94     , fInvertCoverage(invertCoverage) {
     95     this->initClassID<CoverageSetOpXP>();
     96 }
     97 
     98 CoverageSetOpXP::~CoverageSetOpXP() {
     99 }
    100 
    101 void CoverageSetOpXP::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
    102                                             GrProcessorKeyBuilder* b) const {
    103     GLCoverageSetOpXP::GenKey(*this, caps, b);
    104 }
    105 
    106 GrGLSLXferProcessor* CoverageSetOpXP::createGLSLInstance() const {
    107     return new GLCoverageSetOpXP(*this);
    108 }
    109 
    110 GrXferProcessor::OptFlags
    111 CoverageSetOpXP::onGetOptimizations(const GrPipelineOptimizations& optimizations,
    112                                     bool doesStencilWrite,
    113                                     GrColor* color,
    114                                     const GrCaps& caps) const {
    115     // We never look at the color input
    116     return GrXferProcessor::kIgnoreColor_OptFlag;
    117 }
    118 
    119 void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
    120     switch (fRegionOp) {
    121         case SkRegion::kReplace_Op:
    122             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    123             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    124             break;
    125         case SkRegion::kIntersect_Op:
    126             blendInfo->fSrcBlend = kDC_GrBlendCoeff;
    127             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    128             break;
    129         case SkRegion::kUnion_Op:
    130             blendInfo->fSrcBlend = kOne_GrBlendCoeff;
    131             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    132             break;
    133         case SkRegion::kXOR_Op:
    134             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    135             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    136             break;
    137         case SkRegion::kDifference_Op:
    138             blendInfo->fSrcBlend = kZero_GrBlendCoeff;
    139             blendInfo->fDstBlend = kISC_GrBlendCoeff;
    140             break;
    141         case SkRegion::kReverseDifference_Op:
    142             blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
    143             blendInfo->fDstBlend = kZero_GrBlendCoeff;
    144             break;
    145     }
    146     blendInfo->fBlendConstant = 0;
    147 }
    148 
    149 ///////////////////////////////////////////////////////////////////////////////
    150 
    151 class ShaderCSOXferProcessor : public GrXferProcessor {
    152 public:
    153     ShaderCSOXferProcessor(const DstTexture* dstTexture,
    154                            bool hasMixedSamples,
    155                            SkRegion::Op regionOp,
    156                            bool invertCoverage)
    157         : INHERITED(dstTexture, true, hasMixedSamples)
    158         , fRegionOp(regionOp)
    159         , fInvertCoverage(invertCoverage) {
    160         this->initClassID<ShaderCSOXferProcessor>();
    161     }
    162 
    163     const char* name() const override { return "Coverage Set Op Shader"; }
    164 
    165     GrGLSLXferProcessor* createGLSLInstance() const override;
    166 
    167     SkRegion::Op regionOp() const { return fRegionOp; }
    168     bool invertCoverage() const { return fInvertCoverage; }
    169 
    170 private:
    171     GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
    172                                                  const GrCaps&) const override {
    173         // We never look at the color input
    174         return GrXferProcessor::kIgnoreColor_OptFlag;
    175     }
    176 
    177     void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
    178 
    179     bool onIsEqual(const GrXferProcessor& xpBase) const override {
    180         const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
    181         return (fRegionOp == xp.fRegionOp &&
    182                 fInvertCoverage == xp.fInvertCoverage);
    183     }
    184 
    185     SkRegion::Op fRegionOp;
    186     bool         fInvertCoverage;
    187 
    188     typedef GrXferProcessor INHERITED;
    189 };
    190 
    191 ///////////////////////////////////////////////////////////////////////////////
    192 
    193 class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
    194 public:
    195     static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
    196         const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
    197         b->add32(xp.regionOp());
    198         uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
    199         b->add32(key);
    200     }
    201 
    202 private:
    203     void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
    204                                  GrGLSLUniformHandler* uniformHandler,
    205                                  const char* srcColor,
    206                                  const char* srcCoverage,
    207                                  const char* dstColor,
    208                                  const char* outColor,
    209                                  const char* outColorSecondary,
    210                                  const GrXferProcessor& proc) override {
    211         const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
    212 
    213         if (xp.invertCoverage()) {
    214             fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
    215         } else {
    216             fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
    217         }
    218 
    219         GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
    220     }
    221 
    222     void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
    223 
    224     typedef GrGLSLXferProcessor INHERITED;
    225 };
    226 
    227 ///////////////////////////////////////////////////////////////////////////////
    228 
    229 void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
    230                                                    GrProcessorKeyBuilder* b) const {
    231     GLShaderCSOXferProcessor::GenKey(*this, b);
    232 }
    233 
    234 GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
    235     return new GLShaderCSOXferProcessor;
    236 }
    237 
    238 ///////////////////////////////////////////////////////////////////////////////
    239 //
    240 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
    241     : fRegionOp(regionOp)
    242     , fInvertCoverage(invertCoverage) {
    243     this->initClassID<GrCoverageSetOpXPFactory>();
    244 }
    245 
    246 GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
    247     switch (regionOp) {
    248         case SkRegion::kReplace_Op: {
    249             if (invertCoverage) {
    250                 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
    251                 return SkRef(&gReplaceCDXPFI);
    252             } else {
    253                 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
    254                 return SkRef(&gReplaceCDXPF);
    255             }
    256             break;
    257         }
    258         case SkRegion::kIntersect_Op: {
    259             if (invertCoverage) {
    260                 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
    261                 return SkRef(&gIntersectCDXPFI);
    262             } else {
    263                 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
    264                 return SkRef(&gIntersectCDXPF);
    265             }
    266             break;
    267         }
    268         case SkRegion::kUnion_Op: {
    269             if (invertCoverage) {
    270                 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
    271                 return SkRef(&gUnionCDXPFI);
    272             } else {
    273                 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
    274                 return SkRef(&gUnionCDXPF);
    275             }
    276             break;
    277         }
    278         case SkRegion::kXOR_Op: {
    279             if (invertCoverage) {
    280                 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
    281                 return SkRef(&gXORCDXPFI);
    282             } else {
    283                 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
    284                 return SkRef(&gXORCDXPF);
    285             }
    286             break;
    287         }
    288         case SkRegion::kDifference_Op: {
    289             if (invertCoverage) {
    290                 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
    291                 return SkRef(&gDifferenceCDXPFI);
    292             } else {
    293                 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
    294                 return SkRef(&gDifferenceCDXPF);
    295             }
    296             break;
    297         }
    298         case SkRegion::kReverseDifference_Op: {
    299             if (invertCoverage) {
    300                 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
    301                 return SkRef(&gRevDiffCDXPFI);
    302             } else {
    303                 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
    304                 return SkRef(&gRevDiffCDXPF);
    305             }
    306             break;
    307         }
    308         default:
    309             return nullptr;
    310     }
    311 }
    312 
    313 GrXferProcessor*
    314 GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrCaps& caps,
    315                                                 const GrPipelineOptimizations& optimizations,
    316                                                 bool hasMixedSamples,
    317                                                 const DstTexture* dst) const {
    318     // We don't support inverting coverage with mixed samples. We don't expect to ever want this in
    319     // the future, however we could at some point make this work using an inverted coverage
    320     // modulation table. Note that an inverted table still won't work if there are coverage procs.
    321     if (fInvertCoverage && hasMixedSamples) {
    322         SkASSERT(false);
    323         return nullptr;
    324     }
    325 
    326     if (optimizations.fOverrides.fUsePLSDstRead) {
    327         return new ShaderCSOXferProcessor(dst, hasMixedSamples, fRegionOp, fInvertCoverage);
    328     }
    329     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
    330 }
    331 
    332 void GrCoverageSetOpXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI,
    333                                                         InvariantBlendedColor* blendedColor) const {
    334     blendedColor->fWillBlendWithDst = SkRegion::kReplace_Op != fRegionOp;
    335     blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
    336 }
    337 
    338 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
    339 
    340 const GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(GrProcessorTestData* d) {
    341     SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1));
    342     bool invertCoverage = !d->fRenderTarget->hasMixedSamples() && d->fRandom->nextBool();
    343     return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
    344 }
    345 
    346