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 = SK_PMColor4fTRANSPARENT; 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 GrClampType) 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