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 GrPDXPFactory::GrPDXPFactory(SkXfermode::Mode xfermode) | 694 GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkXfermode::Mode xfermode) |
695 : fXfermode(xfermode) { | 695 : fXfermode(xfermode) { |
696 SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode); | 696 SkASSERT(fXfermode <= SkXfermode::kLastCoeffMode); |
697 this->initClassID<GrPDXPFactory>(); | 697 this->initClassID<GrPorterDuffXPFactory>(); |
698 } | 698 } |
699 | 699 |
700 const GrXPFactory* GrPDXPFactory::Create(SkXfermode::Mode xfermode) { | 700 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode xfermode) { |
701 static const GrPDXPFactory gClearPDXPF(SkXfermode::kClear_Mode); | 701 static GrPorterDuffXPFactory gClearPDXPF(SkXfermode::kClear_Mode); |
702 static const GrPDXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); | 702 static GrPorterDuffXPFactory gSrcPDXPF(SkXfermode::kSrc_Mode); |
703 static const GrPDXPFactory gDstPDXPF(SkXfermode::kDst_Mode); | 703 static GrPorterDuffXPFactory gDstPDXPF(SkXfermode::kDst_Mode); |
704 static const GrPDXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); | 704 static GrPorterDuffXPFactory gSrcOverPDXPF(SkXfermode::kSrcOver_Mode); |
705 static const GrPDXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); | 705 static GrPorterDuffXPFactory gDstOverPDXPF(SkXfermode::kDstOver_Mode); |
706 static const GrPDXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); | 706 static GrPorterDuffXPFactory gSrcInPDXPF(SkXfermode::kSrcIn_Mode); |
707 static const GrPDXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); | 707 static GrPorterDuffXPFactory gDstInPDXPF(SkXfermode::kDstIn_Mode); |
708 static const GrPDXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); | 708 static GrPorterDuffXPFactory gSrcOutPDXPF(SkXfermode::kSrcOut_Mode); |
709 static const GrPDXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); | 709 static GrPorterDuffXPFactory gDstOutPDXPF(SkXfermode::kDstOut_Mode); |
710 static const GrPDXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); | 710 static GrPorterDuffXPFactory gSrcATopPDXPF(SkXfermode::kSrcATop_Mode); |
711 static const GrPDXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); | 711 static GrPorterDuffXPFactory gDstATopPDXPF(SkXfermode::kDstATop_Mode); |
712 static const GrPDXPFactory gXorPDXPF(SkXfermode::kXor_Mode); | 712 static GrPorterDuffXPFactory gXorPDXPF(SkXfermode::kXor_Mode); |
713 static const GrPDXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); | 713 static GrPorterDuffXPFactory gPlusPDXPF(SkXfermode::kPlus_Mode); |
714 static const GrPDXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); | 714 static GrPorterDuffXPFactory gModulatePDXPF(SkXfermode::kModulate_Mode); |
715 static const GrPDXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); | 715 static GrPorterDuffXPFactory gScreenPDXPF(SkXfermode::kScreen_Mode); |
716 | 716 |
717 static const GrPDXPFactory* gFactories[] = { | 717 static GrPorterDuffXPFactory* 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 GrPDXPFactory::onCreateXferProcessor(const GrCaps& caps, | 731 GrPorterDuffXPFactory::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 GrPDXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, | 760 void GrPorterDuffXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorP
OI, |
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 GrPDXPFactory::willReadDstColor(const GrCaps& caps, | 791 bool GrPorterDuffXPFactory::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(GrPDXPFactory); | 815 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
816 | 816 |
817 const GrXPFactory* GrPDXPFactory::TestCreate(GrProcessorTestData* d) { | 817 const GrXPFactory* GrPorterDuffXPFactory::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 GrPDXPFactory::Create(mode); | 819 return GrPorterDuffXPFactory::Create(mode); |
820 } | 820 } |
821 | 821 |
822 void GrPDXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, | 822 void GrPorterDuffXPFactory::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 |