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(kPorterDuffXferProcessor_ClassID, false, false, coverage) 401 , fBlendFormula(blendFormula) { 402 } 403 404 const char* name() const override { return "Porter Duff"; } 405 406 GrGLSLXferProcessor* createGLSLInstance() const override; 407 408 BlendFormula getBlendFormula() const { return fBlendFormula; } 409 410 private: 411 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 412 413 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } 414 415 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 416 blendInfo->fEquation = fBlendFormula.equation(); 417 blendInfo->fSrcBlend = fBlendFormula.srcCoeff(); 418 blendInfo->fDstBlend = fBlendFormula.dstCoeff(); 419 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 420 } 421 422 bool onIsEqual(const GrXferProcessor& xpBase) const override { 423 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); 424 return fBlendFormula == xp.fBlendFormula; 425 } 426 427 const BlendFormula fBlendFormula; 428 429 typedef GrXferProcessor INHERITED; 430 }; 431 432 /////////////////////////////////////////////////////////////////////////////// 433 434 static void append_color_output(const PorterDuffXferProcessor& xp, 435 GrGLSLXPFragmentBuilder* fragBuilder, 436 BlendFormula::OutputType outputType, const char* output, 437 const char* inColor, const char* inCoverage) { 438 SkASSERT(inCoverage); 439 SkASSERT(inColor); 440 switch (outputType) { 441 case BlendFormula::kNone_OutputType: 442 fragBuilder->codeAppendf("%s = half4(0.0);", output); 443 break; 444 case BlendFormula::kCoverage_OutputType: 445 // We can have a coverage formula while not reading coverage if there are mixed samples. 446 fragBuilder->codeAppendf("%s = %s;", output, inCoverage); 447 break; 448 case BlendFormula::kModulate_OutputType: 449 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); 450 break; 451 case BlendFormula::kSAModulate_OutputType: 452 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage); 453 break; 454 case BlendFormula::kISAModulate_OutputType: 455 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); 456 break; 457 case BlendFormula::kISCModulate_OutputType: 458 fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage); 459 break; 460 default: 461 SK_ABORT("Unsupported output type."); 462 break; 463 } 464 } 465 466 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor { 467 public: 468 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 469 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); 470 b->add32(xp.getBlendFormula().primaryOutput() | 471 (xp.getBlendFormula().secondaryOutput() << 3)); 472 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); 473 } 474 475 private: 476 void emitOutputsForBlendState(const EmitArgs& args) override { 477 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); 478 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 479 480 BlendFormula blendFormula = xp.getBlendFormula(); 481 if (blendFormula.hasSecondaryOutput()) { 482 append_color_output(xp, fragBuilder, blendFormula.secondaryOutput(), 483 args.fOutputSecondary, args.fInputColor, args.fInputCoverage); 484 } 485 append_color_output(xp, fragBuilder, blendFormula.primaryOutput(), args.fOutputPrimary, 486 args.fInputColor, args.fInputCoverage); 487 } 488 489 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 490 491 typedef GrGLSLXferProcessor INHERITED; 492 }; 493 494 /////////////////////////////////////////////////////////////////////////////// 495 496 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 497 GrProcessorKeyBuilder* b) const { 498 GLPorterDuffXferProcessor::GenKey(*this, b); 499 } 500 501 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { 502 return new GLPorterDuffXferProcessor; 503 } 504 505 /////////////////////////////////////////////////////////////////////////////// 506 507 class ShaderPDXferProcessor : public GrXferProcessor { 508 public: 509 ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode, 510 GrProcessorAnalysisCoverage coverage) 511 : INHERITED(kShaderPDXferProcessor_ClassID, true, hasMixedSamples, coverage) 512 , fXfermode(xfermode) { 513 } 514 515 const char* name() const override { return "Porter Duff Shader"; } 516 517 GrGLSLXferProcessor* createGLSLInstance() const override; 518 519 SkBlendMode getXfermode() const { return fXfermode; } 520 521 private: 522 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 523 524 bool onIsEqual(const GrXferProcessor& xpBase) const override { 525 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 526 return fXfermode == xp.fXfermode; 527 } 528 529 const SkBlendMode fXfermode; 530 531 typedef GrXferProcessor INHERITED; 532 }; 533 534 /////////////////////////////////////////////////////////////////////////////// 535 536 class GLShaderPDXferProcessor : public GrGLSLXferProcessor { 537 public: 538 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 539 const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>(); 540 b->add32((int)xp.getXfermode()); 541 } 542 543 private: 544 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 545 GrGLSLUniformHandler* uniformHandler, 546 const char* srcColor, 547 const char* srcCoverage, 548 const char* dstColor, 549 const char* outColor, 550 const char* outColorSecondary, 551 const GrXferProcessor& proc) override { 552 const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>(); 553 554 GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode()); 555 556 // Apply coverage. 557 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor, 558 outColorSecondary, xp); 559 } 560 561 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 562 563 typedef GrGLSLXferProcessor INHERITED; 564 }; 565 566 /////////////////////////////////////////////////////////////////////////////// 567 568 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 569 GrProcessorKeyBuilder* b) const { 570 GLShaderPDXferProcessor::GenKey(*this, b); 571 } 572 573 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const { 574 return new GLShaderPDXferProcessor; 575 } 576 577 /////////////////////////////////////////////////////////////////////////////// 578 579 class PDLCDXferProcessor : public GrXferProcessor { 580 public: 581 static sk_sp<const GrXferProcessor> Make(SkBlendMode mode, 582 const GrProcessorAnalysisColor& inputColor); 583 584 ~PDLCDXferProcessor() override; 585 586 const char* name() const override { return "Porter Duff LCD"; } 587 588 GrGLSLXferProcessor* createGLSLInstance() const override; 589 590 uint8_t alpha() const { return fAlpha; } 591 592 private: 593 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); 594 595 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 596 597 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 598 blendInfo->fSrcBlend = kConstC_GrBlendCoeff; 599 blendInfo->fDstBlend = kISC_GrBlendCoeff; 600 blendInfo->fBlendConstant = fBlendConstant; 601 } 602 603 bool onIsEqual(const GrXferProcessor& xpBase) const override { 604 const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>(); 605 if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) { 606 return false; 607 } 608 return true; 609 } 610 611 GrColor fBlendConstant; 612 uint8_t fAlpha; 613 614 typedef GrXferProcessor INHERITED; 615 }; 616 617 /////////////////////////////////////////////////////////////////////////////// 618 619 class GLPDLCDXferProcessor : public GrGLSLXferProcessor { 620 public: 621 GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {} 622 623 ~GLPDLCDXferProcessor() override {} 624 625 static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps, 626 GrProcessorKeyBuilder* b) {} 627 628 private: 629 void emitOutputsForBlendState(const EmitArgs& args) override { 630 const char* alpha; 631 fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, 632 "alpha", &alpha); 633 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 634 // We want to force our primary output to be alpha * Coverage, where alpha is the alpha 635 // value of the src color. We know that there are no color stages (or we wouldn't have 636 // created this xp) and the r,g, and b channels of the op's input color are baked into the 637 // blend constant. 638 SkASSERT(args.fInputCoverage); 639 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage); 640 } 641 642 void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override { 643 uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha()); 644 if (fLastAlpha != alpha) { 645 pdm.set1f(fAlphaUniform, alpha / 255.f); 646 fLastAlpha = alpha; 647 } 648 } 649 650 GrGLSLUniformHandler::UniformHandle fAlphaUniform; 651 uint32_t fLastAlpha; 652 typedef GrGLSLXferProcessor INHERITED; 653 }; 654 655 /////////////////////////////////////////////////////////////////////////////// 656 657 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 658 : INHERITED(kPDLCDXferProcessor_ClassID, false, false, GrProcessorAnalysisCoverage::kLCD) 659 , fBlendConstant(blendConstant) 660 , fAlpha(alpha) { 661 } 662 663 sk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode, 664 const GrProcessorAnalysisColor& color) { 665 if (SkBlendMode::kSrcOver != mode) { 666 return nullptr; 667 } 668 GrColor blendConstant; 669 if (!color.isConstant(&blendConstant)) { 670 return nullptr; 671 } 672 blendConstant = GrUnpremulColor(blendConstant); 673 uint8_t alpha = GrColorUnpackA(blendConstant); 674 blendConstant |= (0xff << GrColor_SHIFT_A); 675 return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstant, alpha)); 676 } 677 678 PDLCDXferProcessor::~PDLCDXferProcessor() { 679 } 680 681 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, 682 GrProcessorKeyBuilder* b) const { 683 GLPDLCDXferProcessor::GenKey(*this, caps, b); 684 } 685 686 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { 687 return new GLPDLCDXferProcessor(*this); 688 } 689 690 /////////////////////////////////////////////////////////////////////////////// 691 692 constexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) 693 : fBlendMode(xfermode) {} 694 695 const GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) { 696 SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode); 697 698 // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are 699 // null. 700 #ifdef SK_BUILD_FOR_WIN 701 #define _CONSTEXPR_ 702 #else 703 #define _CONSTEXPR_ constexpr 704 #endif 705 static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear); 706 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc); 707 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst); 708 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver); 709 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver); 710 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn); 711 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn); 712 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut); 713 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut); 714 static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop); 715 static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop); 716 static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor); 717 static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus); 718 static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate); 719 static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen); 720 #undef _CONSTEXPR_ 721 722 switch (blendMode) { 723 case SkBlendMode::kClear: 724 return &gClearPDXPF; 725 case SkBlendMode::kSrc: 726 return &gSrcPDXPF; 727 case SkBlendMode::kDst: 728 return &gDstPDXPF; 729 case SkBlendMode::kSrcOver: 730 return &gSrcOverPDXPF; 731 case SkBlendMode::kDstOver: 732 return &gDstOverPDXPF; 733 case SkBlendMode::kSrcIn: 734 return &gSrcInPDXPF; 735 case SkBlendMode::kDstIn: 736 return &gDstInPDXPF; 737 case SkBlendMode::kSrcOut: 738 return &gSrcOutPDXPF; 739 case SkBlendMode::kDstOut: 740 return &gDstOutPDXPF; 741 case SkBlendMode::kSrcATop: 742 return &gSrcATopPDXPF; 743 case SkBlendMode::kDstATop: 744 return &gDstATopPDXPF; 745 case SkBlendMode::kXor: 746 return &gXorPDXPF; 747 case SkBlendMode::kPlus: 748 return &gPlusPDXPF; 749 case SkBlendMode::kModulate: 750 return &gModulatePDXPF; 751 case SkBlendMode::kScreen: 752 return &gScreenPDXPF; 753 default: 754 SK_ABORT("Unexpected blend mode."); 755 return nullptr; 756 } 757 } 758 759 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( 760 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 761 bool hasMixedSamples, const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped) const { 762 BlendFormula blendFormula; 763 bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD; 764 if (isLCD) { 765 // See comment in MakeSrcOverXferProcessor about color.isOpaque here 766 if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/ 767 !caps.shaderCaps()->dualSourceBlendingSupport() && 768 !caps.shaderCaps()->dstReadInShaderSupport()) { 769 // If we don't have dual source blending or in shader dst reads, we fall back to this 770 // trick for rendering SrcOver LCD text instead of doing a dst copy. 771 return PDLCDXferProcessor::Make(fBlendMode, color); 772 } 773 blendFormula = get_lcd_blend_formula(fBlendMode); 774 } else { 775 blendFormula = 776 get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage, 777 hasMixedSamples, fBlendMode); 778 } 779 780 bool needsClamp = SkBlendMode::kPlus == fBlendMode; 781 if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || 782 (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/)) || 783 (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped))) { 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, GrPixelConfigIsClamped dstIsClamped, 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 bool needsClamp = SkBlendMode::kPlus == mode; 840 if (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped)) { 841 props |= AnalysisProperties::kReadsDstInShader; 842 } 843 844 if (!formula.modifiesDst() || !formula.usesInputColor()) { 845 props |= AnalysisProperties::kIgnoresInputColor; 846 } 847 // Ignore the effect of coverage here for overlap stencil and cover property 848 auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode]; 849 SkASSERT(kAdd_GrBlendEquation == colorFormula.equation()); 850 if (!colorFormula.usesDstColor()) { 851 props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover; 852 } 853 return props; 854 } 855 856 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( 857 const GrProcessorAnalysisColor& color, 858 const GrProcessorAnalysisCoverage& coverage, 859 const GrCaps& caps, 860 GrPixelConfigIsClamped dstIsClamped) const { 861 return analysis_properties(color, coverage, caps, dstIsClamped, fBlendMode); 862 } 863 864 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 865 866 #if GR_TEST_UTILS 867 const GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) { 868 SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode)); 869 return GrPorterDuffXPFactory::Get(mode); 870 } 871 #endif 872 873 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 874 int* outPrimary, 875 int* outSecondary) { 876 if (!!strcmp(xp->name(), "Porter Duff")) { 877 *outPrimary = *outSecondary = -1; 878 return; 879 } 880 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 881 *outPrimary = blendFormula.primaryOutput(); 882 *outSecondary = blendFormula.secondaryOutput(); 883 } 884 885 //////////////////////////////////////////////////////////////////////////////////////////////// 886 // SrcOver Global functions 887 //////////////////////////////////////////////////////////////////////////////////////////////// 888 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 889 static BlendFormula gSrcOverBlendFormula = 890 MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff); 891 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula, 892 GrProcessorAnalysisCoverage::kSingleChannel); 893 return gSrcOverXP; 894 } 895 896 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor( 897 const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 898 bool hasMixedSamples, const GrCaps& caps) { 899 // We want to not make an xfer processor if possible. Thus for the simple case where we are not 900 // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from 901 // the general case where we convert a src-over blend that has solid coverage and an opaque 902 // color to src-mode, which allows disabling of blending. 903 if (coverage != GrProcessorAnalysisCoverage::kLCD) { 904 // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 905 // We don't simply return the address of that XP here because our caller would have to unref 906 // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 907 // safe. 908 return nullptr; 909 } 910 911 // Currently up the stack Skia is requiring that the dst is opaque or that the client has said 912 // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color 913 // being opaque or not. This allows us to use faster code paths as well as avoid various bugs 914 // that occur with dst reads in the shader blending. For now we disable the check for 915 // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make 916 // the correct decision here. 917 // 918 // This also fixes a chrome bug on macs where we are getting random fuzziness when doing 919 // blending in the shader for non opaque sources. 920 if (color.isConstant() && /*color.isOpaque() &&*/ 921 !caps.shaderCaps()->dualSourceBlendingSupport() && 922 !caps.shaderCaps()->dstReadInShaderSupport()) { 923 // If we don't have dual source blending or in shader dst reads, we fall 924 // back to this trick for rendering SrcOver LCD text instead of doing a 925 // dst copy. 926 return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color); 927 } 928 929 BlendFormula blendFormula; 930 blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver); 931 // See comment above regarding why the opaque check is commented out here. 932 if (/*!color.isOpaque() ||*/ 933 (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 934 return sk_sp<GrXferProcessor>( 935 new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage)); 936 } 937 return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 938 } 939 940 sk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) { 941 BlendFormula formula = get_blend_formula(false, false, false, blendmode); 942 return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone); 943 } 944 945 GrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( 946 const GrProcessorAnalysisColor& color, 947 const GrProcessorAnalysisCoverage& coverage, 948 const GrCaps& caps, 949 GrPixelConfigIsClamped dstIsClamped) { 950 return analysis_properties(color, coverage, caps, dstIsClamped, SkBlendMode::kSrcOver); 951 } 952