| 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" | |
| 11 #include "GrDrawState.h" | 10 #include "GrDrawState.h" |
| 12 #include "GrInvariantOutput.h" | 11 #include "GrInvariantOutput.h" |
| 13 #include "GrProcessor.h" | 12 #include "GrProcessor.h" |
| 14 #include "GrTypes.h" | 13 #include "GrTypes.h" |
| 15 #include "GrXferProcessor.h" | 14 #include "GrXferProcessor.h" |
| 16 #include "gl/GrGLProcessor.h" | 15 #include "gl/GrGLProcessor.h" |
| 17 #include "gl/builders/GrGLFragmentShaderBuilder.h" | 16 #include "gl/builders/GrGLFragmentShaderBuilder.h" |
| 18 #include "gl/builders/GrGLProgramBuilder.h" | 17 #include "gl/builders/GrGLProgramBuilder.h" |
| 19 | 18 |
| 20 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD
rawing) { | |
| 21 /* | |
| 22 The fractional coverage is f. | |
| 23 The src and dst coeffs are Cs and Cd. | |
| 24 The dst and src colors are S and D. | |
| 25 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha | |
| 26 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second | |
| 27 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we | |
| 28 find that only 1, ISA, and ISC produce the correct destination when applied
to S' and D. | |
| 29 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag
e is treated as | |
| 30 color by definition. | |
| 31 */ | |
| 32 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera
geDrawing here | |
| 33 return kOne_GrBlendCoeff == dstCoeff || | |
| 34 kISA_GrBlendCoeff == dstCoeff || | |
| 35 kISC_GrBlendCoeff == dstCoeff || | |
| 36 isCoverageDrawing; | |
| 37 } | |
| 38 | |
| 39 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { | 19 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { |
| 40 public: | 20 public: |
| 41 GrGLPorterDuffXferProcessor(const GrProcessor&) {} | 21 GrGLPorterDuffXferProcessor(const GrProcessor&) {} |
| 42 | 22 |
| 43 virtual ~GrGLPorterDuffXferProcessor() {} | 23 virtual ~GrGLPorterDuffXferProcessor() {} |
| 44 | 24 |
| 45 virtual void emitCode(GrGLFPBuilder* builder, | 25 virtual void emitCode(GrGLFPBuilder* builder, |
| 46 const GrFragmentProcessor& fp, | 26 const GrFragmentProcessor& fp, |
| 47 const char* outputColor, | 27 const char* outputColor, |
| 48 const char* inputColor, | 28 const char* inputColor, |
| 49 const TransformedCoordsArray& coords, | 29 const TransformedCoordsArray& coords, |
| 50 const TextureSamplerArray& samplers) SK_OVERRIDE { | 30 const TextureSamplerArray& samplers) SK_OVERRIDE { |
| 51 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 31 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
| 52 fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor); | 32 fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor); |
| 53 } | 33 } |
| 54 | 34 |
| 55 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O
VERRIDE {}; | 35 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O
VERRIDE {}; |
| 56 | 36 |
| 57 static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyB
uilder* b) {}; | 37 static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyB
uilder* b) {}; |
| 58 | 38 |
| 59 private: | 39 private: |
| 60 typedef GrGLXferProcessor INHERITED; | 40 typedef GrGLXferProcessor INHERITED; |
| 61 }; | 41 }; |
| 62 | 42 |
| 63 /////////////////////////////////////////////////////////////////////////////// | 43 /////////////////////////////////////////////////////////////////////////////// |
| 64 | 44 |
| 65 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl
endCoeff dstBlend, | 45 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl
endCoeff dstBlend) |
| 66 GrColor constant) | 46 : fSrcBlend(srcBlend), fDstBlend(dstBlend) { |
| 67 : fSrcBlend(srcBlend), fDstBlend(dstBlend), fBlendConstant(constant) { | |
| 68 this->initClassID<GrPorterDuffXferProcessor>(); | 47 this->initClassID<GrPorterDuffXferProcessor>(); |
| 69 } | 48 } |
| 70 | 49 |
| 71 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() { | 50 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() { |
| 72 } | 51 } |
| 73 | 52 |
| 74 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, | 53 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, |
| 75 GrProcessorKeyBuilder* b) cons
t { | 54 GrProcessorKeyBuilder* b) cons
t { |
| 76 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); | 55 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); |
| 77 } | 56 } |
| 78 | 57 |
| 79 GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const { | 58 GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const { |
| 80 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); | 59 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); |
| 81 } | 60 } |
| 82 | 61 |
| 83 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { | 62 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { |
| 84 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 63 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); |
| 85 } | 64 } |
| 86 | 65 |
| 87 GrXferProcessor::OptFlags | |
| 88 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, | |
| 89 const GrProcOptInfo& coveragePOI, | |
| 90 bool isCoverageDrawing, | |
| 91 bool colorWriteDisabled, | |
| 92 bool doesStencilWrite, | |
| 93 GrColor* color, uint8_t* coverage) { | |
| 94 if (colorWriteDisabled) { | |
| 95 fSrcBlend = kZero_GrBlendCoeff; | |
| 96 fDstBlend = kOne_GrBlendCoeff; | |
| 97 } | |
| 98 | |
| 99 bool srcAIsOne; | |
| 100 bool hasCoverage; | |
| 101 if (isCoverageDrawing) { | |
| 102 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); | |
| 103 hasCoverage = false; | |
| 104 } else { | |
| 105 srcAIsOne = colorPOI.isOpaque(); | |
| 106 hasCoverage = !coveragePOI.isSolidWhite(); | |
| 107 } | |
| 108 | |
| 109 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | |
| 110 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | |
| 111 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | |
| 112 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | |
| 113 | |
| 114 // Optimizations when doing RGB Coverage | |
| 115 if (!coveragePOI.isSingleComponent()) { | |
| 116 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | |
| 117 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | |
| 118 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | |
| 119 // output is already baked into the blendConstant. | |
| 120 uint8_t alpha = GrColorUnpackA(fBlendConstant); | |
| 121 *color = GrColorPackRGBA(alpha, alpha, alpha, alpha); | |
| 122 return GrXferProcessor::kClearColorStages_OptFlag; | |
| 123 } | |
| 124 | |
| 125 // When coeffs are (0,1) there is no reason to draw at all, unless | |
| 126 // stenciling is enabled. Having color writes disabled is effectively | |
| 127 // (0,1). | |
| 128 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | |
| 129 if (doesStencilWrite) { | |
| 130 *color = 0xffffffff; | |
| 131 return GrXferProcessor::kClearColorStages_OptFlag | | |
| 132 GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 133 } else { | |
| 134 fDstBlend = kOne_GrBlendCoeff; | |
| 135 return GrXferProcessor::kSkipDraw_OptFlag; | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 // if we don't have coverage we can check whether the dst | |
| 140 // has to read at all. If not, we'll disable blending. | |
| 141 if (!hasCoverage) { | |
| 142 if (dstCoeffIsZero) { | |
| 143 if (kOne_GrBlendCoeff == fSrcBlend) { | |
| 144 // if there is no coverage and coeffs are (1,0) then we | |
| 145 // won't need to read the dst at all, it gets replaced by src | |
| 146 fDstBlend = kZero_GrBlendCoeff; | |
| 147 return GrXferProcessor::kNone_Opt; | |
| 148 } else if (kZero_GrBlendCoeff == fSrcBlend) { | |
| 149 // if the op is "clear" then we don't need to emit a color | |
| 150 // or blend, just write transparent black into the dst. | |
| 151 fSrcBlend = kOne_GrBlendCoeff; | |
| 152 fDstBlend = kZero_GrBlendCoeff; | |
| 153 *color = 0; | |
| 154 *coverage = 0xff; | |
| 155 return GrXferProcessor::kClearColorStages_OptFlag | | |
| 156 GrXferProcessor::kClearCoverageStages_OptFlag; | |
| 157 } | |
| 158 } | |
| 159 } else if (isCoverageDrawing) { | |
| 160 // we have coverage but we aren't distinguishing it from alpha by reques
t. | |
| 161 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 162 } else { | |
| 163 // check whether coverage can be safely rolled into alpha | |
| 164 // of if we can skip color computation and just emit coverage | |
| 165 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { | |
| 166 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 167 } | |
| 168 if (dstCoeffIsZero) { | |
| 169 if (kZero_GrBlendCoeff == fSrcBlend) { | |
| 170 // the source color is not included in the blend | |
| 171 // the dst coeff is effectively zero so blend works out to: | |
| 172 // (c)(0)D + (1-c)D = (1-c)D. | |
| 173 fDstBlend = kISA_GrBlendCoeff; | |
| 174 *color = 0xffffffff; | |
| 175 return GrXferProcessor::kClearColorStages_OptFlag | | |
| 176 GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 177 } else if (srcAIsOne) { | |
| 178 // the dst coeff is effectively zero so blend works out to: | |
| 179 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. | |
| 180 // If Sa is 1 then we can replace Sa with c | |
| 181 // and set dst coeff to 1-Sa. | |
| 182 fDstBlend = kISA_GrBlendCoeff; | |
| 183 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 184 } | |
| 185 } else if (dstCoeffIsOne) { | |
| 186 // the dst coeff is effectively one so blend works out to: | |
| 187 // cS + (c)(1)D + (1-c)D = cS + D. | |
| 188 fDstBlend = kOne_GrBlendCoeff; | |
| 189 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 return GrXferProcessor::kNone_Opt; | |
| 194 } | |
| 195 /////////////////////////////////////////////////////////////////////////////// | 66 /////////////////////////////////////////////////////////////////////////////// |
| 196 | 67 |
| 197 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) | 68 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) |
| 198 : fSrcCoeff(src), fDstCoeff(dst) { | 69 : fSrc(src), fDst(dst) { |
| 199 this->initClassID<GrPorterDuffXPFactory>(); | 70 this->initClassID<GrPorterDuffXPFactory>(); |
| 200 } | 71 } |
| 201 | 72 |
| 202 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { | 73 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { |
| 203 switch (mode) { | 74 switch (mode) { |
| 204 case SkXfermode::kClear_Mode: { | 75 case SkXfermode::kClear_Mode: { |
| 205 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G
rBlendCoeff); | 76 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G
rBlendCoeff); |
| 206 return SkRef(&gClearPDXPF); | 77 return SkRef(&gClearPDXPF); |
| 207 break; | 78 break; |
| 208 } | 79 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 case SkXfermode::kScreen_Mode: { | 145 case SkXfermode::kScreen_Mode: { |
| 275 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr
BlendCoeff); | 146 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr
BlendCoeff); |
| 276 return SkRef(&gScreenPDXPF); | 147 return SkRef(&gScreenPDXPF); |
| 277 break; | 148 break; |
| 278 } | 149 } |
| 279 default: | 150 default: |
| 280 return NULL; | 151 return NULL; |
| 281 } | 152 } |
| 282 } | 153 } |
| 283 | 154 |
| 284 GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor(const GrProcOptInfo&
colorPOI, | 155 const GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor() const { |
| 285 const GrProcOptInfo&
covPOI) const { | 156 return GrPorterDuffXferProcessor::Create(fSrc, fDst); |
| 286 if (covPOI.isSingleComponent()) { | |
| 287 return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff); | |
| 288 } else { | |
| 289 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags()))
{ | |
| 290 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); | |
| 291 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); | |
| 292 return GrPorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_
GrBlendCoeff, | |
| 293 blendConstant); | |
| 294 } else { | |
| 295 return NULL; | |
| 296 } | |
| 297 } | |
| 298 } | 157 } |
| 299 | 158 |
| 300 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, | 159 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, |
| 301 uint32_t knownColorFlags) const
{ | 160 uint32_t knownColorFlags) const
{ |
| 302 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && | 161 if (kOne_GrBlendCoeff == fSrc && kISA_GrBlendCoeff == fDst && |
| 303 kRGBA_GrColorComponentFlags == knownColorFlags) { | 162 kRGBA_GrColorComponentFlags == knownColorFlags) { |
| 304 return true; | 163 return true; |
| 305 } | 164 } |
| 306 return false; | 165 return false; |
| 307 } | 166 } |
| 308 | 167 |
| 309 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, | |
| 310 const GrProcOptInfo& coveragePOI, | |
| 311 bool isCoverageDrawing, | |
| 312 bool colorWriteDisabled) const { | |
| 313 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i
sOpaque()); | |
| 314 | |
| 315 if (colorWriteDisabled) { | |
| 316 return true; | |
| 317 } | |
| 318 | |
| 319 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || | |
| 320 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
| 321 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || | |
| 322 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
| 323 | |
| 324 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { | |
| 325 return true; | |
| 326 } | |
| 327 | |
| 328 // if we don't have coverage we can check whether the dst | |
| 329 // has to read at all. | |
| 330 if (isCoverageDrawing) { | |
| 331 // we have coverage but we aren't distinguishing it from alpha by reques
t. | |
| 332 return true; | |
| 333 } else { | |
| 334 // check whether coverage can be safely rolled into alpha | |
| 335 // of if we can skip color computation and just emit coverage | |
| 336 if (this->canTweakAlphaForCoverage(isCoverageDrawing)) { | |
| 337 return true; | |
| 338 } | |
| 339 if (dstCoeffIsZero) { | |
| 340 if (kZero_GrBlendCoeff == fSrcCoeff) { | |
| 341 return true; | |
| 342 } else if (srcAIsOne) { | |
| 343 return true; | |
| 344 } | |
| 345 } else if (dstCoeffIsOne) { | |
| 346 return true; | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's | |
| 351 // will readDst and PD XP's don't read dst. | |
| 352 if ((colorPOI.readsDst() || coveragePOI.readsDst()) && | |
| 353 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) { | |
| 354 return true; | |
| 355 } | |
| 356 | |
| 357 return false; | |
| 358 } | |
| 359 | |
| 360 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI, | |
| 361 const GrProcOptInfo& coveragePOI, | |
| 362 bool isCoverageDrawing, | |
| 363 bool colorWriteDisabled) const { | |
| 364 if (!(isCoverageDrawing || coveragePOI.isSolidWhite())) { | |
| 365 return true; | |
| 366 } | |
| 367 | |
| 368 // TODO: once all SkXferEffects are XP's then we will never reads dst here s
ince only XP's | |
| 369 // will readDst and PD XP's don't read dst. | |
| 370 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst())
{ | |
| 371 return true; | |
| 372 } | |
| 373 | |
| 374 if (GrBlendCoeffRefsDst(fSrcCoeff)) { | |
| 375 return true; | |
| 376 } | |
| 377 | |
| 378 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i
sOpaque()); | |
| 379 | |
| 380 if (!(kZero_GrBlendCoeff == fDstCoeff || | |
| 381 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) { | |
| 382 return true; | |
| 383 } | |
| 384 | |
| 385 return false; | |
| 386 } | |
| 387 | |
| 388 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage(bool isCoverageDrawing) con
st { | |
| 389 return can_tweak_alpha_for_coverage(fDstCoeff, isCoverageDrawing); | |
| 390 } | |
| 391 | |
| 392 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI
, | |
| 393 const GrProcOptInfo& coverage
POI, | |
| 394 GrColor* solidColor, | |
| 395 uint32_t* solidColorKnownComp
onents) const { | |
| 396 if (!coveragePOI.isSolidWhite()) { | |
| 397 return false; | |
| 398 } | |
| 399 | |
| 400 SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents)); | |
| 401 | |
| 402 GrBlendCoeff srcCoeff = fSrcCoeff; | |
| 403 GrBlendCoeff dstCoeff = fDstCoeff; | |
| 404 | |
| 405 // TODO: figure out to merge this simplify with other current optimization c
ode paths and | |
| 406 // eventually remove from GrBlend | |
| 407 GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags(
), | |
| 408 0, 0, 0); | |
| 409 | |
| 410 bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoef
f); | |
| 411 if (solidColor) { | |
| 412 if (opaque) { | |
| 413 switch (srcCoeff) { | |
| 414 case kZero_GrBlendCoeff: | |
| 415 *solidColor = 0; | |
| 416 *solidColorKnownComponents = kRGBA_GrColorComponentFlags; | |
| 417 break; | |
| 418 | |
| 419 case kOne_GrBlendCoeff: | |
| 420 *solidColor = colorPOI.color(); | |
| 421 *solidColorKnownComponents = colorPOI.validFlags(); | |
| 422 break; | |
| 423 | |
| 424 // The src coeff should never refer to the src and if it refers
to dst then opaque | |
| 425 // should have been false. | |
| 426 case kSC_GrBlendCoeff: | |
| 427 case kISC_GrBlendCoeff: | |
| 428 case kDC_GrBlendCoeff: | |
| 429 case kIDC_GrBlendCoeff: | |
| 430 case kSA_GrBlendCoeff: | |
| 431 case kISA_GrBlendCoeff: | |
| 432 case kDA_GrBlendCoeff: | |
| 433 case kIDA_GrBlendCoeff: | |
| 434 default: | |
| 435 SkFAIL("srcCoeff should not refer to src or dst."); | |
| 436 break; | |
| 437 | |
| 438 // TODO: update this once GrPaint actually has a const color. | |
| 439 case kConstC_GrBlendCoeff: | |
| 440 case kIConstC_GrBlendCoeff: | |
| 441 case kConstA_GrBlendCoeff: | |
| 442 case kIConstA_GrBlendCoeff: | |
| 443 *solidColorKnownComponents = 0; | |
| 444 break; | |
| 445 } | |
| 446 } else { | |
| 447 solidColorKnownComponents = 0; | |
| 448 } | |
| 449 } | |
| 450 return opaque; | |
| 451 } | |
| 452 | |
| 453 | |
| OLD | NEW |