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