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 "GrColor.h" 11#include "GrDrawTargetCaps.h" 12#include "GrProcessor.h" 13#include "GrProcOptInfo.h" 14#include "gl/GrGLXferProcessor.h" 15#include "gl/builders/GrGLFragmentShaderBuilder.h" 16#include "gl/builders/GrGLProgramBuilder.h" 17 18class CoverageSetOpXP : public GrXferProcessor { 19public: 20 static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) { 21 return SkNEW_ARGS(CoverageSetOpXP, (regionOp, invertCoverage)); 22 } 23 24 ~CoverageSetOpXP() override; 25 26 const char* name() const override { return "Coverage Set Op"; } 27 28 GrGLXferProcessor* createGLInstance() const override; 29 30 bool hasSecondaryOutput() const override { return false; } 31 32 bool invertCoverage() const { return fInvertCoverage; } 33 34private: 35 CoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage); 36 37 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 38 const GrProcOptInfo& coveragePOI, 39 bool doesStencilWrite, 40 GrColor* color, 41 const GrDrawTargetCaps& caps) override; 42 43 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 44 45 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override; 46 47 bool onIsEqual(const GrXferProcessor& xpBase) const override { 48 const CoverageSetOpXP& xp = xpBase.cast<CoverageSetOpXP>(); 49 return (fRegionOp == xp.fRegionOp && 50 fInvertCoverage == xp.fInvertCoverage); 51 } 52 53 SkRegion::Op fRegionOp; 54 bool fInvertCoverage; 55 56 typedef GrXferProcessor INHERITED; 57}; 58 59/////////////////////////////////////////////////////////////////////////////// 60 61class GLCoverageSetOpXP : public GrGLXferProcessor { 62public: 63 GLCoverageSetOpXP(const GrProcessor&) {} 64 65 ~GLCoverageSetOpXP() override {} 66 67 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, 68 GrProcessorKeyBuilder* b) { 69 const CoverageSetOpXP& xp = processor.cast<CoverageSetOpXP>(); 70 uint32_t key = xp.invertCoverage() ? 0x0 : 0x1; 71 b->add32(key); 72 }; 73 74private: 75 void onEmitCode(const EmitArgs& args) override { 76 const CoverageSetOpXP& xp = args.fXP.cast<CoverageSetOpXP>(); 77 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); 78 79 if (xp.invertCoverage()) { 80 fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage); 81 } else { 82 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); 83 } 84 } 85 86 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) override {}; 87 88 typedef GrGLXferProcessor INHERITED; 89}; 90 91/////////////////////////////////////////////////////////////////////////////// 92 93CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage) 94 : fRegionOp(regionOp) 95 , fInvertCoverage(invertCoverage) { 96 this->initClassID<CoverageSetOpXP>(); 97} 98 99CoverageSetOpXP::~CoverageSetOpXP() { 100} 101 102void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 103 GLCoverageSetOpXP::GenKey(*this, caps, b); 104} 105 106GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const { 107 return SkNEW_ARGS(GLCoverageSetOpXP, (*this)); 108} 109 110GrXferProcessor::OptFlags 111CoverageSetOpXP::onGetOptimizations(const GrProcOptInfo& colorPOI, 112 const GrProcOptInfo& coveragePOI, 113 bool doesStencilWrite, 114 GrColor* color, 115 const GrDrawTargetCaps& caps) { 116 // We never look at the color input 117 return GrXferProcessor::kIgnoreColor_OptFlag; 118} 119 120void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const { 121 switch (fRegionOp) { 122 case SkRegion::kReplace_Op: 123 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 124 blendInfo->fDstBlend = kZero_GrBlendCoeff; 125 break; 126 case SkRegion::kIntersect_Op: 127 blendInfo->fSrcBlend = kDC_GrBlendCoeff; 128 blendInfo->fDstBlend = kZero_GrBlendCoeff; 129 break; 130 case SkRegion::kUnion_Op: 131 blendInfo->fSrcBlend = kOne_GrBlendCoeff; 132 blendInfo->fDstBlend = kISC_GrBlendCoeff; 133 break; 134 case SkRegion::kXOR_Op: 135 blendInfo->fSrcBlend = kIDC_GrBlendCoeff; 136 blendInfo->fDstBlend = kISC_GrBlendCoeff; 137 break; 138 case SkRegion::kDifference_Op: 139 blendInfo->fSrcBlend = kZero_GrBlendCoeff; 140 blendInfo->fDstBlend = kISC_GrBlendCoeff; 141 break; 142 case SkRegion::kReverseDifference_Op: 143 blendInfo->fSrcBlend = kIDC_GrBlendCoeff; 144 blendInfo->fDstBlend = kZero_GrBlendCoeff; 145 break; 146 } 147 blendInfo->fBlendConstant = 0; 148} 149 150/////////////////////////////////////////////////////////////////////////////// 151 152GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) 153 : fRegionOp(regionOp) 154 , fInvertCoverage(invertCoverage) { 155 this->initClassID<GrCoverageSetOpXPFactory>(); 156} 157 158GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) { 159 switch (regionOp) { 160 case SkRegion::kReplace_Op: { 161 if (invertCoverage) { 162 static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage); 163 return SkRef(&gReplaceCDXPFI); 164 } else { 165 static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage); 166 return SkRef(&gReplaceCDXPF); 167 } 168 break; 169 } 170 case SkRegion::kIntersect_Op: { 171 if (invertCoverage) { 172 static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage); 173 return SkRef(&gIntersectCDXPFI); 174 } else { 175 static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage); 176 return SkRef(&gIntersectCDXPF); 177 } 178 break; 179 } 180 case SkRegion::kUnion_Op: { 181 if (invertCoverage) { 182 static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage); 183 return SkRef(&gUnionCDXPFI); 184 } else { 185 static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage); 186 return SkRef(&gUnionCDXPF); 187 } 188 break; 189 } 190 case SkRegion::kXOR_Op: { 191 if (invertCoverage) { 192 static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage); 193 return SkRef(&gXORCDXPFI); 194 } else { 195 static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage); 196 return SkRef(&gXORCDXPF); 197 } 198 break; 199 } 200 case SkRegion::kDifference_Op: { 201 if (invertCoverage) { 202 static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage); 203 return SkRef(&gDifferenceCDXPFI); 204 } else { 205 static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage); 206 return SkRef(&gDifferenceCDXPF); 207 } 208 break; 209 } 210 case SkRegion::kReverseDifference_Op: { 211 if (invertCoverage) { 212 static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage); 213 return SkRef(&gRevDiffCDXPFI); 214 } else { 215 static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage); 216 return SkRef(&gRevDiffCDXPF); 217 } 218 break; 219 } 220 default: 221 return NULL; 222 } 223} 224 225GrXferProcessor* 226GrCoverageSetOpXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, 227 const GrProcOptInfo& colorPOI, 228 const GrProcOptInfo& covPOI, 229 const GrDeviceCoordTexture* dstCopy) const { 230 return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage); 231} 232 233void GrCoverageSetOpXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, 234 const GrProcOptInfo& coveragePOI, 235 GrXPFactory::InvariantOutput* output) const { 236 if (SkRegion::kReplace_Op == fRegionOp) { 237 if (coveragePOI.isSolidWhite()) { 238 output->fBlendedColor = GrColor_WHITE; 239 output->fBlendedColorFlags = kRGBA_GrColorComponentFlags; 240 } else { 241 output->fBlendedColorFlags = 0; 242 } 243 244 output->fWillBlendWithDst = false; 245 } else { 246 output->fBlendedColorFlags = 0; 247 output->fWillBlendWithDst = true; 248 } 249} 250 251GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory); 252 253GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random, 254 GrContext*, 255 const GrDrawTargetCaps&, 256 GrTexture*[]) { 257 SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1)); 258 bool invertCoverage = random->nextBool(); 259 return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage); 260} 261 262