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 "GrProcOptInfo.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 #include <utility> 23 24 /** 25 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 26 */ 27 struct 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 enum Properties { 45 kModifiesDst_Property = 1, 46 kUsesDstColor_Property = 1 << 1, 47 kUsesInputColor_Property = 1 << 2, 48 kCanTweakAlphaForCoverage_Property = 1 << 3, 49 50 kLast_Property = kCanTweakAlphaForCoverage_Property 51 }; 52 53 BlendFormula& operator =(const BlendFormula& other) { 54 fData = other.fData; 55 return *this; 56 } 57 58 bool operator ==(const BlendFormula& other) const { 59 return fData == other.fData; 60 } 61 62 bool hasSecondaryOutput() const { return kNone_OutputType != fSecondaryOutputType; } 63 bool modifiesDst() const { return SkToBool(fProps & kModifiesDst_Property); } 64 bool usesDstColor() const { return SkToBool(fProps & kUsesDstColor_Property); } 65 bool usesInputColor() const { return SkToBool(fProps & kUsesInputColor_Property); } 66 bool canTweakAlphaForCoverage() const { 67 return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); 68 } 69 70 /** 71 * Deduce the properties of a compile-time constant BlendFormula. 72 */ 73 template<OutputType PrimaryOut, OutputType SecondaryOut, 74 GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, GrBlendCoeff DstCoeff> 75 struct get_properties : std::integral_constant<Properties, static_cast<Properties>( 76 77 (GR_BLEND_MODIFIES_DST(BlendEquation, SrcCoeff, DstCoeff) ? 78 kModifiesDst_Property : 0) | 79 80 (GR_BLEND_COEFFS_USE_DST_COLOR(SrcCoeff, DstCoeff) ? 81 kUsesDstColor_Property : 0) | 82 83 ((PrimaryOut >= kModulate_OutputType && GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff,DstCoeff)) || 84 (SecondaryOut >= kModulate_OutputType && GR_BLEND_COEFF_REFS_SRC2(DstCoeff)) ? 85 kUsesInputColor_Property : 0) | // We assert later that SrcCoeff doesn't ref src2. 86 87 (kModulate_OutputType == PrimaryOut && 88 kNone_OutputType == SecondaryOut && 89 GR_BLEND_CAN_TWEAK_ALPHA_FOR_COVERAGE(BlendEquation, SrcCoeff, DstCoeff) ? 90 kCanTweakAlphaForCoverage_Property : 0))> { 91 92 // The provided formula should already be optimized. 93 GR_STATIC_ASSERT((kNone_OutputType == PrimaryOut) == 94 !GR_BLEND_COEFFS_USE_SRC_COLOR(SrcCoeff, DstCoeff)); 95 GR_STATIC_ASSERT(!GR_BLEND_COEFF_REFS_SRC2(SrcCoeff)); 96 GR_STATIC_ASSERT((kNone_OutputType == SecondaryOut) == 97 !GR_BLEND_COEFF_REFS_SRC2(DstCoeff)); 98 GR_STATIC_ASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut); 99 GR_STATIC_ASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut); 100 }; 101 102 union { 103 struct { 104 // We allot the enums one more bit than they require because MSVC seems to sign-extend 105 // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) 106 OutputType fPrimaryOutputType : 4; 107 OutputType fSecondaryOutputType : 4; 108 GrBlendEquation fBlendEquation : 6; 109 GrBlendCoeff fSrcCoeff : 6; 110 GrBlendCoeff fDstCoeff : 6; 111 Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); 112 }; 113 uint32_t fData; 114 }; 115 116 GR_STATIC_ASSERT(kLast_OutputType < (1 << 3)); 117 GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5)); 118 GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5)); 119 GR_STATIC_ASSERT(kLast_Property < (1 << 6)); 120 }; 121 122 GR_STATIC_ASSERT(4 == sizeof(BlendFormula)); 123 124 GR_MAKE_BITFIELD_OPS(BlendFormula::Properties); 125 126 /** 127 * Initialize a compile-time constant BlendFormula and automatically deduce fProps. 128 */ 129 #define INIT_BLEND_FORMULA(PRIMARY_OUT, SECONDARY_OUT, BLEND_EQUATION, SRC_COEFF, DST_COEFF) \ 130 {{{PRIMARY_OUT, \ 131 SECONDARY_OUT, \ 132 BLEND_EQUATION, SRC_COEFF, DST_COEFF, \ 133 BlendFormula::get_properties<PRIMARY_OUT, SECONDARY_OUT, \ 134 BLEND_EQUATION, SRC_COEFF, DST_COEFF>::value}}} 135 136 /** 137 * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard 138 * Porter Duff formula. 139 */ 140 #define COEFF_FORMULA(SRC_COEFF, DST_COEFF) \ 141 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ 142 BlendFormula::kNone_OutputType, \ 143 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF) 144 145 /** 146 * Basic coeff formula similar to COEFF_FORMULA but we will make the src f*Sa. This is used in 147 * LCD dst-out. 148 */ 149 #define COEFF_FORMULA_SA_MODULATE(SRC_COEFF, DST_COEFF) \ 150 INIT_BLEND_FORMULA(BlendFormula::kSAModulate_OutputType, \ 151 BlendFormula::kNone_OutputType, \ 152 kAdd_GrBlendEquation, SRC_COEFF, DST_COEFF) 153 154 /** 155 * When the coeffs are (Zero, Zero), we clear the dst. This formula has its own macro so we can set 156 * the primary output type to none. 157 */ 158 #define DST_CLEAR_FORMULA \ 159 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \ 160 BlendFormula::kNone_OutputType, \ 161 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kZero_GrBlendCoeff) 162 163 /** 164 * When the coeffs are (Zero, One), we don't write to the dst at all. This formula has its own macro 165 * so we can set the primary output type to none. 166 */ 167 #define NO_DST_WRITE_FORMULA \ 168 INIT_BLEND_FORMULA(BlendFormula::kNone_OutputType, \ 169 BlendFormula::kNone_OutputType, \ 170 kAdd_GrBlendEquation, kZero_GrBlendCoeff, kOne_GrBlendCoeff) 171 172 /** 173 * When there is coverage, the equation with f=coverage is: 174 * 175 * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 176 * 177 * This can be rewritten as: 178 * 179 * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) 180 * 181 * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the 182 * HW dst coeff with IS2C. 183 * 184 * Xfer modes: dst-atop (Sa!=1) 185 */ 186 #define COVERAGE_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, SRC_COEFF) \ 187 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ 188 ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \ 189 kAdd_GrBlendEquation, SRC_COEFF, kIS2C_GrBlendCoeff) 190 191 /** 192 * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: 193 * 194 * D' = f * D * dstCoeff + (1-f) * D 195 * 196 * This can be rewritten as: 197 * 198 * D' = D - D * [f * (1 - dstCoeff)] 199 * 200 * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse 201 * subtract HW blend equation with coeffs of (DC, One). 202 * 203 * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) 204 */ 205 #define COVERAGE_SRC_COEFF_ZERO_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT) \ 206 INIT_BLEND_FORMULA(ONE_MINUS_DST_COEFF_MODULATE_OUTPUT, \ 207 BlendFormula::kNone_OutputType, \ 208 kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff) 209 210 /** 211 * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: 212 * 213 * D' = f * S * srcCoeff + (1-f) * D 214 * 215 * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff 216 * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) 217 * 218 * Xfer modes (Sa!=1): src, src-in, src-out 219 */ 220 #define COVERAGE_DST_COEFF_ZERO_FORMULA(SRC_COEFF) \ 221 INIT_BLEND_FORMULA(BlendFormula::kModulate_OutputType, \ 222 BlendFormula::kCoverage_OutputType, \ 223 kAdd_GrBlendEquation, SRC_COEFF, kIS2A_GrBlendCoeff) 224 225 /** 226 * This table outlines the blend formulas we will use with each xfermode, with and without coverage, 227 * with and without an opaque input color. Optimization properties are deduced at compile time so we 228 * can make runtime decisions quickly. RGB coverage is not supported. 229 */ 230 static const BlendFormula gBlendTable[2][2][SkXfermode::kLastCoeffMode + 1] = { 231 232 /*>> No coverage, input color unknown <<*/ {{ 233 234 /* clear */ DST_CLEAR_FORMULA, 235 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), 236 /* dst */ NO_DST_WRITE_FORMULA, 237 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), 238 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 239 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), 240 /* dst-in */ COEFF_FORMULA( kZero_GrBlendCoeff, kSA_GrBlendCoeff), 241 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 242 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff), 243 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), 244 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kSA_GrBlendCoeff), 245 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 246 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 247 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff), 248 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 249 250 }, /*>> Has coverage, input color unknown <<*/ { 251 252 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), 253 /* src */ COVERAGE_DST_COEFF_ZERO_FORMULA(kOne_GrBlendCoeff), 254 /* dst */ NO_DST_WRITE_FORMULA, 255 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), 256 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 257 /* src-in */ COVERAGE_DST_COEFF_ZERO_FORMULA(kDA_GrBlendCoeff), 258 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType), 259 /* src-out */ COVERAGE_DST_COEFF_ZERO_FORMULA(kIDA_GrBlendCoeff), 260 /* dst-out */ COEFF_FORMULA( kZero_GrBlendCoeff, kISA_GrBlendCoeff), 261 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), 262 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 263 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 264 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 265 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType), 266 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 267 268 }}, /*>> No coverage, input color opaque <<*/ {{ 269 270 /* clear */ DST_CLEAR_FORMULA, 271 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), 272 /* dst */ NO_DST_WRITE_FORMULA, 273 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kZero_GrBlendCoeff), 274 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 275 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), 276 /* dst-in */ NO_DST_WRITE_FORMULA, 277 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 278 /* dst-out */ DST_CLEAR_FORMULA, 279 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kZero_GrBlendCoeff), 280 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 281 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 282 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 283 /* modulate */ COEFF_FORMULA( kZero_GrBlendCoeff, kSC_GrBlendCoeff), 284 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 285 286 }, /*>> Has coverage, input color opaque <<*/ { 287 288 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), 289 /* src */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), 290 /* dst */ NO_DST_WRITE_FORMULA, 291 /* src-over */ COEFF_FORMULA( kOne_GrBlendCoeff, kISA_GrBlendCoeff), 292 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 293 /* src-in */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), 294 /* dst-in */ NO_DST_WRITE_FORMULA, 295 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 296 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), 297 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), 298 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 299 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 300 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 301 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType), 302 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 303 }}}; 304 305 static const BlendFormula gLCDBlendTable[SkXfermode::kLastCoeffMode + 1] = { 306 /* clear */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_OutputType), 307 /* src */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), 308 /* dst */ NO_DST_WRITE_FORMULA, 309 /* src-over */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff), 310 /* dst-over */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 311 /* src-in */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff), 312 /* dst-in */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISAModulate_OutputType), 313 /* src-out */ COVERAGE_FORMULA(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff), 314 /* dst-out */ COEFF_FORMULA_SA_MODULATE( kZero_GrBlendCoeff, kISC_GrBlendCoeff), 315 /* src-atop */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff), 316 /* dst-atop */ COVERAGE_FORMULA(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 317 /* xor */ COVERAGE_FORMULA(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff), 318 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 319 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_OutputType), 320 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 321 }; 322 323 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI, 324 const GrProcOptInfo& coveragePOI, 325 bool hasMixedSamples, 326 SkXfermode::Mode xfermode) { 327 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); 328 SkASSERT(!coveragePOI.isFourChannelOutput()); 329 330 bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples; 331 return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode]; 332 } 333 334 static BlendFormula get_lcd_blend_formula(const GrProcOptInfo& coveragePOI, 335 SkXfermode::Mode xfermode) { 336 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); 337 SkASSERT(coveragePOI.isFourChannelOutput()); 338 339 return gLCDBlendTable[xfermode]; 340 } 341 342 /////////////////////////////////////////////////////////////////////////////// 343 344 class PorterDuffXferProcessor : public GrXferProcessor { 345 public: 346 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendFormula) { 347 this->initClassID<PorterDuffXferProcessor>(); 348 } 349 350 const char* name() const override { return "Porter Duff"; } 351 352 GrGLSLXferProcessor* createGLSLInstance() const override; 353 354 BlendFormula getBlendFormula() const { return fBlendFormula; } 355 356 private: 357 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations, 358 bool doesStencilWrite, 359 GrColor* overrideColor, 360 const GrCaps& caps) const override; 361 362 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 363 364 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } 365 366 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 367 blendInfo->fEquation = fBlendFormula.fBlendEquation; 368 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; 369 blendInfo->fDstBlend = fBlendFormula.fDstCoeff; 370 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 371 } 372 373 bool onIsEqual(const GrXferProcessor& xpBase) const override { 374 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); 375 return fBlendFormula == xp.fBlendFormula; 376 } 377 378 const BlendFormula fBlendFormula; 379 380 typedef GrXferProcessor INHERITED; 381 }; 382 383 /////////////////////////////////////////////////////////////////////////////// 384 385 static void append_color_output(const PorterDuffXferProcessor& xp, 386 GrGLSLXPFragmentBuilder* fragBuilder, 387 BlendFormula::OutputType outputType, const char* output, 388 const char* inColor, const char* inCoverage) { 389 switch (outputType) { 390 case BlendFormula::kNone_OutputType: 391 fragBuilder->codeAppendf("%s = vec4(0.0);", output); 392 break; 393 case BlendFormula::kCoverage_OutputType: 394 // We can have a coverage formula while not reading coverage if there are mixed samples. 395 if (inCoverage) { 396 fragBuilder->codeAppendf("%s = %s;", output, inCoverage); 397 } else { 398 fragBuilder->codeAppendf("%s = vec4(1.0);", output); 399 } 400 break; 401 case BlendFormula::kModulate_OutputType: 402 if (inCoverage) { 403 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); 404 } else { 405 fragBuilder->codeAppendf("%s = %s;", output, inColor); 406 } 407 break; 408 case BlendFormula::kSAModulate_OutputType: 409 if (inCoverage) { 410 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage); 411 } else { 412 fragBuilder->codeAppendf("%s = %s;", output, inColor); 413 } 414 break; 415 case BlendFormula::kISAModulate_OutputType: 416 if (inCoverage) { 417 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); 418 } else { 419 fragBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inColor); 420 } 421 break; 422 case BlendFormula::kISCModulate_OutputType: 423 if (inCoverage) { 424 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output, inColor, inCoverage); 425 } else { 426 fragBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor); 427 } 428 break; 429 default: 430 SkFAIL("Unsupported output type."); 431 break; 432 } 433 } 434 435 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor { 436 public: 437 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 438 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); 439 b->add32(xp.getBlendFormula().fPrimaryOutputType | 440 (xp.getBlendFormula().fSecondaryOutputType << 3)); 441 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); 442 }; 443 444 private: 445 void emitOutputsForBlendState(const EmitArgs& args) override { 446 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); 447 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 448 449 BlendFormula blendFormula = xp.getBlendFormula(); 450 if (blendFormula.hasSecondaryOutput()) { 451 append_color_output(xp, fragBuilder, blendFormula.fSecondaryOutputType, 452 args.fOutputSecondary, args.fInputColor, args.fInputCoverage); 453 } 454 append_color_output(xp, fragBuilder, blendFormula.fPrimaryOutputType, 455 args.fOutputPrimary, args.fInputColor, args.fInputCoverage); 456 } 457 458 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 459 460 typedef GrGLSLXferProcessor INHERITED; 461 }; 462 463 /////////////////////////////////////////////////////////////////////////////// 464 465 void PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&, 466 GrProcessorKeyBuilder* b) const { 467 GLPorterDuffXferProcessor::GenKey(*this, b); 468 } 469 470 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { 471 return new GLPorterDuffXferProcessor; 472 } 473 474 GrXferProcessor::OptFlags 475 PorterDuffXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations, 476 bool doesStencilWrite, 477 GrColor* overrideColor, 478 const GrCaps& caps) const { 479 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags; 480 if (!fBlendFormula.modifiesDst()) { 481 if (!doesStencilWrite) { 482 optFlags |= GrXferProcessor::kSkipDraw_OptFlag; 483 } 484 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag | 485 GrXferProcessor::kIgnoreCoverage_OptFlag | 486 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); 487 } else { 488 if (!fBlendFormula.usesInputColor()) { 489 optFlags |= GrXferProcessor::kIgnoreColor_OptFlag; 490 } 491 if (optimizations.fCoveragePOI.isSolidWhite()) { 492 optFlags |= GrXferProcessor::kIgnoreCoverage_OptFlag; 493 } 494 if (optimizations.fColorPOI.allStagesMultiplyInput() && 495 fBlendFormula.canTweakAlphaForCoverage() && 496 !optimizations.fCoveragePOI.isFourChannelOutput()) { 497 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; 498 } 499 } 500 return optFlags; 501 } 502 503 /////////////////////////////////////////////////////////////////////////////// 504 505 class ShaderPDXferProcessor : public GrXferProcessor { 506 public: 507 ShaderPDXferProcessor(const DstTexture* dstTexture, 508 bool hasMixedSamples, 509 SkXfermode::Mode xfermode) 510 : INHERITED(dstTexture, true, hasMixedSamples) 511 , fXfermode(xfermode) { 512 this->initClassID<ShaderPDXferProcessor>(); 513 } 514 515 const char* name() const override { return "Porter Duff Shader"; } 516 517 GrGLSLXferProcessor* createGLSLInstance() const override; 518 519 SkXfermode::Mode getXfermode() const { return fXfermode; } 520 521 private: 522 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*, 523 const GrCaps&) const override { 524 return kNone_OptFlags; 525 } 526 527 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 528 529 bool onIsEqual(const GrXferProcessor& xpBase) const override { 530 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 531 return fXfermode == xp.fXfermode; 532 } 533 534 const SkXfermode::Mode fXfermode; 535 536 typedef GrXferProcessor INHERITED; 537 }; 538 539 /////////////////////////////////////////////////////////////////////////////// 540 541 class GLShaderPDXferProcessor : public GrGLSLXferProcessor { 542 public: 543 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 544 const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>(); 545 b->add32(xp.getXfermode()); 546 } 547 548 private: 549 void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 550 GrGLSLUniformHandler* uniformHandler, 551 const char* srcColor, 552 const char* srcCoverage, 553 const char* dstColor, 554 const char* outColor, 555 const char* outColorSecondary, 556 const GrXferProcessor& proc) override { 557 const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>(); 558 559 GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode()); 560 561 // Apply coverage. 562 INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor, 563 outColorSecondary, xp); 564 } 565 566 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 567 568 typedef GrGLSLXferProcessor INHERITED; 569 }; 570 571 /////////////////////////////////////////////////////////////////////////////// 572 573 void ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&, 574 GrProcessorKeyBuilder* b) const { 575 GLShaderPDXferProcessor::GenKey(*this, b); 576 } 577 578 GrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const { 579 return new GLShaderPDXferProcessor; 580 } 581 582 /////////////////////////////////////////////////////////////////////////////// 583 584 class PDLCDXferProcessor : public GrXferProcessor { 585 public: 586 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInfo& colorPOI); 587 588 ~PDLCDXferProcessor() override; 589 590 const char* name() const override { return "Porter Duff LCD"; } 591 592 GrGLSLXferProcessor* createGLSLInstance() const override; 593 594 private: 595 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); 596 597 GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations& optimizations, 598 bool doesStencilWrite, 599 GrColor* overrideColor, 600 const GrCaps& caps) const override; 601 602 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override; 603 604 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 605 blendInfo->fSrcBlend = kConstC_GrBlendCoeff; 606 blendInfo->fDstBlend = kISC_GrBlendCoeff; 607 blendInfo->fBlendConstant = fBlendConstant; 608 } 609 610 bool onIsEqual(const GrXferProcessor& xpBase) const override { 611 const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>(); 612 if (fBlendConstant != xp.fBlendConstant || 613 fAlpha != xp.fAlpha) { 614 return false; 615 } 616 return true; 617 } 618 619 GrColor fBlendConstant; 620 uint8_t fAlpha; 621 622 typedef GrXferProcessor INHERITED; 623 }; 624 625 /////////////////////////////////////////////////////////////////////////////// 626 627 class GLPDLCDXferProcessor : public GrGLSLXferProcessor { 628 public: 629 GLPDLCDXferProcessor(const GrProcessor&) {} 630 631 virtual ~GLPDLCDXferProcessor() {} 632 633 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, 634 GrProcessorKeyBuilder* b) {} 635 636 private: 637 void emitOutputsForBlendState(const EmitArgs& args) override { 638 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 639 SkASSERT(args.fInputCoverage); 640 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, 641 args.fInputCoverage); 642 } 643 644 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}; 645 646 typedef GrGLSLXferProcessor INHERITED; 647 }; 648 649 /////////////////////////////////////////////////////////////////////////////// 650 651 PDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 652 : fBlendConstant(blendConstant) 653 , fAlpha(alpha) { 654 this->initClassID<PDLCDXferProcessor>(); 655 } 656 657 GrXferProcessor* PDLCDXferProcessor::Create(SkXfermode::Mode xfermode, 658 const GrProcOptInfo& colorPOI) { 659 if (SkXfermode::kSrcOver_Mode != xfermode) { 660 return nullptr; 661 } 662 663 if (kRGBA_GrColorComponentFlags != colorPOI.validFlags()) { 664 return nullptr; 665 } 666 667 GrColor blendConstant = GrUnpremulColor(colorPOI.color()); 668 uint8_t alpha = GrColorUnpackA(blendConstant); 669 blendConstant |= (0xff << GrColor_SHIFT_A); 670 671 return new PDLCDXferProcessor(blendConstant, alpha); 672 } 673 674 PDLCDXferProcessor::~PDLCDXferProcessor() { 675 } 676 677 void PDLCDXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps& caps, 678 GrProcessorKeyBuilder* b) const { 679 GLPDLCDXferProcessor::GenKey(*this, caps, b); 680 } 681 682 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { 683 return new GLPDLCDXferProcessor(*this); 684 } 685 686 GrXferProcessor::OptFlags 687 PDLCDXferProcessor::onGetOptimizations(const GrPipelineOptimizations& optimizations, 688 bool doesStencilWrite, 689 GrColor* overrideColor, 690 const GrCaps& caps) const { 691 // We want to force our primary output to be alpha * Coverage, where alpha is the alpha 692 // value of the blend the constant. We should already have valid blend coeff's if we are at 693 // a point where we have RGB coverage. We don't need any color stages since the known color 694 // output is already baked into the blendConstant. 695 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); 696 return GrXferProcessor::kOverrideColor_OptFlag; 697 } 698 699 /////////////////////////////////////////////////////////////////////////////// 700 701 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode) 702 : fXfermode(xfermode) { 703 SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode); 704 this->initClassID<GrPorterDuffXPFactory>(); 705 } 706 707 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) { 708 static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode); 709 static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); 710 static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode); 711 static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); 712 static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); 713 static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); 714 static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); 715 static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); 716 static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); 717 static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); 718 static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); 719 static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode); 720 static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); 721 static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); 722 static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); 723 724 static GrPorterDuffXPFactory* gFactories[] = { 725 &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &gSrcInPDXPF, 726 &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDXPF, &gXorPDXPF, 727 &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF 728 }; 729 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1); 730 731 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { 732 return nullptr; 733 } 734 return SkRef(gFactories[xfermode]); 735 } 736 737 GrXferProcessor* 738 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, 739 const GrPipelineOptimizations& optimizations, 740 bool hasMixedSamples, 741 const DstTexture* dstTexture) const { 742 if (optimizations.fOverrides.fUsePLSDstRead) { 743 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode); 744 } 745 BlendFormula blendFormula; 746 if (optimizations.fCoveragePOI.isFourChannelOutput()) { 747 if (SkXfermode::kSrcOver_Mode == fXfermode && 748 kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() && 749 !caps.shaderCaps()->dualSourceBlendingSupport() && 750 !caps.shaderCaps()->dstReadInShaderSupport()) { 751 // If we don't have dual source blending or in shader dst reads, we fall back to this 752 // trick for rendering SrcOver LCD text instead of doing a dst copy. 753 SkASSERT(!dstTexture || !dstTexture->texture()); 754 return PDLCDXferProcessor::Create(fXfermode, optimizations.fColorPOI); 755 } 756 blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode); 757 } else { 758 blendFormula = get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, 759 hasMixedSamples, fXfermode); 760 } 761 762 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) { 763 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode); 764 } 765 766 SkASSERT(!dstTexture || !dstTexture->texture()); 767 return new PorterDuffXferProcessor(blendFormula); 768 } 769 770 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, 771 InvariantBlendedColor* blendedColor) const { 772 // Find the blended color info based on the formula that does not have coverage. 773 BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode]; 774 if (colorFormula.usesDstColor()) { 775 blendedColor->fWillBlendWithDst = true; 776 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; 777 return; 778 } 779 780 blendedColor->fWillBlendWithDst = false; 781 782 SkASSERT(kAdd_GrBlendEquation == colorFormula.fBlendEquation); 783 784 switch (colorFormula.fSrcCoeff) { 785 case kZero_GrBlendCoeff: 786 blendedColor->fKnownColor = 0; 787 blendedColor->fKnownColorFlags = kRGBA_GrColorComponentFlags; 788 return; 789 790 case kOne_GrBlendCoeff: 791 blendedColor->fKnownColor = colorPOI.color(); 792 blendedColor->fKnownColorFlags = colorPOI.validFlags(); 793 return; 794 795 default: 796 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; 797 return; 798 } 799 } 800 801 bool GrPorterDuffXPFactory::onWillReadDstColor(const GrCaps& caps, 802 const GrPipelineOptimizations& optimizations, 803 bool hasMixedSamples) const { 804 if (caps.shaderCaps()->dualSourceBlendingSupport()) { 805 return false; 806 } 807 808 // When we have four channel coverage we always need to read the dst in order to correctly 809 // blend. The one exception is when we are using srcover mode and we know the input color into 810 // the XP. 811 if (optimizations.fCoveragePOI.isFourChannelOutput()) { 812 if (SkXfermode::kSrcOver_Mode == fXfermode && 813 kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() && 814 !caps.shaderCaps()->dstReadInShaderSupport()) { 815 return false; 816 } 817 return get_lcd_blend_formula(optimizations.fCoveragePOI, fXfermode).hasSecondaryOutput(); 818 } 819 // We fallback on the shader XP when the blend formula would use dual source blending but we 820 // don't have support for it. 821 return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, hasMixedSamples, 822 fXfermode).hasSecondaryOutput(); 823 } 824 825 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 826 827 const GrXPFactory* GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) { 828 SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermode::kLastCoeffMode)); 829 return GrPorterDuffXPFactory::Create(mode); 830 } 831 832 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 833 int* outPrimary, 834 int* outSecondary) { 835 if (!!strcmp(xp->name(), "Porter Duff")) { 836 *outPrimary = *outSecondary = -1; 837 return; 838 } 839 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 840 *outPrimary = blendFormula.fPrimaryOutputType; 841 *outSecondary = blendFormula.fSecondaryOutputType; 842 } 843 844 845 //////////////////////////////////////////////////////////////////////////////////////////////// 846 // SrcOver Global functions 847 //////////////////////////////////////////////////////////////////////////////////////////////// 848 const GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 849 static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoeff, 850 kISA_GrBlendCoeff); 851 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula); 852 return gSrcOverXP; 853 } 854 855 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor( 856 const GrCaps& caps, 857 const GrPipelineOptimizations& optimizations, 858 bool hasMixedSamples, 859 const GrXferProcessor::DstTexture* dstTexture) { 860 if (optimizations.fOverrides.fUsePLSDstRead) { 861 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode); 862 } 863 if (!optimizations.fCoveragePOI.isFourChannelOutput() && 864 !(optimizations.fCoveragePOI.isSolidWhite() && 865 !hasMixedSamples && 866 optimizations.fColorPOI.isOpaque())) { 867 // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 868 // We don't simply return the address of that XP here because our caller would have to unref 869 // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 870 // safe. 871 return nullptr; 872 } 873 874 BlendFormula blendFormula; 875 if (optimizations.fCoveragePOI.isFourChannelOutput()) { 876 if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() && 877 !caps.shaderCaps()->dualSourceBlendingSupport() && 878 !caps.shaderCaps()->dstReadInShaderSupport()) { 879 // If we don't have dual source blending or in shader dst reads, we fall 880 // back to this trick for rendering SrcOver LCD text instead of doing a 881 // dst copy. 882 SkASSERT(!dstTexture || !dstTexture->texture()); 883 return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, optimizations.fColorPOI); 884 } 885 blendFormula = get_lcd_blend_formula(optimizations.fCoveragePOI, SkXfermode::kSrcOver_Mode); 886 } else { 887 blendFormula = get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, 888 hasMixedSamples, SkXfermode::kSrcOver_Mode); 889 } 890 891 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) { 892 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode::kSrcOver_Mode); 893 } 894 895 SkASSERT(!dstTexture || !dstTexture->texture()); 896 return new PorterDuffXferProcessor(blendFormula); 897 } 898 899 bool GrPorterDuffXPFactory::SrcOverWillNeedDstTexture(const GrCaps& caps, 900 const GrPipelineOptimizations& optimizations, 901 bool hasMixedSamples) { 902 if (caps.shaderCaps()->dstReadInShaderSupport() || 903 caps.shaderCaps()->dualSourceBlendingSupport()) { 904 return false; 905 } 906 907 // When we have four channel coverage we always need to read the dst in order to correctly 908 // blend. The one exception is when we are using srcover mode and we know the input color 909 // into the XP. 910 if (optimizations.fCoveragePOI.isFourChannelOutput()) { 911 if (kRGBA_GrColorComponentFlags == optimizations.fColorPOI.validFlags() && 912 !caps.shaderCaps()->dstReadInShaderSupport()) { 913 return false; 914 } 915 return get_lcd_blend_formula(optimizations.fCoveragePOI, 916 SkXfermode::kSrcOver_Mode).hasSecondaryOutput(); 917 } 918 // We fallback on the shader XP when the blend formula would use dual source blending but we 919 // don't have support for it. 920 return get_blend_formula(optimizations.fColorPOI, optimizations.fCoveragePOI, 921 hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSecondaryOutput(); 922 } 923 924