OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "effects/GrPorterDuffXferProcessor.h" | 8 #include "effects/GrPorterDuffXferProcessor.h" |
9 | 9 |
10 #include "GrBlend.h" | 10 #include "GrBlend.h" |
11 #include "GrDrawState.h" | |
12 #include "GrDrawTargetCaps.h" | 11 #include "GrDrawTargetCaps.h" |
13 #include "GrInvariantOutput.h" | 12 #include "GrInvariantOutput.h" |
14 #include "GrProcessor.h" | 13 #include "GrProcessor.h" |
| 14 #include "GrProcOptInfo.h" |
15 #include "GrTypes.h" | 15 #include "GrTypes.h" |
16 #include "GrXferProcessor.h" | 16 #include "GrXferProcessor.h" |
17 #include "gl/GrGLXferProcessor.h" | 17 #include "gl/GrGLXferProcessor.h" |
18 #include "gl/builders/GrGLFragmentShaderBuilder.h" | 18 #include "gl/builders/GrGLFragmentShaderBuilder.h" |
19 #include "gl/builders/GrGLProgramBuilder.h" | 19 #include "gl/builders/GrGLProgramBuilder.h" |
20 | 20 |
21 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD
rawing) { | 21 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff) { |
22 /* | 22 /* |
23 The fractional coverage is f. | 23 The fractional coverage is f. |
24 The src and dst coeffs are Cs and Cd. | 24 The src and dst coeffs are Cs and Cd. |
25 The dst and src colors are S and D. | 25 The dst and src colors are S and D. |
26 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha | 26 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha |
27 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second | 27 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second |
28 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we | 28 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we |
29 find that only 1, ISA, and ISC produce the correct destination when applied
to S' and D. | 29 find that only 1, ISA, and ISC produce the correct destination when applied
to S' and D. |
30 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag
e is treated as | |
31 color by definition. | |
32 */ | 30 */ |
33 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera
geDrawing here | |
34 return kOne_GrBlendCoeff == dstCoeff || | 31 return kOne_GrBlendCoeff == dstCoeff || |
35 kISA_GrBlendCoeff == dstCoeff || | 32 kISA_GrBlendCoeff == dstCoeff || |
36 kISC_GrBlendCoeff == dstCoeff || | 33 kISC_GrBlendCoeff == dstCoeff; |
37 isCoverageDrawing; | |
38 } | 34 } |
39 | 35 |
40 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { | 36 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { |
41 public: | 37 public: |
42 GrGLPorterDuffXferProcessor(const GrProcessor&) {} | 38 GrGLPorterDuffXferProcessor(const GrProcessor&) {} |
43 | 39 |
44 virtual ~GrGLPorterDuffXferProcessor() {} | 40 virtual ~GrGLPorterDuffXferProcessor() {} |
45 | 41 |
46 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { | 42 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
47 const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProc
essor>(); | 43 const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProc
essor>(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 | 117 |
122 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, | 118 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, |
123 GrProcessorKeyBuilder* b) cons
t { | 119 GrProcessorKeyBuilder* b) cons
t { |
124 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); | 120 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); |
125 } | 121 } |
126 | 122 |
127 GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const { | 123 GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const { |
128 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); | 124 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); |
129 } | 125 } |
130 | 126 |
131 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { | |
132 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | |
133 } | |
134 | |
135 GrXferProcessor::OptFlags | 127 GrXferProcessor::OptFlags |
136 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, | 128 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
137 const GrProcOptInfo& coveragePOI, | 129 const GrProcOptInfo& coveragePOI, |
138 bool isCoverageDrawing, | |
139 bool colorWriteDisabled, | 130 bool colorWriteDisabled, |
140 bool doesStencilWrite, | 131 bool doesStencilWrite, |
141 GrColor* overrideColor, | 132 GrColor* overrideColor, |
142 const GrDrawTargetCaps& caps) { | 133 const GrDrawTargetCaps& caps) { |
143 GrXferProcessor::OptFlags optFlags; | 134 GrXferProcessor::OptFlags optFlags; |
144 // Optimizations when doing RGB Coverage | 135 // Optimizations when doing RGB Coverage |
145 if (coveragePOI.isFourChannelOutput()) { | 136 if (coveragePOI.isFourChannelOutput()) { |
146 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | 137 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
147 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | 138 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
148 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | 139 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
149 // output is already baked into the blendConstant. | 140 // output is already baked into the blendConstant. |
150 uint8_t alpha = GrColorUnpackA(fBlendConstant); | 141 uint8_t alpha = GrColorUnpackA(fBlendConstant); |
151 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); | 142 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); |
152 optFlags = GrXferProcessor::kOverrideColor_OptFlag; | 143 optFlags = GrXferProcessor::kOverrideColor_OptFlag; |
153 } else { | 144 } else { |
154 optFlags = this->internalGetOptimizations(colorPOI, | 145 optFlags = this->internalGetOptimizations(colorPOI, |
155 coveragePOI, | 146 coveragePOI, |
156 isCoverageDrawing, | |
157 colorWriteDisabled, | 147 colorWriteDisabled, |
158 doesStencilWrite); | 148 doesStencilWrite); |
159 } | 149 } |
160 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), | 150 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite(), |
161 colorPOI.readsDst() || coveragePOI.readsDst()); | 151 colorPOI.readsDst() || coveragePOI.readsDst()); |
162 return optFlags; | 152 return optFlags; |
163 } | 153 } |
164 | 154 |
165 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, | 155 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, |
166 const GrDrawTargetCaps& caps, | 156 const GrDrawTargetCaps& caps, |
167 bool hasSolidCoverage, bool read
sDst) { | 157 bool hasSolidCoverage, bool read
sDst) { |
168 if (optFlags & kIgnoreColor_OptFlag) { | 158 if (optFlags & kIgnoreColor_OptFlag) { |
169 if (optFlags & kIgnoreCoverage_OptFlag) { | 159 if (optFlags & kIgnoreCoverage_OptFlag) { |
170 fPrimaryOutputType = kNone_PrimaryOutputType; | 160 fPrimaryOutputType = kNone_PrimaryOutputType; |
(...skipping 30 matching lines...) Expand all Loading... |
201 kOne_GrBlendCoeff == fSrcBlend && | 191 kOne_GrBlendCoeff == fSrcBlend && |
202 kZero_GrBlendCoeff == fDstBlend) { | 192 kZero_GrBlendCoeff == fDstBlend) { |
203 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; | 193 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; |
204 } | 194 } |
205 } | 195 } |
206 } | 196 } |
207 | 197 |
208 GrXferProcessor::OptFlags | 198 GrXferProcessor::OptFlags |
209 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, | 199 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, |
210 const GrProcOptInfo& coverag
ePOI, | 200 const GrProcOptInfo& coverag
ePOI, |
211 bool isCoverageDrawing, | |
212 bool colorWriteDisabled, | 201 bool colorWriteDisabled, |
213 bool doesStencilWrite) { | 202 bool doesStencilWrite) { |
214 if (colorWriteDisabled) { | 203 if (colorWriteDisabled) { |
215 fSrcBlend = kZero_GrBlendCoeff; | 204 fSrcBlend = kZero_GrBlendCoeff; |
216 fDstBlend = kOne_GrBlendCoeff; | 205 fDstBlend = kOne_GrBlendCoeff; |
217 } | 206 } |
218 | 207 |
219 bool srcAIsOne; | 208 bool srcAIsOne; |
220 bool hasCoverage; | 209 bool hasCoverage; |
221 if (isCoverageDrawing) { | 210 |
222 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); | 211 srcAIsOne = colorPOI.isOpaque(); |
223 hasCoverage = false; | 212 hasCoverage = !coveragePOI.isSolidWhite(); |
224 } else { | |
225 srcAIsOne = colorPOI.isOpaque(); | |
226 hasCoverage = !coveragePOI.isSolidWhite(); | |
227 } | |
228 | 213 |
229 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 214 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
230 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 215 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
231 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 216 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
232 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 217 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
233 | 218 |
234 // When coeffs are (0,1) there is no reason to draw at all, unless | 219 // When coeffs are (0,1) there is no reason to draw at all, unless |
235 // stenciling is enabled. Having color writes disabled is effectively | 220 // stenciling is enabled. Having color writes disabled is effectively |
236 // (0,1). | 221 // (0,1). |
237 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 222 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
(...skipping 17 matching lines...) Expand all Loading... |
255 return GrXferProcessor::kNone_Opt; | 240 return GrXferProcessor::kNone_Opt; |
256 } else if (kZero_GrBlendCoeff == fSrcBlend) { | 241 } else if (kZero_GrBlendCoeff == fSrcBlend) { |
257 // if the op is "clear" then we don't need to emit a color | 242 // if the op is "clear" then we don't need to emit a color |
258 // or blend, just write transparent black into the dst. | 243 // or blend, just write transparent black into the dst. |
259 fSrcBlend = kOne_GrBlendCoeff; | 244 fSrcBlend = kOne_GrBlendCoeff; |
260 fDstBlend = kZero_GrBlendCoeff; | 245 fDstBlend = kZero_GrBlendCoeff; |
261 return GrXferProcessor::kIgnoreColor_OptFlag | | 246 return GrXferProcessor::kIgnoreColor_OptFlag | |
262 GrXferProcessor::kIgnoreCoverage_OptFlag; | 247 GrXferProcessor::kIgnoreCoverage_OptFlag; |
263 } | 248 } |
264 } | 249 } |
265 } else if (isCoverageDrawing) { | 250 } else { |
266 // we have coverage but we aren't distinguishing it from alpha by reques
t. | |
267 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
268 } else { | |
269 // check whether coverage can be safely rolled into alpha | 251 // check whether coverage can be safely rolled into alpha |
270 // of if we can skip color computation and just emit coverage | 252 // of if we can skip color computation and just emit coverage |
271 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { | 253 if (can_tweak_alpha_for_coverage(fDstBlend)) { |
272 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 254 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
273 } | 255 } |
274 if (dstCoeffIsZero) { | 256 if (dstCoeffIsZero) { |
275 if (kZero_GrBlendCoeff == fSrcBlend) { | 257 if (kZero_GrBlendCoeff == fSrcBlend) { |
276 // the source color is not included in the blend | 258 // the source color is not included in the blend |
277 // the dst coeff is effectively zero so blend works out to: | 259 // the dst coeff is effectively zero so blend works out to: |
278 // (c)(0)D + (1-c)D = (1-c)D. | 260 // (c)(0)D + (1-c)D = (1-c)D. |
279 fDstBlend = kISA_GrBlendCoeff; | 261 fDstBlend = kISA_GrBlendCoeff; |
280 return GrXferProcessor::kIgnoreColor_OptFlag | | 262 return GrXferProcessor::kIgnoreColor_OptFlag | |
281 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 263 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 uint32_t knownColorFlags) const
{ | 393 uint32_t knownColorFlags) const
{ |
412 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && | 394 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && |
413 kRGBA_GrColorComponentFlags == knownColorFlags) { | 395 kRGBA_GrColorComponentFlags == knownColorFlags) { |
414 return true; | 396 return true; |
415 } | 397 } |
416 return false; | 398 return false; |
417 } | 399 } |
418 | 400 |
419 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, | 401 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, |
420 const GrProcOptInfo& coveragePOI, | 402 const GrProcOptInfo& coveragePOI, |
421 bool isCoverageDrawing, | |
422 bool colorWriteDisabled) const { | 403 bool colorWriteDisabled) const { |
423 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i
sOpaque()); | 404 bool srcAIsOne = colorPOI.isOpaque(); |
424 | 405 |
425 if (colorWriteDisabled) { | 406 if (colorWriteDisabled) { |
426 return true; | 407 return true; |
427 } | 408 } |
428 | 409 |
429 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || | 410 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || |
430 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); | 411 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); |
431 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || | 412 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || |
432 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); | 413 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); |
433 | 414 |
434 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { | 415 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { |
435 return true; | 416 return true; |
436 } | 417 } |
437 | 418 |
438 // if we don't have coverage we can check whether the dst | 419 // if we don't have coverage we can check whether the dst |
439 // has to read at all. | 420 // has to read at all. |
440 if (isCoverageDrawing) { | 421 // check whether coverage can be safely rolled into alpha |
441 // we have coverage but we aren't distinguishing it from alpha by reques
t. | 422 // of if we can skip color computation and just emit coverage |
| 423 if (this->canTweakAlphaForCoverage()) { |
442 return true; | 424 return true; |
443 } else { | 425 } |
444 // check whether coverage can be safely rolled into alpha | 426 if (dstCoeffIsZero) { |
445 // of if we can skip color computation and just emit coverage | 427 if (kZero_GrBlendCoeff == fSrcCoeff) { |
446 if (this->canTweakAlphaForCoverage(isCoverageDrawing)) { | |
447 return true; | 428 return true; |
| 429 } else if (srcAIsOne) { |
| 430 return true; |
448 } | 431 } |
449 if (dstCoeffIsZero) { | 432 } else if (dstCoeffIsOne) { |
450 if (kZero_GrBlendCoeff == fSrcCoeff) { | 433 return true; |
451 return true; | |
452 } else if (srcAIsOne) { | |
453 return true; | |
454 } | |
455 } else if (dstCoeffIsOne) { | |
456 return true; | |
457 } | |
458 } | 434 } |
459 | 435 |
460 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's | 436 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's |
461 // will readDst and PD XP's don't read dst. | 437 // will readDst and PD XP's don't read dst. |
462 if ((colorPOI.readsDst() || coveragePOI.readsDst()) && | 438 if ((colorPOI.readsDst() || coveragePOI.readsDst()) && |
463 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) { | 439 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) { |
464 return true; | 440 return true; |
465 } | 441 } |
466 | 442 |
467 return false; | 443 return false; |
468 } | 444 } |
469 | 445 |
470 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI, | 446 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI, |
471 const GrProcOptInfo& coveragePOI, | 447 const GrProcOptInfo& coveragePOI, |
472 bool isCoverageDrawing, | |
473 bool colorWriteDisabled) const { | 448 bool colorWriteDisabled) const { |
474 if (!(isCoverageDrawing || coveragePOI.isSolidWhite())) { | 449 if (!coveragePOI.isSolidWhite()) { |
475 return true; | 450 return true; |
476 } | 451 } |
477 | 452 |
478 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's | 453 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's |
479 // will readDst and PD XP's don't read dst. | 454 // will readDst and PD XP's don't read dst. |
480 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst())
{ | 455 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst())
{ |
481 return true; | 456 return true; |
482 } | 457 } |
483 | 458 |
484 if (GrBlendCoeffRefsDst(fSrcCoeff)) { | 459 if (GrBlendCoeffRefsDst(fSrcCoeff)) { |
485 return true; | 460 return true; |
486 } | 461 } |
487 | 462 |
488 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i
sOpaque()); | 463 bool srcAIsOne = colorPOI.isOpaque(); |
489 | 464 |
490 if (!(kZero_GrBlendCoeff == fDstCoeff || | 465 if (!(kZero_GrBlendCoeff == fDstCoeff || |
491 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) { | 466 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) { |
492 return true; | 467 return true; |
493 } | 468 } |
494 | 469 |
495 return false; | 470 return false; |
496 } | 471 } |
497 | 472 |
498 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage(bool isCoverageDrawing) con
st { | 473 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const { |
499 return can_tweak_alpha_for_coverage(fDstCoeff, isCoverageDrawing); | 474 return can_tweak_alpha_for_coverage(fDstCoeff); |
500 } | 475 } |
501 | 476 |
502 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI
, | 477 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI
, |
503 const GrProcOptInfo& coverage
POI, | 478 const GrProcOptInfo& coverage
POI, |
504 GrColor* solidColor, | 479 GrColor* solidColor, |
505 uint32_t* solidColorKnownComp
onents) const { | 480 uint32_t* solidColorKnownComp
onents) const { |
506 if (!coveragePOI.isSolidWhite()) { | 481 if (!coveragePOI.isSolidWhite()) { |
507 return false; | 482 return false; |
508 } | 483 } |
509 | 484 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 } while (GrBlendCoeffRefsSrc(src)); | 547 } while (GrBlendCoeffRefsSrc(src)); |
573 | 548 |
574 GrBlendCoeff dst; | 549 GrBlendCoeff dst; |
575 do { | 550 do { |
576 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | 551 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); |
577 } while (GrBlendCoeffRefsDst(dst)); | 552 } while (GrBlendCoeffRefsDst(dst)); |
578 | 553 |
579 return GrPorterDuffXPFactory::Create(src, dst); | 554 return GrPorterDuffXPFactory::Create(src, dst); |
580 } | 555 } |
581 | 556 |
OLD | NEW |