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 "glsl/GrGLSLBlend.h" 18 #include "glsl/GrGLSLFragmentShaderBuilder.h" 19 #include "glsl/GrGLSLProgramDataManager.h" 20 #include "glsl/GrGLSLUniformHandler.h" 21 #include "glsl/GrGLSLXferProcessor.h" 22 23 /** 24 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 25 */ 26 class BlendFormula { 27 public: 28 /** 29 * Values the shader can write to primary and secondary outputs. These must all be modulated by 30 * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage. 31 */ 32 enum OutputType { 33 kNone_OutputType, //<! 0 34 kCoverage_OutputType, //<! inputCoverage 35 kModulate_OutputType, //<! inputColor * inputCoverage 36 kSAModulate_OutputType, //<! inputColor.a * inputCoverage 37 kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage 38 kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage 39 40 kLast_OutputType = kISCModulate_OutputType 41 }; 42 43 BlendFormula() = default; 44 45 constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation, 46 GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) 47 : fPrimaryOutputType(primaryOut) 48 , fSecondaryOutputType(secondaryOut) 49 , fBlendEquation(equation) 50 , fSrcCoeff(srcCoeff) 51 , fDstCoeff(dstCoeff) 52 , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {} 53 54 BlendFormula& operator=(const BlendFormula& other) { 55 SkDEBUGCODE(other.validatePreoptimized()); 56 fData = other.fData; 57 return *this; 58 } 59 60 bool operator==(const BlendFormula& other) const { 61 SkDEBUGCODE(this->validatePreoptimized()); 62 SkDEBUGCODE(other.validatePreoptimized()); 63 return fData == other.fData; 64 } 65 66 bool hasSecondaryOutput() const { 67 SkDEBUGCODE(this->validatePreoptimized()); 68 return kNone_OutputType != fSecondaryOutputType; 69 } 70 bool modifiesDst() const { 71 SkDEBUGCODE(this->validatePreoptimized()); 72 return SkToBool(fProps & kModifiesDst_Property); 73 } 74 bool usesDstColor() const { 75 SkDEBUGCODE(this->validatePreoptimized()); 76 return SkToBool(fProps & kUsesDstColor_Property); 77 } 78 bool usesInputColor() const { 79 SkDEBUGCODE(this->validatePreoptimized()); 80 return SkToBool(fProps & kUsesInputColor_Property); 81 } 82 bool canTweakAlphaForCoverage() const { 83 SkDEBUGCODE(this->validatePreoptimized()); 84 return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); 85 } 86 87 GrBlendEquation equation() const { 88 SkDEBUGCODE(this->validatePreoptimized()); 89 return fBlendEquation; 90 } 91 92 GrBlendCoeff srcCoeff() const { 93 SkDEBUGCODE(this->validatePreoptimized()); 94 return fSrcCoeff; 95 } 96 97 GrBlendCoeff dstCoeff() const { 98 SkDEBUGCODE(this->validatePreoptimized()); 99 return fDstCoeff; 100 } 101 102 OutputType primaryOutput() const { 103 SkDEBUGCODE(this->validatePreoptimized()); 104 return fPrimaryOutputType; 105 } 106 107 OutputType secondaryOutput() const { 108 SkDEBUGCODE(this->validatePreoptimized()); 109 return fSecondaryOutputType; 110 } 111 112 private: 113 enum Properties { 114 kModifiesDst_Property = 1, 115 kUsesDstColor_Property = 1 << 1, 116 kUsesInputColor_Property = 1 << 2, 117 kCanTweakAlphaForCoverage_Property = 1 << 3, 118 119 kLast_Property = kCanTweakAlphaForCoverage_Property 120 }; 121 GR_DECL_BITFIELD_OPS_FRIENDS(Properties) 122 123 #ifdef SK_DEBUG 124 void validatePreoptimized() const { 125 // The provided formula should already be optimized before a BlendFormula is constructed. 126 // Preferably these asserts would be done statically in the constexpr constructor, but this 127 // is not allowed in C++11. 128 SkASSERT((kNone_OutputType == fPrimaryOutputType) == 129 !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff)); 130 SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff)); 131 SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff)); 132 SkASSERT(fPrimaryOutputType != fSecondaryOutputType || 133 kNone_OutputType == fPrimaryOutputType); 134 SkASSERT(kNone_OutputType != fPrimaryOutputType || 135 kNone_OutputType == fSecondaryOutputType); 136 } 137 #endif 138 139 /** 140 * Deduce the properties of a BlendFormula. 141 */ 142 static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut, 143 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, 144 GrBlendCoeff DstCoeff); 145 146 union { 147 struct { 148 // We allot the enums one more bit than they require because MSVC seems to sign-extend 149 // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) 150 OutputType fPrimaryOutputType : 4; 151 OutputType fSecondaryOutputType : 4; 152 GrBlendEquation fBlendEquation : 6; 153 GrBlendCoeff fSrcCoeff : 6; 154 GrBlendCoeff fDstCoeff : 6; 155 Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); 156 }; 157 uint32_t fData; 158 }; 159 160 GR_STATIC_ASSERT(kLast_OutputType < (1 << 3)); 161 GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5)); 162 GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5)); 163 GR_STATIC_ASSERT(kLast_Property < (1 << 6)); 164 }; 165 166 GR_STATIC_ASSERT(4 == sizeof(BlendFormula)); 167 168 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties); 169 170 constexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut, 171 OutputType SecondaryOut, 172 GrBlendEquation BlendEquation, 173 GrBlendCoeff SrcCoeff, 174 GrBlendCoeff DstCoeff) { 175 return static_cast<Properties>( 176 (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) | 177 (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) | 178 ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) || 179 (SecondaryOut >= kModulate_OutputType && 180 GrBlendCoeffRefsSrc2(DstCoeff)) 181 ? kUsesInputColor_Property 182 : 0) | // We assert later that SrcCoeff doesn't ref src2. 183 ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) && 184 kNone_OutputType == SecondaryOut && 185 GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff) 186 ? kCanTweakAlphaForCoverage_Property 187 : 0)); 188 } 189 190 /** 191 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard 192 * Porter Duff formula. 193 */ 194 static constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 195 // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none. 196 return (kZero_GrBlendCoeff == srcCoeff && 197 (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff)) 198 ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType, 199 kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff) 200 : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType, 201 kAdd_GrBlendEquation, srcCoeff, dstCoeff); 202 } 203 204 /** 205 * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in 206 * LCD dst-out. 207 */ 208 static constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 209 return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType, 210 kAdd_GrBlendEquation, srcCoeff, dstCoeff); 211 } 212 213 /** 214 * When there is coverage, the equation with f=coverage is: 215 * 216 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 217 * 218 * This can be rewritten as: 219 * 220 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) 221 * 222 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the 223 * HW dst coeff with IS2C. 224 * 225 * Xfer modes: dst-atop (Sa!=1) 226 */ 227 static constexpr BlendFormula MakeCoverageFormula( 228 BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) { 229 return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput, 230 kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff); 231 } 232 233 /** 234 * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: 235 * 236 * D' = f * D * dstCoeff + (1-f) * D 237 * 238 * This can be rewritten as: 239 * 240 * D' = D - D * [f * (1 - dstCoeff)] 241 * 242 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse 243 * subtract HW blend equation with coeffs of (DC, One). 244 * 245 * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) 246 */ 247 static constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula( 248 BlendFormula::OutputType oneMinusDstCoeffModulateOutput) { 249 return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType, 250 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff); 251 } 252 253 /** 254 * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: 255 * 256 * D' = f * S * srcCoeff + (1-f) * D 257 * 258 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff 259 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) 260 * 261 * Xfer modes (Sa!=1): src, src-in, src-out 262 */ 263 static constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) { 264 return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType, 265 kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff); 266 } 267 268 // Older GCC won't like the constexpr arrays because of 269 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484. 270 // MSVC 2015 crashes with an internal compiler error. 271 #if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910)) 272 # define MAYBE_CONSTEXPR const 273 #else 274 # define MAYBE_CONSTEXPR constexpr 275 #endif 276 277 /** 278 * This table outlines the blend formulas we will use with each xfermode, with and without coverage, 279 * with and without an opaque input color. Optimization properties are deduced at compile time so we 280 * can make runtime decisions quickly. RGB coverage is not supported. 281 */ 282 static MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = { 283 /*>> No coverage, input color unknown <<*/ {{ 284 285 /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 286 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 287 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 288 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 289 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 290 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 291 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff), 292 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 293 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 294 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 295 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kSA_GrBlendCoeff), 296 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 297 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 298 /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 299 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 300 301 }, /*>> Has coverage, input color unknown <<*/ { 302 303 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 304 /* src */ MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff), 305 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 306 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 307 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 308 /* src-in */ MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff), 309 /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 310 /* src-out */ MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff), 311 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 312 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 313 /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 314 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 315 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 316 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 317 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 318 319 }}, /*>> No coverage, input color opaque <<*/ {{ 320 321 /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 322 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 323 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 324 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), // see comment below 325 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 326 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 327 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 328 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 329 /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 330 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 331 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 332 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 333 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 334 /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 335 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 336 337 }, /*>> Has coverage, input color opaque <<*/ { 338 339 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 340 /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 341 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 342 /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 343 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 344 /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 345 /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 346 /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 347 /* dst-out */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 348 /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 349 /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 350 /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 351 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 352 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 353 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 354 }}}; 355 // In the above table src-over is not optimized to src mode when the color is opaque because we 356 // found no advantage to doing so. Also, we are using a global src-over XP in most cases which is 357 // not specialized for opaque input. If the table were set to use the src formula then we'd have to 358 // change when we use this global XP to keep analysis and practice in sync. 359 360 static MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = { 361 /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 362 /* src */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), 363 /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 364 /* src-over */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff), 365 /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 366 /* src-in */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff), 367 /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 368 /* src-out */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff), 369 /* dst-out */ MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff), 370 /* src-atop */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff), 371 /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 372 /* xor */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff), 373 /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 374 /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 375 /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 376 }; 377 378 #undef MAYBE_CONSTEXPR 379 380 static BlendFormula get_blend_formula(bool isOpaque, 381 bool hasCoverage, 382 bool hasMixedSamples, 383 SkBlendMode xfermode) { 384 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 385 bool conflatesCoverage = hasCoverage || hasMixedSamples; 386 return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode]; 387 } 388 389 static BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) { 390 SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 391 392 return gLCDBlendTable[(int)xfermode]; 393 } 394 395 /////////////////////////////////////////////////////////////////////////////// 396 397 class PorterDuffXferProcessor : public GrXferProcessor { 398 public: 399 PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage) 400 : INHERITED(false, false, coverage) 401 , fBlendFormula(blendFormula) { 402 this->initClassID<PorterDuffXferProcessor>(); 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 = vec4(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 = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage); 460 break; 461 default: 462 SkFAIL("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(true, hasMixedSamples, coverage), fXfermode(xfermode) { 513 this->initClassID<ShaderPDXferProcessor>(); 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 uint8_t alpha() const { return fAlpha; } 592 593 private: 594 PDLCDXferProcessor(GrColor blendConstant, uint8_t 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 GrColor fBlendConstant; 613 uint8_t fAlpha; 614 615 typedef GrXferProcessor INHERITED; 616 }; 617 618 /////////////////////////////////////////////////////////////////////////////// 619 620 class GLPDLCDXferProcessor : public GrGLSLXferProcessor { 621 public: 622 GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {} 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, kFloat_GrSLType, 633 kDefault_GrSLPrecision, "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 uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha()); 645 if (fLastAlpha != alpha) { 646 pdm.set1f(fAlphaUniform, alpha / 255.f); 647 fLastAlpha = alpha; 648 } 649 } 650 651 GrGLSLUniformHandler::UniformHandle fAlphaUniform; 652 uint32_t fLastAlpha; 653 typedef GrGLSLXferProcessor INHERITED; 654 }; 655 656 /////////////////////////////////////////////////////////////////////////////// 657 658 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 659 : INHERITED(false, false, GrProcessorAnalysisCoverage::kLCD) 660 , fBlendConstant(blendConstant) 661 , fAlpha(alpha) { 662 this->initClassID<PDLCDXferProcessor>(); 663 } 664 665 sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode, 666 const GrProcessorAnalysisColor& color) { 667 if (SkBlendMode::kSrcOver != mode) { 668 return nullptr; 669 } 670 GrColor blendConstant; 671 if (!color.isConstant(&blendConstant)) { 672 return nullptr; 673 } 674 blendConstant = GrUnpremulColor(blendConstant); 675 uint8_t alpha = GrColorUnpackA(blendConstant); 676 blendConstant |= (0xff << GrColor_SHIFT_A); 677 return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstant, alpha)); 678 } 679 680 PDLCDXferProcessor::~PDLCDXferProcessor() { 681 } 682 683 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, 684 GrProcessorKeyBuilder* b) const { 685 GLPDLCDXferProcessor::GenKey(*this, caps, b); 686 } 687 688 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { 689 return new GLPDLCDXferProcessor(*this); 690 } 691 692 /////////////////////////////////////////////////////////////////////////////// 693 694 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) 695 : fBlendMode(xfermode) {} 696 697 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) { 698 SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode); 699 700 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are 701 // null. 702 #ifdef SK_BUILD_FOR_WIN 703 #define _CONSTEXPR_ 704 #else 705 #define _CONSTEXPR_ constexpr 706 #endif 707 static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear); 708 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc); 709 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst); 710 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver); 711 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver); 712 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn); 713 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn); 714 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut); 715 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut); 716 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop); 717 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop); 718 static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor); 719 static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus); 720 static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate); 721 static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen); 722 #undef _CONSTEXPR_ 723 724 switch (blendMode) { 725 case SkBlendMode::kClear: 726 return &gClearPDXPF; 727 case SkBlendMode::kSrc: 728 return &gSrcPDXPF; 729 case SkBlendMode::kDst: 730 return &gDstPDXPF; 731 case SkBlendMode::kSrcOver: 732 return &gSrcOverPDXPF; 733 case SkBlendMode::kDstOver: 734 return &gDstOverPDXPF; 735 case SkBlendMode::kSrcIn: 736 return &gSrcInPDXPF; 737 case SkBlendMode::kDstIn: 738 return &gDstInPDXPF; 739 case SkBlendMode::kSrcOut: 740 return &gSrcOutPDXPF; 741 case SkBlendMode::kDstOut: 742 return &gDstOutPDXPF; 743 case SkBlendMode::kSrcATop: 744 return &gSrcATopPDXPF; 745 case SkBlendMode::kDstATop: 746 return &gDstATopPDXPF; 747 case SkBlendMode::kXor: 748 return &gXorPDXPF; 749 case SkBlendMode::kPlus: 750 return &gPlusPDXPF; 751 case SkBlendMode::kModulate: 752 return &gModulatePDXPF; 753 case SkBlendMode::kScreen: 754 return &gScreenPDXPF; 755 default: 756 SkFAIL("Unexpected blend mode."); 757 return nullptr; 758 } 759 } 760 761 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( 762 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 763 bool hasMixedSamples, const GrCaps& caps) const { 764 BlendFormula blendFormula; 765 bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD; 766 if (isLCD) { 767 // See comment in MakeSrcOverXferProcessor about color.isOpaque here 768 if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/ 769 !caps.shaderCaps()->dualSourceBlendingSupport() && 770 !caps.shaderCaps()->dstReadInShaderSupport()) { 771 // If we don't have dual source blending or in shader dst reads, we fall back to this 772 // trick for rendering SrcOver LCD text instead of doing a dst copy. 773 return PDLCDXferProcessor::Make(fBlendMode, color); 774 } 775 blendFormula = get_lcd_blend_formula(fBlendMode); 776 } else { 777 blendFormula = 778 get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage, 779 hasMixedSamples, fBlendMode); 780 } 781 782 if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || 783 (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/))) { 784 return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode, 785 coverage)); 786 } 787 return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 788 } 789 790 static inline GrXPFactory::AnalysisProperties analysis_properties( 791 const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage, 792 const GrCaps& caps, SkBlendMode mode) { 793 using AnalysisProperties = GrXPFactory::AnalysisProperties; 794 AnalysisProperties props = AnalysisProperties::kNone; 795 bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage; 796 bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage; 797 BlendFormula formula; 798 if (isLCD) { 799 formula = gLCDBlendTable[(int)mode]; 800 } else { 801 formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode]; 802 } 803 804 if (formula.canTweakAlphaForCoverage() && !isLCD) { 805 props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage; 806 } 807 808 if (isLCD) { 809 // See comment in MakeSrcOverXferProcessor about color.isOpaque here 810 if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/ 811 !caps.shaderCaps()->dualSourceBlendingSupport() && 812 !caps.shaderCaps()->dstReadInShaderSupport()) { 813 props |= AnalysisProperties::kIgnoresInputColor; 814 } else { 815 // For LCD blending, if the color is not opaque we must read the dst in shader even if 816 // we have dual source blending. The opaqueness check must be done after blending so for 817 // simplicity we only allow src-over to not take the dst read path (though src, src-in, 818 // and DstATop would also work). We also fall into the dst read case for src-over if we 819 // do not have dual source blending. 820 if (SkBlendMode::kSrcOver != mode || 821 /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque. 822 (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 823 props |= AnalysisProperties::kReadsDstInShader; 824 } 825 } 826 } else { 827 // With dual-source blending we never need the destination color in the shader. 828 if (!caps.shaderCaps()->dualSourceBlendingSupport()) { 829 // Mixed samples implicity computes a fractional coverage from sample coverage. This 830 // could affect the formula used. However, we don't expect to have mixed samples without 831 // dual source blending. 832 SkASSERT(!caps.usesMixedSamples()); 833 if (formula.hasSecondaryOutput()) { 834 props |= AnalysisProperties::kReadsDstInShader; 835 } 836 } 837 } 838 839 if (!formula.modifiesDst() || !formula.usesInputColor()) { 840 props |= AnalysisProperties::kIgnoresInputColor; 841 } 842 // Ignore the effect of coverage here for overlap stencil and cover property 843 auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode]; 844 SkASSERT(kAdd_GrBlendEquation == colorFormula.equation()); 845 if (!colorFormula.usesDstColor()) { 846 props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover; 847 } 848 return props; 849 } 850 851 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( 852 const GrProcessorAnalysisColor& color, 853 const GrProcessorAnalysisCoverage& coverage, 854 const GrCaps& caps) const { 855 return analysis_properties(color, coverage, caps, fBlendMode); 856 } 857 858 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 859 860 #if GR_TEST_UTILS 861 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) { 862 SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode)); 863 return GrPorterDuffXPFactory::Get(mode); 864 } 865 #endif 866 867 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 868 int* outPrimary, 869 int* outSecondary) { 870 if (!!strcmp(xp->name(), "Porter Duff")) { 871 *outPrimary = *outSecondary = -1; 872 return; 873 } 874 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 875 *outPrimary = blendFormula.primaryOutput(); 876 *outSecondary = blendFormula.secondaryOutput(); 877 } 878 879 //////////////////////////////////////////////////////////////////////////////////////////////// 880 // SrcOver Global functions 881 //////////////////////////////////////////////////////////////////////////////////////////////// 882 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 883 static BlendFormula gSrcOverBlendFormula = 884 MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff); 885 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula, 886 GrProcessorAnalysisCoverage::kSingleChannel); 887 return gSrcOverXP; 888 } 889 890 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor( 891 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 892 bool hasMixedSamples, const GrCaps& caps) { 893 // We want to not make an xfer processor if possible. Thus for the simple case where we are not 894 // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from 895 // the general case where we convert a src-over blend that has solid coverage and an opaque 896 // color to src-mode, which allows disabling of blending. 897 if (coverage != GrProcessorAnalysisCoverage::kLCD) { 898 // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 899 // We don't simply return the address of that XP here because our caller would have to unref 900 // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 901 // safe. 902 return nullptr; 903 } 904 905 // Currently up the stack Skia is requiring that the dst is opaque or that the client has said 906 // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color 907 // being opaque or not. This allows us to use faster code paths as well as avoid various bugs 908 // that occur with dst reads in the shader blending. For now we disable the check for 909 // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make 910 // the correct decision here. 911 // 912 // This also fixes a chrome bug on macs where we are getting random fuzziness when doing 913 // blending in the shader for non opaque sources. 914 if (color.isConstant() && /*color.isOpaque() &&*/ 915 !caps.shaderCaps()->dualSourceBlendingSupport() && 916 !caps.shaderCaps()->dstReadInShaderSupport()) { 917 // If we don't have dual source blending or in shader dst reads, we fall 918 // back to this trick for rendering SrcOver LCD text instead of doing a 919 // dst copy. 920 return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color); 921 } 922 923 BlendFormula blendFormula; 924 blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver); 925 // See comment above regarding why the opaque check is commented out here. 926 if (/*!color.isOpaque() ||*/ 927 (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 928 return sk_sp<GrXferProcessor>( 929 new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage)); 930 } 931 return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 932 } 933 934 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) { 935 BlendFormula formula = get_blend_formula(false, false, false, blendmode); 936 return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone); 937 } 938 939 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( 940 const GrProcessorAnalysisColor& color, 941 const GrProcessorAnalysisCoverage& coverage, 942 const GrCaps& caps) { 943 return analysis_properties(color, coverage, caps, SkBlendMode::kSrcOver); 944 } 945