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" |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), | 281 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), |
282 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out
putType), | 282 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out
putType), |
283 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), | 283 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), |
284 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), | 284 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), |
285 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), | 285 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), |
286 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), | 286 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), |
287 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_
OutputType), | 287 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_
OutputType), |
288 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), | 288 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), |
289 }}}; | 289 }}}; |
290 | 290 |
291 static BlendFormula get_blend_formula(SkXfermode::Mode xfermode, | 291 static BlendFormula get_blend_formula(const GrProcOptInfo& colorPOI, |
292 const GrProcOptInfo& colorPOI, | 292 const GrProcOptInfo& coveragePOI, |
293 const GrProcOptInfo& coveragePOI) { | 293 bool hasMixedSamples, |
| 294 SkXfermode::Mode xfermode) { |
294 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); | 295 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); |
295 SkASSERT(!coveragePOI.isFourChannelOutput()); | 296 SkASSERT(!coveragePOI.isFourChannelOutput()); |
296 | 297 |
297 return gBlendTable[colorPOI.isOpaque()][!coveragePOI.isSolidWhite()][xfermod
e]; | 298 bool conflatesCoverage = !coveragePOI.isSolidWhite() || hasMixedSamples; |
| 299 return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode]; |
298 } | 300 } |
299 | 301 |
300 /////////////////////////////////////////////////////////////////////////////// | 302 /////////////////////////////////////////////////////////////////////////////// |
301 | 303 |
302 class PorterDuffXferProcessor : public GrXferProcessor { | 304 class PorterDuffXferProcessor : public GrXferProcessor { |
303 public: | 305 public: |
304 static GrXferProcessor* Create(BlendFormula blendFormula) { | 306 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendForm
ula) { |
305 return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula)); | 307 this->initClassID<PorterDuffXferProcessor>(); |
306 } | 308 } |
307 | 309 |
308 const char* name() const override { return "Porter Duff"; } | 310 const char* name() const override { return "Porter Duff"; } |
309 | 311 |
310 GrGLXferProcessor* createGLInstance() const override; | 312 GrGLXferProcessor* createGLInstance() const override; |
311 | 313 |
312 BlendFormula getBlendFormula() const { return fBlendFormula; } | 314 BlendFormula getBlendFormula() const { return fBlendFormula; } |
313 | 315 |
314 private: | 316 private: |
315 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendForm
ula) { | |
316 this->initClassID<PorterDuffXferProcessor>(); | |
317 } | |
318 | |
319 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, | 317 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
320 const GrProcOptInfo& coveragePO
I, | 318 const GrProcOptInfo& coveragePO
I, |
321 bool doesStencilWrite, | 319 bool doesStencilWrite, |
322 GrColor* overrideColor, | 320 GrColor* overrideColor, |
323 const GrCaps& caps) override; | 321 const GrCaps& caps) override; |
324 | 322 |
325 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; | 323 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; |
326 | 324 |
327 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSeconda
ryOutput(); } | 325 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSeconda
ryOutput(); } |
328 | 326 |
(...skipping 17 matching lines...) Expand all Loading... |
346 /////////////////////////////////////////////////////////////////////////////// | 344 /////////////////////////////////////////////////////////////////////////////// |
347 | 345 |
348 static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen
tBuilder* fsBuilder, | 346 static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen
tBuilder* fsBuilder, |
349 BlendFormula::OutputType outputType, const char*
output, | 347 BlendFormula::OutputType outputType, const char*
output, |
350 const char* inColor, const char* inCoverage) { | 348 const char* inColor, const char* inCoverage) { |
351 switch (outputType) { | 349 switch (outputType) { |
352 case BlendFormula::kNone_OutputType: | 350 case BlendFormula::kNone_OutputType: |
353 fsBuilder->codeAppendf("%s = vec4(0.0);", output); | 351 fsBuilder->codeAppendf("%s = vec4(0.0);", output); |
354 break; | 352 break; |
355 case BlendFormula::kCoverage_OutputType: | 353 case BlendFormula::kCoverage_OutputType: |
| 354 // We can have a coverage formula while not reading coverage if ther
e are mixed samples. |
356 fsBuilder->codeAppendf("%s = %s;", | 355 fsBuilder->codeAppendf("%s = %s;", |
357 output, xp.readsCoverage() ? inCoverage : "ve
c4(1.0)"); | 356 output, xp.readsCoverage() ? inCoverage : "ve
c4(1.0)"); |
358 break; | 357 break; |
359 case BlendFormula::kModulate_OutputType: | 358 case BlendFormula::kModulate_OutputType: |
360 if (xp.readsCoverage()) { | 359 if (xp.readsCoverage()) { |
361 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover
age); | 360 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover
age); |
362 } else { | 361 } else { |
363 fsBuilder->codeAppendf("%s = %s;", output, inColor); | 362 fsBuilder->codeAppendf("%s = %s;", output, inColor); |
364 } | 363 } |
365 break; | 364 break; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; | 447 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; |
449 } | 448 } |
450 } | 449 } |
451 return optFlags; | 450 return optFlags; |
452 } | 451 } |
453 | 452 |
454 /////////////////////////////////////////////////////////////////////////////// | 453 /////////////////////////////////////////////////////////////////////////////// |
455 | 454 |
456 class ShaderPDXferProcessor : public GrXferProcessor { | 455 class ShaderPDXferProcessor : public GrXferProcessor { |
457 public: | 456 public: |
458 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const DstTexture*
dstTexture) { | 457 ShaderPDXferProcessor(const DstTexture* dstTexture, |
459 return SkNEW_ARGS(ShaderPDXferProcessor, (xfermode, dstTexture)); | 458 bool hasMixedSamples, |
| 459 SkXfermode::Mode xfermode) |
| 460 : INHERITED(dstTexture, true, hasMixedSamples) |
| 461 , fXfermode(xfermode) { |
| 462 this->initClassID<ShaderPDXferProcessor>(); |
460 } | 463 } |
461 | 464 |
462 const char* name() const override { return "Porter Duff Shader"; } | 465 const char* name() const override { return "Porter Duff Shader"; } |
463 | 466 |
464 GrGLXferProcessor* createGLInstance() const override; | 467 GrGLXferProcessor* createGLInstance() const override; |
465 | 468 |
466 SkXfermode::Mode getXfermode() const { return fXfermode; } | 469 SkXfermode::Mode getXfermode() const { return fXfermode; } |
467 | 470 |
468 private: | 471 private: |
469 ShaderPDXferProcessor(SkXfermode::Mode xfermode, const DstTexture* dstTextur
e) | |
470 : INHERITED(dstTexture, true) | |
471 , fXfermode(xfermode) { | |
472 this->initClassID<ShaderPDXferProcessor>(); | |
473 } | |
474 | |
475 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP
rocOptInfo&, | 472 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP
rocOptInfo&, |
476 bool, GrColor*, const GrCaps&)
override { | 473 bool, GrColor*, const GrCaps&)
override { |
477 return kNone_Opt; | 474 return kNone_Opt; |
478 } | 475 } |
479 | 476 |
480 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; | 477 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; |
481 | 478 |
482 bool onIsEqual(const GrXferProcessor& xpBase) const override { | 479 bool onIsEqual(const GrXferProcessor& xpBase) const override { |
483 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); | 480 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); |
484 return fXfermode == xp.fXfermode; | 481 return fXfermode == xp.fXfermode; |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { | 728 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { |
732 return NULL; | 729 return NULL; |
733 } | 730 } |
734 return SkRef(gFactories[xfermode]); | 731 return SkRef(gFactories[xfermode]); |
735 } | 732 } |
736 | 733 |
737 GrXferProcessor* | 734 GrXferProcessor* |
738 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, | 735 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, |
739 const GrProcOptInfo& colorPOI, | 736 const GrProcOptInfo& colorPOI, |
740 const GrProcOptInfo& covPOI, | 737 const GrProcOptInfo& covPOI, |
| 738 bool hasMixedSamples, |
741 const DstTexture* dstTexture) const
{ | 739 const DstTexture* dstTexture) const
{ |
742 if (covPOI.isFourChannelOutput()) { | 740 if (covPOI.isFourChannelOutput()) { |
743 SkASSERT(!dstTexture || !dstTexture->texture()); | 741 SkASSERT(!dstTexture || !dstTexture->texture()); |
744 return PDLCDXferProcessor::Create(fXfermode, colorPOI); | 742 return PDLCDXferProcessor::Create(fXfermode, colorPOI); |
745 } | 743 } |
746 | 744 |
747 BlendFormula blendFormula = get_blend_formula(fXfermode, colorPOI, covPOI); | 745 BlendFormula blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamp
les, fXfermode); |
748 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend
ingSupport()) { | 746 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend
ingSupport()) { |
749 return ShaderPDXferProcessor::Create(fXfermode, dstTexture); | 747 return SkNEW_ARGS(ShaderPDXferProcessor, (dstTexture, hasMixedSamples, f
Xfermode)); |
750 } | 748 } |
751 | 749 |
752 SkASSERT(!dstTexture || !dstTexture->texture()); | 750 SkASSERT(!dstTexture || !dstTexture->texture()); |
753 return PorterDuffXferProcessor::Create(blendFormula); | 751 return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula)); |
754 } | 752 } |
755 | 753 |
756 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, | 754 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, |
757 uint32_t knownColorFlags) const
{ | 755 uint32_t knownColorFlags) const
{ |
758 if (SkXfermode::kSrcOver_Mode == fXfermode && | 756 if (SkXfermode::kSrcOver_Mode == fXfermode && |
759 kRGBA_GrColorComponentFlags == knownColorFlags) { | 757 kRGBA_GrColorComponentFlags == knownColorFlags) { |
760 return true; | 758 return true; |
761 } | 759 } |
762 return false; | 760 return false; |
763 } | 761 } |
(...skipping 24 matching lines...) Expand all Loading... |
788 return; | 786 return; |
789 | 787 |
790 default: | 788 default: |
791 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | 789 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
792 return; | 790 return; |
793 } | 791 } |
794 } | 792 } |
795 | 793 |
796 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, | 794 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, |
797 const GrProcOptInfo& colorPOI, | 795 const GrProcOptInfo& colorPOI, |
798 const GrProcOptInfo& coveragePOI) c
onst { | 796 const GrProcOptInfo& covPOI, |
799 if (coveragePOI.isFourChannelOutput()) { | 797 bool hasMixedSamples) const { |
800 return false; // The LCD XP never does a dst read. | 798 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
| 799 return false; |
801 } | 800 } |
802 | 801 if (covPOI.isFourChannelOutput()) { |
| 802 return false; // The LCD XP will abort rather than doing a dst read. |
| 803 } |
803 // We fallback on the shader XP when the blend formula would use dual source
blending but we | 804 // We fallback on the shader XP when the blend formula would use dual source
blending but we |
804 // don't have support for it. | 805 // don't have support for it. |
805 return !caps.shaderCaps()->dualSourceBlendingSupport() && | 806 return get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode).hasSe
condaryOutput(); |
806 get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutpu
t(); | |
807 } | 807 } |
808 | 808 |
809 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 809 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
810 | 810 |
811 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, | 811 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
812 GrContext*, | 812 GrContext*, |
813 const GrCaps&, | 813 const GrCaps&, |
814 GrTexture*[]) { | 814 GrTexture*[]) { |
815 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k
LastCoeffMode)); | 815 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k
LastCoeffMode)); |
816 return GrPorterDuffXPFactory::Create(mode); | 816 return GrPorterDuffXPFactory::Create(mode); |
817 } | 817 } |
818 | 818 |
819 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, | 819 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, |
820 int* outPrimary, | 820 int* outPrimary, |
821 int* outSecondary) { | 821 int* outSecondary) { |
822 if (!!strcmp(xp->name(), "Porter Duff")) { | 822 if (!!strcmp(xp->name(), "Porter Duff")) { |
823 *outPrimary = *outSecondary = -1; | 823 *outPrimary = *outSecondary = -1; |
824 return; | 824 return; |
825 } | 825 } |
826 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)-
>getBlendFormula(); | 826 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)-
>getBlendFormula(); |
827 *outPrimary = blendFormula.fPrimaryOutputType; | 827 *outPrimary = blendFormula.fPrimaryOutputType; |
828 *outSecondary = blendFormula.fSecondaryOutputType; | 828 *outSecondary = blendFormula.fSecondaryOutputType; |
829 } | 829 } |
830 | 830 |
OLD | NEW |