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 |