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 18 class CoverageSetOpXP : public GrXferProcessor { 19 public: 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 34 private: 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 61 class GLCoverageSetOpXP : public GrGLXferProcessor { 62 public: 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 74 private: 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 93 CoverageSetOpXP::CoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage) 94 : fRegionOp(regionOp) 95 , fInvertCoverage(invertCoverage) { 96 this->initClassID<CoverageSetOpXP>(); 97 } 98 99 CoverageSetOpXP::~CoverageSetOpXP() { 100 } 101 102 void CoverageSetOpXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const { 103 GLCoverageSetOpXP::GenKey(*this, caps, b); 104 } 105 106 GrGLXferProcessor* CoverageSetOpXP::createGLInstance() const { 107 return SkNEW_ARGS(GLCoverageSetOpXP, (*this)); 108 } 109 110 GrXferProcessor::OptFlags 111 CoverageSetOpXP::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 120 void 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 152 GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) 153 : fRegionOp(regionOp) 154 , fInvertCoverage(invertCoverage) { 155 this->initClassID<GrCoverageSetOpXPFactory>(); 156 } 157 158 GrXPFactory* 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 225 GrXferProcessor* 226 GrCoverageSetOpXPFactory::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 233 void 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 251 GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory); 252 253 GrXPFactory* 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