| 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 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | 684 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
| 685 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | 685 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
| 686 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | 686 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
| 687 // output is already baked into the blendConstant. | 687 // output is already baked into the blendConstant. |
| 688 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); | 688 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); |
| 689 return GrXferProcessor::kOverrideColor_OptFlag; | 689 return GrXferProcessor::kOverrideColor_OptFlag; |
| 690 } | 690 } |
| 691 | 691 |
| 692 /////////////////////////////////////////////////////////////////////////////// | 692 /////////////////////////////////////////////////////////////////////////////// |
| 693 | 693 |
| 694 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode) | 694 GrPDXPFactory::GrPDXPFactory(SkXfermode::Mode xfermode) |
| 695 : fXfermode(xfermode) { | 695 : fXfermode(xfermode) { |
| 696 SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode); | 696 SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode); |
| 697 this->initClassID<GrPorterDuffXPFactory>(); | 697 this->initClassID<GrPDXPFactory>(); |
| 698 } | 698 } |
| 699 | 699 |
| 700 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) { | 700 const GrXPFactory* GrPDXPFactory::Create(SkXfermode::Mode xfermode) { |
| 701 static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode); | 701 static const GrPDXPFactory gClearPDXPF(SkXfermode::kClear_Mode); |
| 702 static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); | 702 static const GrPDXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); |
| 703 static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode); | 703 static const GrPDXPFactory gDstPDXPF(SkXfermode::kDst_Mode); |
| 704 static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); | 704 static const GrPDXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); |
| 705 static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); | 705 static const GrPDXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); |
| 706 static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); | 706 static const GrPDXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); |
| 707 static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); | 707 static const GrPDXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); |
| 708 static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); | 708 static const GrPDXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); |
| 709 static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); | 709 static const GrPDXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); |
| 710 static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); | 710 static const GrPDXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); |
| 711 static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); | 711 static const GrPDXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); |
| 712 static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode); | 712 static const GrPDXPFactory gXorPDXPF(SkXfermode::kXor_Mode); |
| 713 static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); | 713 static const GrPDXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); |
| 714 static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); | 714 static const GrPDXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); |
| 715 static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); | 715 static const GrPDXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); |
| 716 | 716 |
| 717 static GrPorterDuffXPFactory* gFactories[] = { | 717 static const GrPDXPFactory* gFactories[] = { |
| 718 &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &g
SrcInPDXPF, | 718 &gClearPDXPF, &gSrcPDXPF, &gDstPDXPF, &gSrcOverPDXPF, &gDstOverPDXPF, &g
SrcInPDXPF, |
| 719 &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDX
PF, &gXorPDXPF, | 719 &gDstInPDXPF, &gSrcOutPDXPF, &gDstOutPDXPF, &gSrcATopPDXPF, &gDstATopPDX
PF, &gXorPDXPF, |
| 720 &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF | 720 &gPlusPDXPF, &gModulatePDXPF, &gScreenPDXPF |
| 721 }; | 721 }; |
| 722 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode +
1); | 722 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode +
1); |
| 723 | 723 |
| 724 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { | 724 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { |
| 725 return nullptr; | 725 return nullptr; |
| 726 } | 726 } |
| 727 return SkRef(gFactories[xfermode]); | 727 return SkRef(gFactories[xfermode]); |
| 728 } | 728 } |
| 729 | 729 |
| 730 GrXferProcessor* | 730 GrXferProcessor* |
| 731 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, | 731 GrPDXPFactory::onCreateXferProcessor(const GrCaps& caps, |
| 732 const GrProcOptInfo& colorPOI, | 732 const GrProcOptInfo& colorPOI, |
| 733 const GrProcOptInfo& covPOI, | 733 const GrProcOptInfo& covPOI, |
| 734 bool hasMixedSamples, | 734 bool hasMixedSamples, |
| 735 const DstTexture* dstTexture) const
{ | 735 const DstTexture* dstTexture) const
{ |
| 736 BlendFormula blendFormula; | 736 BlendFormula blendFormula; |
| 737 if (covPOI.isFourChannelOutput()) { | 737 if (covPOI.isFourChannelOutput()) { |
| 738 if (SkXfermode::kSrcOver_Mode == fXfermode && | 738 if (SkXfermode::kSrcOver_Mode == fXfermode && |
| 739 kRGBA_GrColorComponentFlags == colorPOI.validFlags() && | 739 kRGBA_GrColorComponentFlags == colorPOI.validFlags() && |
| 740 !caps.shaderCaps()->dualSourceBlendingSupport() && | 740 !caps.shaderCaps()->dualSourceBlendingSupport() && |
| 741 !caps.shaderCaps()->dstReadInShaderSupport()) { | 741 !caps.shaderCaps()->dstReadInShaderSupport()) { |
| 742 // If we don't have dual source blending or in shader dst reads, we
fall back to this | 742 // If we don't have dual source blending or in shader dst reads, we
fall back to this |
| 743 // trick for rendering SrcOver LCD text instead of doing a dst copy. | 743 // trick for rendering SrcOver LCD text instead of doing a dst copy. |
| 744 SkASSERT(!dstTexture || !dstTexture->texture()); | 744 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 745 return PDLCDXferProcessor::Create(fXfermode, colorPOI); | 745 return PDLCDXferProcessor::Create(fXfermode, colorPOI); |
| 746 } | 746 } |
| 747 blendFormula = get_lcd_blend_formula(covPOI, fXfermode); | 747 blendFormula = get_lcd_blend_formula(covPOI, fXfermode); |
| 748 } else { | 748 } else { |
| 749 blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfe
rmode); | 749 blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfe
rmode); |
| 750 } | 750 } |
| 751 | 751 |
| 752 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend
ingSupport()) { | 752 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend
ingSupport()) { |
| 753 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode)
; | 753 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fXfermode)
; |
| 754 } | 754 } |
| 755 | 755 |
| 756 SkASSERT(!dstTexture || !dstTexture->texture()); | 756 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 757 return new PorterDuffXferProcessor(blendFormula); | 757 return new PorterDuffXferProcessor(blendFormula); |
| 758 } | 758 } |
| 759 | 759 |
| 760 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorP
OI, | 760 void GrPDXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, |
| 761 InvariantBlendedColor* blen
dedColor) const { | 761 InvariantBlendedColor* blen
dedColor) const { |
| 762 // Find the blended color info based on the formula that does not have cover
age. | 762 // Find the blended color info based on the formula that does not have cover
age. |
| 763 BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode]; | 763 BlendFormula colorFormula = gBlendTable[colorPOI.isOpaque()][0][fXfermode]; |
| 764 if (colorFormula.usesDstColor()) { | 764 if (colorFormula.usesDstColor()) { |
| 765 blendedColor->fWillBlendWithDst = true; | 765 blendedColor->fWillBlendWithDst = true; |
| 766 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | 766 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
| 767 return; | 767 return; |
| 768 } | 768 } |
| 769 | 769 |
| 770 blendedColor->fWillBlendWithDst = false; | 770 blendedColor->fWillBlendWithDst = false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 781 blendedColor->fKnownColor = colorPOI.color(); | 781 blendedColor->fKnownColor = colorPOI.color(); |
| 782 blendedColor->fKnownColorFlags = colorPOI.validFlags(); | 782 blendedColor->fKnownColorFlags = colorPOI.validFlags(); |
| 783 return; | 783 return; |
| 784 | 784 |
| 785 default: | 785 default: |
| 786 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | 786 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
| 787 return; | 787 return; |
| 788 } | 788 } |
| 789 } | 789 } |
| 790 | 790 |
| 791 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, | 791 bool GrPDXPFactory::willReadDstColor(const GrCaps& caps, |
| 792 const GrProcOptInfo& colorPOI, | 792 const GrProcOptInfo& colorPOI, |
| 793 const GrProcOptInfo& covPOI, | 793 const GrProcOptInfo& covPOI, |
| 794 bool hasMixedSamples) const { | 794 bool hasMixedSamples) const { |
| 795 if (caps.shaderCaps()->dualSourceBlendingSupport()) { | 795 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
| 796 return false; | 796 return false; |
| 797 } | 797 } |
| 798 | 798 |
| 799 // When we have four channel coverage we always need to read the dst in orde
r to correctly | 799 // When we have four channel coverage we always need to read the dst in orde
r to correctly |
| 800 // blend. The one exception is when we are using srcover mode and we know th
e input color into | 800 // blend. The one exception is when we are using srcover mode and we know th
e input color into |
| 801 // the XP. | 801 // the XP. |
| 802 if (covPOI.isFourChannelOutput()) { | 802 if (covPOI.isFourChannelOutput()) { |
| 803 if (SkXfermode::kSrcOver_Mode == fXfermode && | 803 if (SkXfermode::kSrcOver_Mode == fXfermode && |
| 804 kRGBA_GrColorComponentFlags == colorPOI.validFlags() && | 804 kRGBA_GrColorComponentFlags == colorPOI.validFlags() && |
| 805 !caps.shaderCaps()->dstReadInShaderSupport()) { | 805 !caps.shaderCaps()->dstReadInShaderSupport()) { |
| 806 return false; | 806 return false; |
| 807 } | 807 } |
| 808 return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput(); | 808 return get_lcd_blend_formula(covPOI, fXfermode).hasSecondaryOutput(); |
| 809 } | 809 } |
| 810 // We fallback on the shader XP when the blend formula would use dual source
blending but we | 810 // We fallback on the shader XP when the blend formula would use dual source
blending but we |
| 811 // don't have support for it. | 811 // don't have support for it. |
| 812 return get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode).hasSe
condaryOutput(); | 812 return get_blend_formula(colorPOI, covPOI, hasMixedSamples, fXfermode).hasSe
condaryOutput(); |
| 813 } | 813 } |
| 814 | 814 |
| 815 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 815 GR_DEFINE_XP_FACTORY_TEST(GrPDXPFactory); |
| 816 | 816 |
| 817 const GrXPFactory* GrPorterDuffXPFactory::TestCreate(GrProcessorTestData* d) { | 817 const GrXPFactory* GrPDXPFactory::TestCreate(GrProcessorTestData* d) { |
| 818 SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermod
e::kLastCoeffMode)); | 818 SkXfermode::Mode mode = SkXfermode::Mode(d->fRandom->nextULessThan(SkXfermod
e::kLastCoeffMode)); |
| 819 return GrPorterDuffXPFactory::Create(mode); | 819 return GrPDXPFactory::Create(mode); |
| 820 } | 820 } |
| 821 | 821 |
| 822 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, | 822 void GrPDXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, |
| 823 int* outPrimary, | 823 int* outPrimary, |
| 824 int* outSecondary) { | 824 int* outSecondary) { |
| 825 if (!!strcmp(xp->name(), "Porter Duff")) { | 825 if (!!strcmp(xp->name(), "Porter Duff")) { |
| 826 *outPrimary = *outSecondary = -1; | 826 *outPrimary = *outSecondary = -1; |
| 827 return; | 827 return; |
| 828 } | 828 } |
| 829 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)-
>getBlendFormula(); | 829 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)-
>getBlendFormula(); |
| 830 *outPrimary = blendFormula.fPrimaryOutputType; | 830 *outPrimary = blendFormula.fPrimaryOutputType; |
| 831 *outSecondary = blendFormula.fSecondaryOutputType; | 831 *outSecondary = blendFormula.fSecondaryOutputType; |
| 832 } | 832 } |
| 833 |
| 834 //////////////////////////////////////////////////////////////////////////////// |
| 835 |
| 836 GrSrcOverPDXPFactory::GrSrcOverPDXPFactory() { |
| 837 this->initClassID<GrSrcOverPDXPFactory>(); |
| 838 } |
| 839 |
| 840 GrXferProcessor* |
| 841 GrSrcOverPDXPFactory::onCreateXferProcessor(const GrCaps& caps, |
| 842 const GrProcOptInfo& colorPOI, |
| 843 const GrProcOptInfo& covPOI, |
| 844 bool hasMixedSamples, |
| 845 const DstTexture* dstTexture) const
{ |
| 846 BlendFormula blendFormula; |
| 847 if (covPOI.isFourChannelOutput()) { |
| 848 if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() && |
| 849 !caps.shaderCaps()->dualSourceBlendingSupport() && |
| 850 !caps.shaderCaps()->dstReadInShaderSupport()) { |
| 851 // If we don't have dual source blending or in shader dst reads, we
fall back to this |
| 852 // trick for rendering SrcOver LCD text instead of doing a dst copy. |
| 853 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 854 return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, colorPO
I); |
| 855 } |
| 856 blendFormula = get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode); |
| 857 } else { |
| 858 blendFormula = get_blend_formula(colorPOI, covPOI, hasMixedSamples, |
| 859 SkXfermode::kSrcOver_Mode); |
| 860 } |
| 861 |
| 862 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend
ingSupport()) { |
| 863 return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkXfermode
::kSrcOver_Mode); |
| 864 } |
| 865 |
| 866 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 867 return new PorterDuffXferProcessor(blendFormula); |
| 868 } |
| 869 |
| 870 void GrSrcOverPDXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPO
I, |
| 871 InvariantBlendedColor* blend
edColor) const { |
| 872 if (!colorPOI.isOpaque()) { |
| 873 blendedColor->fWillBlendWithDst = true; |
| 874 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
| 875 return; |
| 876 } |
| 877 |
| 878 blendedColor->fWillBlendWithDst = false; |
| 879 |
| 880 blendedColor->fKnownColor = colorPOI.color(); |
| 881 blendedColor->fKnownColorFlags = colorPOI.validFlags(); |
| 882 } |
| 883 |
| 884 bool GrSrcOverPDXPFactory::willReadDstColor(const GrCaps& caps, |
| 885 const GrProcOptInfo& colorPOI, |
| 886 const GrProcOptInfo& covPOI, |
| 887 bool hasMixedSamples) const { |
| 888 if (caps.shaderCaps()->dualSourceBlendingSupport()) { |
| 889 return false; |
| 890 } |
| 891 |
| 892 // When we have four channel coverage we always need to read the dst in orde
r to correctly |
| 893 // blend. The one exception is when we are using srcover mode and we know th
e input color into |
| 894 // the XP. |
| 895 if (covPOI.isFourChannelOutput()) { |
| 896 if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() && |
| 897 !caps.shaderCaps()->dstReadInShaderSupport()) { |
| 898 return false; |
| 899 } |
| 900 return get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode).hasSecon
daryOutput(); |
| 901 } |
| 902 // We fallback on the shader XP when the blend formula would use dual source
blending but we |
| 903 // don't have support for it. |
| 904 return get_blend_formula(colorPOI, covPOI, |
| 905 hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSeco
ndaryOutput(); |
| 906 } |
| 907 |
| 908 GR_DEFINE_XP_FACTORY_TEST(GrSrcOverPDXPFactory); |
| 909 |
| 910 const GrXPFactory* GrSrcOverPDXPFactory::TestCreate(GrProcessorTestData* d) { |
| 911 return SkRef(&GrPorterDuffXPFactory::gSrcOverPDXPFactory); |
| 912 } |
| 913 |
| OLD | NEW |