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/GrPorterDuffXferProcessor.h" 9 10 #include "GrBlend.h" 11 #include "GrCaps.h" 12 #include "GrPipeline.h" 13 #include "GrProcessor.h" 14 #include "GrProcessorAnalysis.h" 15 #include "GrTypes.h" 16 #include "GrXferProcessor.h" 17 #include "SkTo.h" 18 #include "glsl/GrGLSLBlend.h" 19 #include "glsl/GrGLSLFragmentShaderBuilder.h" 20 #include "glsl/GrGLSLProgramDataManager.h" 21 #include "glsl/GrGLSLUniformHandler.h" 22 #include "glsl/GrGLSLXferProcessor.h" 23 24 /** 25 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 26 */ 27 class BlendFormula { 28 public: 29 /** 30 * Values the shader can write to primary and secondary outputs. These must all be modulated by 31 * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage. 32 */ 33 enum OutputType { 34 kNone_OutputType, //<! 0 35 kCoverage_OutputType, //<! inputCoverage 36 kModulate_OutputType, //<! inputColor * inputCoverage 37 kSAModulate_OutputType, //<! inputColor.a * inputCoverage 38 kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage 39 kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage 40 41 kLast_OutputType = kISCModulate_OutputType 42 }; 43 44 BlendFormula() = default; 45 46 constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation, 47 GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) 48 : fPrimaryOutputType(primaryOut) 49 , fSecondaryOutputType(secondaryOut) 50 , fBlendEquation(equation) 51 , fSrcCoeff(srcCoeff) 52 , fDstCoeff(dstCoeff) 53 , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {} 54 55 BlendFormula& operator=(const BlendFormula& other) { 56 SkDEBUGCODE(other.validatePreoptimized()); 57 fData = other.fData; 58 return *this; 59 } 60 61 bool operator==(const BlendFormula& other) const { 62 SkDEBUGCODE(this->validatePreoptimized()); 63 SkDEBUGCODE(other.validatePreoptimized()); 64 return fData == other.fData; 65 } 66 67 bool hasSecondaryOutput() const { 68 SkDEBUGCODE(this->validatePreoptimized()); 69 return kNone_OutputType != fSecondaryOutputType; 70 } 71 bool modifiesDst() const { 72 SkDEBUGCODE(this->validatePreoptimized()); 73 return SkToBool(fProps & kModifiesDst_Property); 74 } 75 bool usesDstColor() const { 76 SkDEBUGCODE(this->validatePreoptimized()); 77 return SkToBool(fProps & kUsesDstColor_Property); 78 } 79 bool usesInputColor() const { 80 SkDEBUGCODE(this->validatePreoptimized()); 81 return SkToBool(fProps & kUsesInputColor_Property); 82 } 83 bool canTweakAlphaForCoverage() const { 84 SkDEBUGCODE(this->validatePreoptimized()); 85 return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); 86 } 87 88 GrBlendEquation equation() const { 89 SkDEBUGCODE(this->validatePreoptimized()); 90 return fBlendEquation; 91 } 92 93 GrBlendCoeff srcCoeff() const { 94 SkDEBUGCODE(this->validatePreoptimized()); 95 return fSrcCoeff; 96 } 97 98 GrBlendCoeff dstCoeff() const { 99 SkDEBUGCODE(this->validatePreoptimized()); 100 return fDstCoeff; 101 } 102 103 OutputType primaryOutput() const { 104 SkDEBUGCODE(this->validatePreoptimized()); 105 return fPrimaryOutputType; 106 } 107 108 OutputType secondaryOutput() const { 109 SkDEBUGCODE(this->validatePreoptimized()); 110 return fSecondaryOutputType; 111 } 112 113 private: 114 enum Properties { 115 kModifiesDst_Property = 1, 116 kUsesDstColor_Property = 1 << 1, 117 kUsesInputColor_Property = 1 << 2, 118 kCanTweakAlphaForCoverage_Property = 1 << 3, 119 120 kLast_Property = kCanTweakAlphaForCoverage_Property 121 }; 122 GR_DECL_BITFIELD_OPS_FRIENDS(Properties) 123 124 #ifdef SK_DEBUG 125 void validatePreoptimized() const { 126 // The provided formula should already be optimized before a BlendFormula is constructed. 127 // Preferably these asserts would be done statically in the constexpr constructor, but this 128 // is not allowed in C++11. 129 SkASSERT((kNone_OutputType == fPrimaryOutputType) == 130 !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff)); 131 SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff)); 132 SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff)); 133 SkASSERT(fPrimaryOutputType != fSecondaryOutputType || 134 kNone_OutputType == fPrimaryOutputType); 135 SkASSERT(kNone_OutputType != fPrimaryOutputType || 136 kNone_OutputType == fSecondaryOutputType); 137 } 138 #endif 139 140 /** 141 * Deduce the properties of a BlendFormula. 142 */ 143 static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut, 144 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, 145 GrBlendCoeff DstCoeff); 146 147 union { 148 struct { 149 // We allot the enums one more bit than they require because MSVC seems to sign-extend 150 // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) 151 OutputType fPrimaryOutputType : 4; 152 OutputType fSecondaryOutputType : 4; 153 GrBlendEquation fBlendEquation : 6; 154 GrBlendCoeff fSrcCoeff : 6; 155 GrBlendCoeff fDstCoeff : 6; 156 Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); 157 }; 158 uint32_t fData; 159 }; 160 161 GR_STATIC_ASSERT(kLast_OutputType < (1 << 3)); 162 GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5)); 163 GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5)); 164 GR_STATIC_ASSERT(kLast_Property < (1 << 6)); 165 }; 166 167 GR_STATIC_ASSERT(4 == sizeof(BlendFormula)); 168 169 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties); 170 171 constexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut, 172 OutputType SecondaryOut, 173 GrBlendEquation BlendEquation, 174 GrBlendCoeff SrcCoeff, 175 GrBlendCoeff DstCoeff) { 176 return static_cast<Properties>( 177 (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) | 178 (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) | 179 ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) || 180 (SecondaryOut >= kModulate_OutputType && 181 GrBlendCoeffRefsSrc2(DstCoeff)) 182 ? kUsesInputColor_Property 183 : 0) | // We assert later that SrcCoeff doesn't ref src2. 184 ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) && 185 kNone_OutputType == SecondaryOut && 186 GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff) 187 ? kCanTweakAlphaForCoverage_Property 188 : 0)); 189 } 190 191 /** 192 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard 193 * Porter Duff formula. 194 */ 195 static constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 196 // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none. 197 return (kZero_GrBlendCoeff == srcCoeff && 198 (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff)) 199 ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType, 200 kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff) 201 : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType, 202 kAdd_GrBlendEquation, srcCoeff, dstCoeff); 203 } 204 205 /** 206 * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in 207 * LCD dst-out. 208 */ 209 static constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 210 return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType, 211 kAdd_GrBlendEquation, srcCoeff, dstCoeff); 212 } 213 214 /** 215 * When there is coverage, the equation with f=coverage is: 216 * 217 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 218 * 219 * This can be rewritten as: 220 * 221 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) 222 * 223 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the 224 * HW dst coeff with IS2C. 225 * 226 * Xfer modes: dst-atop (Sa!=1) 227 */ 228 static constexpr BlendFormula MakeCoverageFormula( 229 BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) { 230 return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput, 231 kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff); 232 } 233 234 /** 235 * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: 236 * 237 * D' = f * D * dstCoeff + (1-f) * D 238 * 239 * This can be rewritten as: 240 * 241 * D' = D - D * [f * (1 - dstCoeff)] 242 * 243 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse 244 * subtract HW blend equation with coeffs of (DC, One). 245 * 246 * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) 247 */ 248 static constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula( 249 BlendFormula::OutputType oneMinusDstCoeffModulateOutput) { 250 return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType, 251 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff); 252 } 253 254 /** 255 * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: 256 * 257 * D' = f * S * srcCoeff + (1-f) * D 258 * 259 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff 260 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) 261 * 262 * Xfer modes (Sa!=1): src, src-in, src-out 263 */ 264 static constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) { 265 return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType, 266 kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff); 267 } 268 269 // Older GCC won't like the constexpr arrays because of 270 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484. 271 // MSVC 2015 crashes with an internal compiler error. 272 #if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910)) 273 # define MAYBE_CONSTEXPR const 274 #else 275 # define MAYBE_CONSTEXPR constexpr 276 #endif 277 278 /** 279 * This table outlines the blend formulas we will use with each xfermode, with and without coverage, 280 * with and without an opaque input color. Optimization properties are deduced at compile time so we 281 * can make runtime decisions quickly. RGB coverage is not supported. 282 */ 283 static MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = { 284 /*>> No coverage, input color unknown <<*/ {{ 285 286 /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 287 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 288 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 289 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 290 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 291 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 292 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff), 293 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 294 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 295 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 296 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kSA_GrBlendCoeff), 297 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 298 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 299 /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 300 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 301 302 }, /*>> Has coverage, input color unknown <<*/ { 303 304 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 305 /* src */ MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff), 306 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 307 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 308 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 309 /* src-in */ MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff), 310 /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 311 /* src-out */ MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff), 312 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 313 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 314 /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 315 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 316 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 317 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 318 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 319 320 }}, /*>> No coverage, input color opaque <<*/ {{ 321 322 /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 323 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 324 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 325 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), // see comment below 326 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 327 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 328 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 329 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 330 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 331 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 332 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 333 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 334 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 335 /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 336 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 337 338 }, /*>> Has coverage, input color opaque <<*/ { 339 340 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 341 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 342 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 343 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 344 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 345 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 346 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 347 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 348 /* dst-out */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 349 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 350 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 351 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 352 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 353 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 354 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 355 }}}; 356 // In the above table src-over is not optimized to src mode when the color is opaque because we 357 // found no advantage to doing so. Also, we are using a global src-over XP in most cases which is 358 // not specialized for opaque input. If the table were set to use the src formula then we'd have to 359 // change when we use this global XP to keep analysis and practice in sync. 360 361 static MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = { 362 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 363 /* src */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), 364 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 365 /* src-over */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff), 366 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 367 /* src-in */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff), 368 /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 369 /* src-out */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff), 370 /* dst-out */ MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff), 371 /* src-atop */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff), 372 /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 373 /* xor */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff), 374 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 375 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 376 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 377 }; 378 379 #undef MAYBE_CONSTEXPR 380 381 static BlendFormula get_blend_formula(bool isOpaque, 382 bool hasCoverage, 383 bool hasMixedSamples, 384 SkBlendMode xfermode) { 385 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 386 bool conflatesCoverage = hasCoverage || hasMixedSamples; 387 return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode]; 388 } 389 390 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) { 391 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 392 393 return gLCDBlendTable[(int)xfermode]; 394 } 395 396 /////////////////////////////////////////////////////////////////////////////// 397 398 class PorterDuffXferProcessor : public GrXferProcessor { 399 public: 400 PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage) 401 : INHERITED(kPorterDuffXferProcessor_ClassID, false, false, coverage) 402 , fBlendFormula(blendFormula) { 403 } 404 405 const char* name() const override { return "Porter Duff"; } 406 407 GrGLSLXferProcessor* createGLSLInstance() const override; 408 409 BlendFormula getBlendFormula() const { return fBlendFormula; } 410 411 private: 412 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 413 414 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } 415 416 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 417 blendInfo->fEquation = fBlendFormula.equation(); 418 blendInfo->fSrcBlend = fBlendFormula.srcCoeff(); 419 blendInfo->fDstBlend = fBlendFormula.dstCoeff(); 420 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 421 } 422 423 bool onIsEqual(const GrXferProcessor& xpBase) const override { 424 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); 425 return fBlendFormula == xp.fBlendFormula; 426 } 427 428 const BlendFormula fBlendFormula; 429 430 typedef GrXferProcessor INHERITED; 431 }; 432 433 /////////////////////////////////////////////////////////////////////////////// 434 435 static void append_color_output(const PorterDuffXferProcessor& xp, 436 GrGLSLXPFragmentBuilder* fragBuilder, 437 BlendFormula::OutputType outputType, const char* output, 438 const char* inColor, const char* inCoverage) { 439 SkASSERT(inCoverage); 440 SkASSERT(inColor); 441 switch (outputType) { 442 case BlendFormula::kNone_OutputType: 443 fragBuilder->codeAppendf("%s = half4(0.0);", output); 444 break; 445 case BlendFormula::kCoverage_OutputType: 446 // We can have a coverage formula while not reading coverage if there are mixed samples. 447 fragBuilder->codeAppendf("%s = %s;", output, inCoverage); 448 break; 449 case BlendFormula::kModulate_OutputType: 450 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); 451 break; 452 case BlendFormula::kSAModulate_OutputType: 453 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage); 454 break; 455 case BlendFormula::kISAModulate_OutputType: 456 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); 457 break; 458 case BlendFormula::kISCModulate_OutputType: 459 fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage); 460 break; 461 default: 462 SK_ABORT("Unsupported output type."); 463 break; 464 } 465 } 466 467 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor { 468 public: 469 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 470 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); 471 b->add32(xp.getBlendFormula().primaryOutput() | 472 (xp.getBlendFormula().secondaryOutput() << 3)); 473 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); 474 } 475 476 private: 477 void emitOutputsForBlendState(const EmitArgs& args) override { 478 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); 479 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 480 481 BlendFormula blendFormula = xp.getBlendFormula(); 482 if (blendFormula.hasSecondaryOutput()) { 483 append_color_output(xp, fragBuilder, blendFormula.secondaryOutput(), 484 args.fOutputSecondary, args.fInputColor, args.fInputCoverage); 485 } 486 append_color_output(xp, fragBuilder, blendFormula.primaryOutput(), args.fOutputPrimary, 487 args.fInputColor, args.fInputCoverage); 488 } 489 490 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 491 492 typedef GrGLSLXferProcessor INHERITED; 493 }; 494 495 /////////////////////////////////////////////////////////////////////////////// 496 497 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 498 GrProcessorKeyBuilder* b) const { 499 GLPorterDuffXferProcessor::GenKey(*this, b); 500 } 501 502 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { 503 return new GLPorterDuffXferProcessor; 504 } 505 506 /////////////////////////////////////////////////////////////////////////////// 507 508 class ShaderPDXferProcessor : public GrXferProcessor { 509 public: 510 ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode, 511 GrProcessorAnalysisCoverage coverage) 512 : INHERITED(kShaderPDXferProcessor_ClassID, true, hasMixedSamples, coverage) 513 , fXfermode(xfermode) { 514 } 515 516 const char* name() const override { return "Porter Duff Shader"; } 517 518 GrGLSLXferProcessor* createGLSLInstance() const override; 519 520 SkBlendMode getXfermode() const { return fXfermode; } 521 522 private: 523 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 524 525 bool onIsEqual(const GrXferProcessor& xpBase) const override { 526 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 527 return fXfermode == xp.fXfermode; 528 } 529 530 const SkBlendMode fXfermode; 531 532 typedef GrXferProcessor INHERITED; 533 }; 534 535 /////////////////////////////////////////////////////////////////////////////// 536 537 class GLShaderPDXferProcessor : public GrGLSLXferProcessor { 538 public: 539 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 540 const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>(); 541 b->add32((int)xp.getXfermode()); 542 } 543 544 private: 545 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 546 GrGLSLUniformHandler* uniformHandler, 547 const char* srcColor, 548 const char* srcCoverage, 549 const char* dstColor, 550 const char* outColor, 551 const char* outColorSecondary, 552 const GrXferProcessor& proc) override { 553 const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>(); 554 555 GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode()); 556 557 // Apply coverage. 558 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor, 559 outColorSecondary, xp); 560 } 561 562 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 563 564 typedef GrGLSLXferProcessor INHERITED; 565 }; 566 567 /////////////////////////////////////////////////////////////////////////////// 568 569 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 570 GrProcessorKeyBuilder* b) const { 571 GLShaderPDXferProcessor::GenKey(*this, b); 572 } 573 574 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const { 575 return new GLShaderPDXferProcessor; 576 } 577 578 /////////////////////////////////////////////////////////////////////////////// 579 580 class PDLCDXferProcessor : public GrXferProcessor { 581 public: 582 static sk_sp<const GrXferProcessor> Make(SkBlendMode mode, 583 const GrProcessorAnalysisColor& inputColor); 584 585 ~PDLCDXferProcessor() override; 586 587 const char* name() const override { return "Porter Duff LCD"; } 588 589 GrGLSLXferProcessor* createGLSLInstance() const override; 590 591 float alpha() const { return fAlpha; } 592 593 private: 594 PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha); 595 596 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 597 598 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 599 blendInfo->fSrcBlend = kConstC_GrBlendCoeff; 600 blendInfo->fDstBlend = kISC_GrBlendCoeff; 601 blendInfo->fBlendConstant = fBlendConstant; 602 } 603 604 bool onIsEqual(const GrXferProcessor& xpBase) const override { 605 const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>(); 606 if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) { 607 return false; 608 } 609 return true; 610 } 611 612 SkPMColor4f fBlendConstant; 613 float fAlpha; 614 615 typedef GrXferProcessor INHERITED; 616 }; 617 618 /////////////////////////////////////////////////////////////////////////////// 619 620 class GLPDLCDXferProcessor : public GrGLSLXferProcessor { 621 public: 622 GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_FloatNaN) {} 623 624 ~GLPDLCDXferProcessor() override {} 625 626 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps, 627 GrProcessorKeyBuilder* b) {} 628 629 private: 630 void emitOutputsForBlendState(const EmitArgs& args) override { 631 const char* alpha; 632 fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, 633 "alpha", &alpha); 634 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 635 // We want to force our primary output to be alpha * Coverage, where alpha is the alpha 636 // value of the src color. We know that there are no color stages (or we wouldn't have 637 // created this xp) and the r,g, and b channels of the op's input color are baked into the 638 // blend constant. 639 SkASSERT(args.fInputCoverage); 640 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage); 641 } 642 643 void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override { 644 float alpha = xp.cast<PDLCDXferProcessor>().alpha(); 645 if (fLastAlpha != alpha) { 646 pdm.set1f(fAlphaUniform, alpha); 647 fLastAlpha = alpha; 648 } 649 } 650 651 GrGLSLUniformHandler::UniformHandle fAlphaUniform; 652 float fLastAlpha; 653 typedef GrGLSLXferProcessor INHERITED; 654 }; 655 656 /////////////////////////////////////////////////////////////////////////////// 657 658 PDLCDXferProcessor::PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha) 659 : INHERITED(kPDLCDXferProcessor_ClassID, false, false, GrProcessorAnalysisCoverage::kLCD) 660 , fBlendConstant(blendConstant) 661 , fAlpha(alpha) { 662 } 663 664 sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode, 665 const GrProcessorAnalysisColor& color) { 666 if (SkBlendMode::kSrcOver != mode) { 667 return nullptr; 668 } 669 SkPMColor4f blendConstantPM; 670 if (!color.isConstant(&blendConstantPM)) { 671 return nullptr; 672 } 673 SkColor4f blendConstantUPM = blendConstantPM.unpremul(); 674 float alpha = blendConstantUPM.fA; 675 blendConstantPM = { blendConstantUPM.fR, blendConstantUPM.fG, blendConstantUPM.fB, 1 }; 676 return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstantPM, alpha)); 677 } 678 679 PDLCDXferProcessor::~PDLCDXferProcessor() { 680 } 681 682 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, 683 GrProcessorKeyBuilder* b) const { 684 GLPDLCDXferProcessor::GenKey(*this, caps, b); 685 } 686 687 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { 688 return new GLPDLCDXferProcessor(*this); 689 } 690 691 /////////////////////////////////////////////////////////////////////////////// 692 693 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) 694 : fBlendMode(xfermode) {} 695 696 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) { 697 SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode); 698 699 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are 700 // null. 701 #ifdef SK_BUILD_FOR_WIN 702 #define _CONSTEXPR_ 703 #else 704 #define _CONSTEXPR_ constexpr 705 #endif 706 static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear); 707 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc); 708 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst); 709 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver); 710 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver); 711 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn); 712 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn); 713 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut); 714 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut); 715 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop); 716 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop); 717 static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor); 718 static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus); 719 static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate); 720 static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen); 721 #undef _CONSTEXPR_ 722 723 switch (blendMode) { 724 case SkBlendMode::kClear: 725 return &gClearPDXPF; 726 case SkBlendMode::kSrc: 727 return &gSrcPDXPF; 728 case SkBlendMode::kDst: 729 return &gDstPDXPF; 730 case SkBlendMode::kSrcOver: 731 return &gSrcOverPDXPF; 732 case SkBlendMode::kDstOver: 733 return &gDstOverPDXPF; 734 case SkBlendMode::kSrcIn: 735 return &gSrcInPDXPF; 736 case SkBlendMode::kDstIn: 737 return &gDstInPDXPF; 738 case SkBlendMode::kSrcOut: 739 return &gSrcOutPDXPF; 740 case SkBlendMode::kDstOut: 741 return &gDstOutPDXPF; 742 case SkBlendMode::kSrcATop: 743 return &gSrcATopPDXPF; 744 case SkBlendMode::kDstATop: 745 return &gDstATopPDXPF; 746 case SkBlendMode::kXor: 747 return &gXorPDXPF; 748 case SkBlendMode::kPlus: 749 return &gPlusPDXPF; 750 case SkBlendMode::kModulate: 751 return &gModulatePDXPF; 752 case SkBlendMode::kScreen: 753 return &gScreenPDXPF; 754 default: 755 SK_ABORT("Unexpected blend mode."); 756 return nullptr; 757 } 758 } 759 760 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( 761 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 762 bool hasMixedSamples, const GrCaps& caps) const { 763 BlendFormula blendFormula; 764 bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD; 765 if (isLCD) { 766 // See comment in MakeSrcOverXferProcessor about color.isOpaque here 767 if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/ 768 !caps.shaderCaps()->dualSourceBlendingSupport() && 769 !caps.shaderCaps()->dstReadInShaderSupport()) { 770 // If we don't have dual source blending or in shader dst reads, we fall back to this 771 // trick for rendering SrcOver LCD text instead of doing a dst copy. 772 return PDLCDXferProcessor::Make(fBlendMode, color); 773 } 774 blendFormula = get_lcd_blend_formula(fBlendMode); 775 } else { 776 blendFormula = 777 get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage, 778 hasMixedSamples, fBlendMode); 779 } 780 781 if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || 782 (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/))) { 783 return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode, 784 coverage)); 785 } 786 return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 787 } 788 789 static inline GrXPFactory::AnalysisProperties analysis_properties( 790 const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage, 791 const GrCaps& caps, SkBlendMode mode) { 792 using AnalysisProperties = GrXPFactory::AnalysisProperties; 793 AnalysisProperties props = AnalysisProperties::kNone; 794 bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage; 795 bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage; 796 BlendFormula formula; 797 if (isLCD) { 798 formula = gLCDBlendTable[(int)mode]; 799 } else { 800 formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode]; 801 } 802 803 if (formula.canTweakAlphaForCoverage() && !isLCD) { 804 props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage; 805 } 806 807 if (isLCD) { 808 // See comment in MakeSrcOverXferProcessor about color.isOpaque here 809 if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/ 810 !caps.shaderCaps()->dualSourceBlendingSupport() && 811 !caps.shaderCaps()->dstReadInShaderSupport()) { 812 props |= AnalysisProperties::kIgnoresInputColor; 813 } else { 814 // For LCD blending, if the color is not opaque we must read the dst in shader even if 815 // we have dual source blending. The opaqueness check must be done after blending so for 816 // simplicity we only allow src-over to not take the dst read path (though src, src-in, 817 // and DstATop would also work). We also fall into the dst read case for src-over if we 818 // do not have dual source blending. 819 if (SkBlendMode::kSrcOver != mode || 820 /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque. 821 (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 822 props |= AnalysisProperties::kReadsDstInShader; 823 } 824 } 825 } else { 826 // With dual-source blending we never need the destination color in the shader. 827 if (!caps.shaderCaps()->dualSourceBlendingSupport()) { 828 // Mixed samples implicity computes a fractional coverage from sample coverage. This 829 // could affect the formula used. However, we don't expect to have mixed samples without 830 // dual source blending. 831 SkASSERT(!caps.usesMixedSamples()); 832 if (formula.hasSecondaryOutput()) { 833 props |= AnalysisProperties::kReadsDstInShader; 834 } 835 } 836 } 837 838 if (!formula.modifiesDst() || !formula.usesInputColor()) { 839 props |= AnalysisProperties::kIgnoresInputColor; 840 } 841 return props; 842 } 843 844 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( 845 const GrProcessorAnalysisColor& color, 846 const GrProcessorAnalysisCoverage& coverage, 847 const GrCaps& caps) const { 848 return analysis_properties(color, coverage, caps, fBlendMode); 849 } 850 851 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 852 853 #if GR_TEST_UTILS 854 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) { 855 SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode)); 856 return GrPorterDuffXPFactory::Get(mode); 857 } 858 #endif 859 860 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 861 int* outPrimary, 862 int* outSecondary) { 863 if (!!strcmp(xp->name(), "Porter Duff")) { 864 *outPrimary = *outSecondary = -1; 865 return; 866 } 867 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 868 *outPrimary = blendFormula.primaryOutput(); 869 *outSecondary = blendFormula.secondaryOutput(); 870 } 871 872 //////////////////////////////////////////////////////////////////////////////////////////////// 873 // SrcOver Global functions 874 //////////////////////////////////////////////////////////////////////////////////////////////// 875 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 876 static BlendFormula gSrcOverBlendFormula = 877 MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff); 878 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula, 879 GrProcessorAnalysisCoverage::kSingleChannel); 880 return gSrcOverXP; 881 } 882 883 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor( 884 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 885 bool hasMixedSamples, const GrCaps& caps) { 886 // We want to not make an xfer processor if possible. Thus for the simple case where we are not 887 // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from 888 // the general case where we convert a src-over blend that has solid coverage and an opaque 889 // color to src-mode, which allows disabling of blending. 890 if (coverage != GrProcessorAnalysisCoverage::kLCD) { 891 // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 892 // We don't simply return the address of that XP here because our caller would have to unref 893 // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 894 // safe. 895 return nullptr; 896 } 897 898 // Currently up the stack Skia is requiring that the dst is opaque or that the client has said 899 // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color 900 // being opaque or not. This allows us to use faster code paths as well as avoid various bugs 901 // that occur with dst reads in the shader blending. For now we disable the check for 902 // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make 903 // the correct decision here. 904 // 905 // This also fixes a chrome bug on macs where we are getting random fuzziness when doing 906 // blending in the shader for non opaque sources. 907 if (color.isConstant() && /*color.isOpaque() &&*/ 908 !caps.shaderCaps()->dualSourceBlendingSupport() && 909 !caps.shaderCaps()->dstReadInShaderSupport()) { 910 // If we don't have dual source blending or in shader dst reads, we fall 911 // back to this trick for rendering SrcOver LCD text instead of doing a 912 // dst copy. 913 return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color); 914 } 915 916 BlendFormula blendFormula; 917 blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver); 918 // See comment above regarding why the opaque check is commented out here. 919 if (/*!color.isOpaque() ||*/ 920 (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 921 return sk_sp<GrXferProcessor>( 922 new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage)); 923 } 924 return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 925 } 926 927 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) { 928 BlendFormula formula = get_blend_formula(false, false, false, blendmode); 929 return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone); 930 } 931 932 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( 933 const GrProcessorAnalysisColor& color, 934 const GrProcessorAnalysisCoverage& coverage, 935 const GrCaps& caps) { 936 return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver); 937 } 938