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 "src/gpu/effects/GrCoverageSetOpXP.h" 9 10#include "src/gpu/GrCaps.h" 11#include "src/gpu/GrColor.h" 12#include "src/gpu/GrPipeline.h" 13#include "src/gpu/GrXferProcessor.h" 14#include "src/gpu/glsl/GrGLSLBlend.h" 15#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 16#include "src/gpu/glsl/GrGLSLUniformHandler.h" 17 18class CoverageSetOpXP : public GrXferProcessor { 19public: 20 CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage) 21 : INHERITED(kCoverageSetOpXP_ClassID) 22 , fRegionOp(regionOp) 23 , fInvertCoverage(invertCoverage) {} 24 25 const char* name() const override { return "Coverage Set Op"; } 26 27 SkString getShaderDfxInfo() const override; 28 29 std::unique_ptr<ProgramImpl> makeProgramImpl() const override; 30 31private: 32 void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 33 34 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override; 35 36 bool onIsEqual(const GrXferProcessor& xpBase) const override { 37 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>(); 38 return (fRegionOp == xp.fRegionOp && 39 fInvertCoverage == xp.fInvertCoverage); 40 } 41 42 SkRegion::Op fRegionOp; 43 bool fInvertCoverage; 44 45 using INHERITED = GrXferProcessor; 46}; 47 48SkString CoverageSetOpXP::getShaderDfxInfo() const 49{ 50 SkString format; 51 format.printf("ShaderDfx_CoverageSetOpXP_%d", fInvertCoverage); 52 return format; 53} 54 55void CoverageSetOpXP::onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { 56 b->addBool(fInvertCoverage, "invert coverage"); 57} 58 59std::unique_ptr<GrXferProcessor::ProgramImpl> CoverageSetOpXP::makeProgramImpl() const { 60 class Impl : public ProgramImpl { 61 private: 62 void emitOutputsForBlendState(const EmitArgs& args) override { 63 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>(); 64 GrGLSLXPFragmentBuilder* fb = args.fXPFragBuilder; 65 if (xp.fInvertCoverage) { 66 fb->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage); 67 } else { 68 fb->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); 69 } 70 } 71 }; 72 return std::make_unique<Impl>(); 73} 74 75void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const { 76 switch (fRegionOp) { 77 case SkRegion::kReplace_Op: 78 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 79 blendInfo->fDstBlend = kZero_GrBlendCoeff; 80 break; 81 case SkRegion::kIntersect_Op: 82 blendInfo->fSrcBlend = kDC_GrBlendCoeff; 83 blendInfo->fDstBlend = kZero_GrBlendCoeff; 84 break; 85 case SkRegion::kUnion_Op: 86 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 87 blendInfo->fDstBlend = kISC_GrBlendCoeff; 88 break; 89 case SkRegion::kXOR_Op: 90 blendInfo->fSrcBlend = kIDC_GrBlendCoeff; 91 blendInfo->fDstBlend = kISC_GrBlendCoeff; 92 break; 93 case SkRegion::kDifference_Op: 94 blendInfo->fSrcBlend = kZero_GrBlendCoeff; 95 blendInfo->fDstBlend = kISC_GrBlendCoeff; 96 break; 97 case SkRegion::kReverseDifference_Op: 98 blendInfo->fSrcBlend = kIDC_GrBlendCoeff; 99 blendInfo->fDstBlend = kZero_GrBlendCoeff; 100 break; 101 } 102 blendInfo->fBlendConstant = SK_PMColor4fTRANSPARENT; 103} 104 105/////////////////////////////////////////////////////////////////////////////// 106 107constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, 108 bool invertCoverage) 109 : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {} 110 111const GrXPFactory* GrCoverageSetOpXPFactory::Get(SkRegion::Op regionOp, bool invertCoverage) { 112 switch (regionOp) { 113 case SkRegion::kReplace_Op: { 114 if (invertCoverage) { 115 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPFI( 116 SkRegion::kReplace_Op, true); 117 return &gReplaceCDXPFI; 118 } else { 119 static constexpr const GrCoverageSetOpXPFactory gReplaceCDXPF(SkRegion::kReplace_Op, 120 false); 121 return &gReplaceCDXPF; 122 } 123 } 124 case SkRegion::kIntersect_Op: { 125 if (invertCoverage) { 126 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPFI( 127 SkRegion::kIntersect_Op, true); 128 return &gIntersectCDXPFI; 129 } else { 130 static constexpr const GrCoverageSetOpXPFactory gIntersectCDXPF( 131 SkRegion::kIntersect_Op, false); 132 return &gIntersectCDXPF; 133 } 134 } 135 case SkRegion::kUnion_Op: { 136 if (invertCoverage) { 137 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPFI(SkRegion::kUnion_Op, 138 true); 139 return &gUnionCDXPFI; 140 } else { 141 static constexpr const GrCoverageSetOpXPFactory gUnionCDXPF(SkRegion::kUnion_Op, 142 false); 143 return &gUnionCDXPF; 144 } 145 } 146 case SkRegion::kXOR_Op: { 147 if (invertCoverage) { 148 static constexpr const GrCoverageSetOpXPFactory gXORCDXPFI(SkRegion::kXOR_Op, true); 149 return &gXORCDXPFI; 150 } else { 151 static constexpr const GrCoverageSetOpXPFactory gXORCDXPF(SkRegion::kXOR_Op, false); 152 return &gXORCDXPF; 153 } 154 } 155 case SkRegion::kDifference_Op: { 156 if (invertCoverage) { 157 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPFI( 158 SkRegion::kDifference_Op, true); 159 return &gDifferenceCDXPFI; 160 } else { 161 static constexpr const GrCoverageSetOpXPFactory gDifferenceCDXPF( 162 SkRegion::kDifference_Op, false); 163 return &gDifferenceCDXPF; 164 } 165 } 166 case SkRegion::kReverseDifference_Op: { 167 if (invertCoverage) { 168 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPFI( 169 SkRegion::kReverseDifference_Op, true); 170 return &gRevDiffCDXPFI; 171 } else { 172 static constexpr const GrCoverageSetOpXPFactory gRevDiffCDXPF( 173 SkRegion::kReverseDifference_Op, false); 174 return &gRevDiffCDXPF; 175 } 176 } 177 } 178 SK_ABORT("Unknown region op."); 179} 180 181sk_sp<const GrXferProcessor> GrCoverageSetOpXPFactory::makeXferProcessor( 182 const GrProcessorAnalysisColor&, 183 GrProcessorAnalysisCoverage, 184 const GrCaps& caps, 185 GrClampType) const { 186 return sk_sp<GrXferProcessor>(new CoverageSetOpXP(fRegionOp, fInvertCoverage)); 187} 188 189GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory); 190 191#if GR_TEST_UTILS 192const GrXPFactory* GrCoverageSetOpXPFactory::TestGet(GrProcessorTestData* d) { 193 SkRegion::Op regionOp = SkRegion::Op(d->fRandom->nextULessThan(SkRegion::kLastOp + 1)); 194 bool invertCoverage = d->fRandom->nextBool(); 195 return GrCoverageSetOpXPFactory::Get(regionOp, invertCoverage); 196} 197#endif 198