| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "SkXfermode.h" | 9 #include "SkXfermode.h" |
| 10 #include "SkXfermode_opts_SSE2.h" | 10 #include "SkXfermode_opts_SSE2.h" |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 (SkPMColor)(dstA << SK_A32_SHIFT))); | 788 (SkPMColor)(dstA << SK_A32_SHIFT))); |
| 789 if (0xFF != a) { | 789 if (0xFF != a) { |
| 790 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); | 790 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); |
| 791 } | 791 } |
| 792 dst[i] = SkToU8(A); | 792 dst[i] = SkToU8(A); |
| 793 } | 793 } |
| 794 } | 794 } |
| 795 } | 795 } |
| 796 } | 796 } |
| 797 | 797 |
| 798 ////////////////////////////////////////////////////////////////////////////// | |
| 799 | |
| 800 #if SK_SUPPORT_GPU | |
| 801 | |
| 802 #include "GrFragmentProcessor.h" | |
| 803 #include "GrCoordTransform.h" | |
| 804 #include "GrInvariantOutput.h" | |
| 805 #include "GrProcessorUnitTest.h" | |
| 806 #include "gl/GrGLProcessor.h" | |
| 807 #include "gl/builders/GrGLProgramBuilder.h" | |
| 808 | |
| 809 /** | |
| 810 * GrProcessor that implements the all the separable xfer modes that cannot be e
xpressed as Coeffs. | |
| 811 */ | |
| 812 class XferEffect : public GrFragmentProcessor { | |
| 813 public: | |
| 814 static bool IsSupportedMode(SkXfermode::Mode mode) { | |
| 815 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMod
e; | |
| 816 } | |
| 817 | |
| 818 static GrFragmentProcessor* Create(SkXfermode::Mode mode, GrTexture* backgro
und) { | |
| 819 if (!IsSupportedMode(mode)) { | |
| 820 return NULL; | |
| 821 } else { | |
| 822 return SkNEW_ARGS(XferEffect, (mode, background)); | |
| 823 } | |
| 824 } | |
| 825 | |
| 826 virtual void getGLProcessorKey(const GrGLCaps& caps, | |
| 827 GrProcessorKeyBuilder* b) const SK_OVERRIDE { | |
| 828 GLProcessor::GenKey(*this, caps, b); | |
| 829 } | |
| 830 | |
| 831 GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE { | |
| 832 return SkNEW_ARGS(GLProcessor, (*this)); | |
| 833 } | |
| 834 | |
| 835 const char* name() const SK_OVERRIDE { return "XferEffect"; } | |
| 836 | |
| 837 SkXfermode::Mode mode() const { return fMode; } | |
| 838 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess;
} | |
| 839 | |
| 840 class GLProcessor : public GrGLFragmentProcessor { | |
| 841 public: | |
| 842 GLProcessor(const GrFragmentProcessor&) {} | |
| 843 | |
| 844 virtual void emitCode(GrGLFPBuilder* builder, | |
| 845 const GrFragmentProcessor& fp, | |
| 846 const char* outputColor, | |
| 847 const char* inputColor, | |
| 848 const TransformedCoordsArray& coords, | |
| 849 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
| 850 SkXfermode::Mode mode = fp.cast<XferEffect>().mode(); | |
| 851 const GrTexture* backgroundTex = | |
| 852 fp.cast<XferEffect>().backgroundAccess().getTexture(); | |
| 853 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder
(); | |
| 854 const char* dstColor; | |
| 855 if (backgroundTex) { | |
| 856 dstColor = "bgColor"; | |
| 857 fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor); | |
| 858 fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), c
oords[0].getType()); | |
| 859 fsBuilder->codeAppendf(";\n"); | |
| 860 } else { | |
| 861 dstColor = fsBuilder->dstColor(); | |
| 862 } | |
| 863 SkASSERT(dstColor); | |
| 864 | |
| 865 // We don't try to optimize for this case at all | |
| 866 if (NULL == inputColor) { | |
| 867 fsBuilder->codeAppendf("\t\tconst vec4 ones = vec4(1);\n"); | |
| 868 inputColor = "ones"; | |
| 869 } | |
| 870 fsBuilder->codeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::
ModeName(mode)); | |
| 871 | |
| 872 // These all perform src-over on the alpha channel. | |
| 873 fsBuilder->codeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", | |
| 874 outputColor, inputColor, inputColor, dstColo
r); | |
| 875 | |
| 876 switch (mode) { | |
| 877 case SkXfermode::kOverlay_Mode: | |
| 878 // Overlay is Hard-Light with the src and dst reversed | |
| 879 HardLight(fsBuilder, outputColor, dstColor, inputColor); | |
| 880 break; | |
| 881 case SkXfermode::kDarken_Mode: | |
| 882 fsBuilder->codeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.r
gb + %s.rgb, " | |
| 883 "(1.0 - %s.a) * %s.r
gb + %s.rgb);\n", | |
| 884 outputColor, | |
| 885 inputColor, dstColor, inputColor, | |
| 886 dstColor, inputColor, dstColor); | |
| 887 break; | |
| 888 case SkXfermode::kLighten_Mode: | |
| 889 fsBuilder->codeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.r
gb + %s.rgb, " | |
| 890 "(1.0 - %s.a) * %s.r
gb + %s.rgb);\n", | |
| 891 outputColor, | |
| 892 inputColor, dstColor, inputColor, | |
| 893 dstColor, inputColor, dstColor); | |
| 894 break; | |
| 895 case SkXfermode::kColorDodge_Mode: | |
| 896 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstC
olor, 'r'); | |
| 897 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstC
olor, 'g'); | |
| 898 ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstC
olor, 'b'); | |
| 899 break; | |
| 900 case SkXfermode::kColorBurn_Mode: | |
| 901 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstCo
lor, 'r'); | |
| 902 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstCo
lor, 'g'); | |
| 903 ColorBurnComponent(fsBuilder, outputColor, inputColor, dstCo
lor, 'b'); | |
| 904 break; | |
| 905 case SkXfermode::kHardLight_Mode: | |
| 906 HardLight(fsBuilder, outputColor, inputColor, dstColor); | |
| 907 break; | |
| 908 case SkXfermode::kSoftLight_Mode: | |
| 909 fsBuilder->codeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor)
; | |
| 910 fsBuilder->codeAppendf("\t\t\t%s.rgba = %s;\n", outputColor,
inputColor); | |
| 911 fsBuilder->codeAppendf("\t\t} else {\n"); | |
| 912 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputC
olor, dstColor, 'r'); | |
| 913 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputC
olor, dstColor, 'g'); | |
| 914 SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputC
olor, dstColor, 'b'); | |
| 915 fsBuilder->codeAppendf("\t\t}\n"); | |
| 916 break; | |
| 917 case SkXfermode::kDifference_Mode: | |
| 918 fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" | |
| 919 "2.0 * min(%s.rgb * %s.a,
%s.rgb * %s.a);\n", | |
| 920 outputColor, inputColor, dstColor, in
putColor, dstColor, | |
| 921 dstColor, inputColor); | |
| 922 break; | |
| 923 case SkXfermode::kExclusion_Mode: | |
| 924 fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " | |
| 925 "2.0 * %s.rgb * %s.rgb;\
n", | |
| 926 outputColor, dstColor, inputColor, ds
tColor, inputColor); | |
| 927 break; | |
| 928 case SkXfermode::kMultiply_Mode: | |
| 929 fsBuilder->codeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb +
" | |
| 930 "(1.0 - %s.a) * %s.rgb +
" | |
| 931 "%s.rgb * %s.rgb;\n", | |
| 932 outputColor, inputColor, dstColor, ds
tColor, inputColor, | |
| 933 inputColor, dstColor); | |
| 934 break; | |
| 935 case SkXfermode::kHue_Mode: { | |
| 936 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 -
Sa) * D + (1 - Da) * S | |
| 937 SkString setSat, setLum; | |
| 938 AddSatFunction(fsBuilder, &setSat); | |
| 939 AddLumFunction(fsBuilder, &setLum); | |
| 940 fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n"
, | |
| 941 dstColor, inputColor); | |
| 942 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, ds
tSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", | |
| 943 outputColor, setLum.c_str(), setSat.c
_str(), inputColor, | |
| 944 dstColor); | |
| 945 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb
+ (1.0 - %s.a) * %s.rgb;\n", | |
| 946 outputColor, inputColor, dstColor, ds
tColor, inputColor); | |
| 947 break; | |
| 948 } | |
| 949 case SkXfermode::kSaturation_Mode: { | |
| 950 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 -
Sa) * D + (1 - Da) * S | |
| 951 SkString setSat, setLum; | |
| 952 AddSatFunction(fsBuilder, &setSat); | |
| 953 AddLumFunction(fsBuilder, &setLum); | |
| 954 fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n"
, | |
| 955 dstColor, inputColor); | |
| 956 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb,
%s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", | |
| 957 outputColor, setLum.c_str(), setSat.c
_str(), inputColor, | |
| 958 dstColor); | |
| 959 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb
+ (1.0 - %s.a) * %s.rgb;\n", | |
| 960 outputColor, inputColor, dstColor, ds
tColor, inputColor); | |
| 961 break; | |
| 962 } | |
| 963 case SkXfermode::kColor_Mode: { | |
| 964 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da)
* S | |
| 965 SkString setLum; | |
| 966 AddLumFunction(fsBuilder, &setLum); | |
| 967 fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n"
, | |
| 968 inputColor, dstColor); | |
| 969 fsBuilder->codeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, src
DstAlpha.a, %s.rgb * %s.a);\n", | |
| 970 outputColor, setLum.c_str(), dstColor
, inputColor); | |
| 971 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb
+ (1.0 - %s.a) * %s.rgb;\n", | |
| 972 outputColor, inputColor, dstColor, ds
tColor, inputColor); | |
| 973 break; | |
| 974 } | |
| 975 case SkXfermode::kLuminosity_Mode: { | |
| 976 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da)
* S | |
| 977 SkString setLum; | |
| 978 AddLumFunction(fsBuilder, &setLum); | |
| 979 fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n"
, | |
| 980 inputColor, dstColor); | |
| 981 fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDs
tAlpha.a, srcDstAlpha.rgb);\n", | |
| 982 outputColor, setLum.c_str(), dstColor
, inputColor); | |
| 983 fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb
+ (1.0 - %s.a) * %s.rgb;\n", | |
| 984 outputColor, inputColor, dstColor, ds
tColor, inputColor); | |
| 985 break; | |
| 986 } | |
| 987 default: | |
| 988 SkFAIL("Unknown XferEffect mode."); | |
| 989 break; | |
| 990 } | |
| 991 } | |
| 992 | |
| 993 static inline void GenKey(const GrProcessor& proc, const GrGLCaps&, | |
| 994 GrProcessorKeyBuilder* b) { | |
| 995 // The background may come from the dst or from a texture. | |
| 996 uint32_t key = proc.numTextures(); | |
| 997 SkASSERT(key <= 1); | |
| 998 key |= proc.cast<XferEffect>().mode() << 1; | |
| 999 b->add32(key); | |
| 1000 } | |
| 1001 | |
| 1002 private: | |
| 1003 static void HardLight(GrGLFPFragmentBuilder* fsBuilder, | |
| 1004 const char* final, | |
| 1005 const char* src, | |
| 1006 const char* dst) { | |
| 1007 static const char kComponents[] = {'r', 'g', 'b'}; | |
| 1008 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | |
| 1009 char component = kComponents[i]; | |
| 1010 fsBuilder->codeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src,
component, src); | |
| 1011 fsBuilder->codeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", f
inal, component, src, component, dst, component); | |
| 1012 fsBuilder->codeAppend("\t\t} else {\n"); | |
| 1013 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a
- %s.%c) * (%s.a - %s.%c);\n", | |
| 1014 final, component, src, dst, dst, dst, com
ponent, src, src, component); | |
| 1015 fsBuilder->codeAppend("\t\t}\n"); | |
| 1016 } | |
| 1017 fsBuilder->codeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb
* (1.0 - %s.a);\n", | |
| 1018 final, src, dst, dst, src); | |
| 1019 } | |
| 1020 | |
| 1021 // Does one component of color-dodge | |
| 1022 static void ColorDodgeComponent(GrGLFPFragmentBuilder* fsBuilder, | |
| 1023 const char* final, | |
| 1024 const char* src, | |
| 1025 const char* dst, | |
| 1026 const char component) { | |
| 1027 fsBuilder->codeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); | |
| 1028 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", | |
| 1029 final, component, src, component, dst); | |
| 1030 fsBuilder->codeAppend("\t\t} else {\n"); | |
| 1031 fsBuilder->codeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src,
component); | |
| 1032 fsBuilder->codeAppend("\t\t\tif (0.0 == d) {\n"); | |
| 1033 fsBuilder->codeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 -
%s.a) + %s.%c * (1.0 - %s.a);\n", | |
| 1034 final, component, src, dst, src, component, d
st, dst, component, | |
| 1035 src); | |
| 1036 fsBuilder->codeAppend("\t\t\t} else {\n"); | |
| 1037 fsBuilder->codeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", | |
| 1038 dst, dst, component, src); | |
| 1039 fsBuilder->codeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s
.a) + %s.%c * (1.0 - %s.a);\n", | |
| 1040 final, component, src, src, component, dst, d
st, component, src); | |
| 1041 fsBuilder->codeAppend("\t\t\t}\n"); | |
| 1042 fsBuilder->codeAppend("\t\t}\n"); | |
| 1043 } | |
| 1044 | |
| 1045 // Does one component of color-burn | |
| 1046 static void ColorBurnComponent(GrGLFPFragmentBuilder* fsBuilder, | |
| 1047 const char* final, | |
| 1048 const char* src, | |
| 1049 const char* dst, | |
| 1050 const char component) { | |
| 1051 fsBuilder->codeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, compo
nent); | |
| 1052 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %
s.a) + %s.%c * (1.0 - %s.a);\n", | |
| 1053 final, component, src, dst, src, component, d
st, dst, component, | |
| 1054 src); | |
| 1055 fsBuilder->codeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, comp
onent); | |
| 1056 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", | |
| 1057 final, component, dst, component, src); | |
| 1058 fsBuilder->codeAppend("\t\t} else {\n"); | |
| 1059 fsBuilder->codeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%
c) * %s.a / %s.%c);\n", | |
| 1060 dst, dst, dst, component, src, src, component
); | |
| 1061 fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a
) + %s.%c * (1.0 - %s.a);\n", | |
| 1062 final, component, src, src, component, dst, d
st, component, src); | |
| 1063 fsBuilder->codeAppend("\t\t}\n"); | |
| 1064 } | |
| 1065 | |
| 1066 // Does one component of soft-light. Caller should have already checked
that dst alpha > 0. | |
| 1067 static void SoftLightComponentPosDstAlpha(GrGLFPFragmentBuilder* fsBuild
er, | |
| 1068 const char* final, | |
| 1069 const char* src, | |
| 1070 const char* dst, | |
| 1071 const char component) { | |
| 1072 // if (2S < Sa) | |
| 1073 fsBuilder->codeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, co
mponent, src); | |
| 1074 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) | |
| 1075 fsBuilder->codeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.
%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", | |
| 1076 final, component, dst, component, dst, compon
ent, src, src, | |
| 1077 component, dst, dst, src, component, dst, com
ponent, src, src, | |
| 1078 component); | |
| 1079 // else if (4D < Da) | |
| 1080 fsBuilder->codeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", | |
| 1081 dst, component, dst); | |
| 1082 fsBuilder->codeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", | |
| 1083 dst, component, dst, component); | |
| 1084 fsBuilder->codeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst,
component); | |
| 1085 fsBuilder->codeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst,
dst); | |
| 1086 fsBuilder->codeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst)
; | |
| 1087 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-
2 S))/Da^2 | |
| 1088 fsBuilder->codeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c
- %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 1
6.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", | |
| 1089 final, component, src, component, src, compon
ent, dst, component, | |
| 1090 src, src, component, dst, src, src, component
, src, src, | |
| 1091 component); | |
| 1092 fsBuilder->codeAppendf("\t\t\t} else {\n"); | |
| 1093 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S | |
| 1094 fsBuilder->codeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.
0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", | |
| 1095 final, component, dst, dst, component, src,
src, component, dst, | |
| 1096 src, component, dst, component, src, src, co
mponent, src, | |
| 1097 component); | |
| 1098 fsBuilder->codeAppendf("\t\t\t}\n"); | |
| 1099 } | |
| 1100 | |
| 1101 // Adds a function that takes two colors and an alpha as input. It produ
ces a color with the | |
| 1102 // hue and saturation of the first color, the luminosity of the second c
olor, and the input | |
| 1103 // alpha. It has this signature: | |
| 1104 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor)
. | |
| 1105 static void AddLumFunction(GrGLFPFragmentBuilder* fsBuilder, SkString* s
etLumFunction) { | |
| 1106 // Emit a helper that gets the luminance of a color. | |
| 1107 SkString getFunction; | |
| 1108 GrGLShaderVar getLumArgs[] = { | |
| 1109 GrGLShaderVar("color", kVec3f_GrSLType), | |
| 1110 }; | |
| 1111 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n")
; | |
| 1112 fsBuilder->emitFunction(kFloat_GrSLType, | |
| 1113 "luminance", | |
| 1114 SK_ARRAY_COUNT(getLumArgs), getLumArgs, | |
| 1115 getLumBody.c_str(), | |
| 1116 &getFunction); | |
| 1117 | |
| 1118 // Emit the set luminance function. | |
| 1119 GrGLShaderVar setLumArgs[] = { | |
| 1120 GrGLShaderVar("hueSat", kVec3f_GrSLType), | |
| 1121 GrGLShaderVar("alpha", kFloat_GrSLType), | |
| 1122 GrGLShaderVar("lumColor", kVec3f_GrSLType), | |
| 1123 }; | |
| 1124 SkString setLumBody; | |
| 1125 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunc
tion.c_str()); | |
| 1126 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); | |
| 1127 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c
_str()); | |
| 1128 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g)
, outColor.b);\n" | |
| 1129 "\tfloat maxComp = max(max(outColor.r, outColor.g)
, outColor.b);\n" | |
| 1130 "\tif (minComp < 0.0 && outLum != minComp) {\n" | |
| 1131 "\t\toutColor = outLum + ((outColor - vec3(outLum,
outLum, outLum)) * outLum) / (outLum - minComp);\n" | |
| 1132 "\t}\n" | |
| 1133 "\tif (maxComp > alpha && maxComp != outLum) {\n" | |
| 1134 "\t\toutColor = outLum + ((outColor - vec3(outLum,
outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" | |
| 1135 "\t}\n" | |
| 1136 "\treturn outColor;\n"); | |
| 1137 fsBuilder->emitFunction(kVec3f_GrSLType, | |
| 1138 "set_luminance", | |
| 1139 SK_ARRAY_COUNT(setLumArgs), setLumArgs, | |
| 1140 setLumBody.c_str(), | |
| 1141 setLumFunction); | |
| 1142 } | |
| 1143 | |
| 1144 // Adds a function that creates a color with the hue and luminosity of o
ne input color and | |
| 1145 // the saturation of another color. It will have this signature: | |
| 1146 // float set_saturation(vec3 hueLumColor, vec3 satColor) | |
| 1147 static void AddSatFunction(GrGLFPFragmentBuilder* fsBuilder, SkString* s
etSatFunction) { | |
| 1148 // Emit a helper that gets the saturation of a color | |
| 1149 SkString getFunction; | |
| 1150 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLTyp
e) }; | |
| 1151 SkString getSatBody; | |
| 1152 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " | |
| 1153 "min(min(color.r, color.g), color.b);\n"); | |
| 1154 fsBuilder->emitFunction(kFloat_GrSLType, | |
| 1155 "saturation", | |
| 1156 SK_ARRAY_COUNT(getSatArgs), getSatArgs, | |
| 1157 getSatBody.c_str(), | |
| 1158 &getFunction); | |
| 1159 | |
| 1160 // Emit a helper that sets the saturation given sorted input channel
s. This used | |
| 1161 // to use inout params for min, mid, and max components but that see
ms to cause | |
| 1162 // problems on PowerVR drivers. So instead it returns a vec3 where r
, g ,b are the | |
| 1163 // adjusted min, mid, and max inputs, respectively. | |
| 1164 SkString helperFunction; | |
| 1165 GrGLShaderVar helperArgs[] = { | |
| 1166 GrGLShaderVar("minComp", kFloat_GrSLType), | |
| 1167 GrGLShaderVar("midComp", kFloat_GrSLType), | |
| 1168 GrGLShaderVar("maxComp", kFloat_GrSLType), | |
| 1169 GrGLShaderVar("sat", kFloat_GrSLType), | |
| 1170 }; | |
| 1171 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n" | |
| 1172 "\t\tvec3 result;\n" | |
| 1173 "\t\tresult.r = 0.0;\n" | |
| 1174 "\t\tresult.g = sat * (midComp - m
inComp) / (maxComp - minComp);\n" | |
| 1175 "\t\tresult.b = sat;\n" | |
| 1176 "\t\treturn result;\n" | |
| 1177 "\t} else {\n" | |
| 1178 "\t\treturn vec3(0, 0, 0);\n" | |
| 1179 "\t}\n"; | |
| 1180 fsBuilder->emitFunction(kVec3f_GrSLType, | |
| 1181 "set_saturation_helper", | |
| 1182 SK_ARRAY_COUNT(helperArgs), helperArgs, | |
| 1183 kHelperBody, | |
| 1184 &helperFunction); | |
| 1185 | |
| 1186 GrGLShaderVar setSatArgs[] = { | |
| 1187 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), | |
| 1188 GrGLShaderVar("satColor", kVec3f_GrSLType), | |
| 1189 }; | |
| 1190 const char* helpFunc = helperFunction.c_str(); | |
| 1191 SkString setSatBody; | |
| 1192 setSatBody.appendf("\tfloat sat = %s(satColor);\n" | |
| 1193 "\tif (hueLumColor.r <= hueLumColor.g) {\n" | |
| 1194 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" | |
| 1195 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLum
Color.g, hueLumColor.b, sat);\n" | |
| 1196 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {
\n" | |
| 1197 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLum
Color.b, hueLumColor.g, sat);\n" | |
| 1198 "\t\t} else {\n" | |
| 1199 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLum
Color.r, hueLumColor.g, sat);\n" | |
| 1200 "\t\t}\n" | |
| 1201 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n
" | |
| 1202 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumCo
lor.r, hueLumColor.b, sat);\n" | |
| 1203 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n
" | |
| 1204 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumCo
lor.b, hueLumColor.r, sat);\n" | |
| 1205 "\t} else {\n" | |
| 1206 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumCo
lor.g, hueLumColor.r, sat);\n" | |
| 1207 "\t}\n" | |
| 1208 "\treturn hueLumColor;\n", | |
| 1209 getFunction.c_str(), helpFunc, helpFunc, helpFunc
, helpFunc, | |
| 1210 helpFunc, helpFunc); | |
| 1211 fsBuilder->emitFunction(kVec3f_GrSLType, | |
| 1212 "set_saturation", | |
| 1213 SK_ARRAY_COUNT(setSatArgs), setSatArgs, | |
| 1214 setSatBody.c_str(), | |
| 1215 setSatFunction); | |
| 1216 | |
| 1217 } | |
| 1218 | |
| 1219 typedef GrGLFragmentProcessor INHERITED; | |
| 1220 }; | |
| 1221 | |
| 1222 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | |
| 1223 | |
| 1224 private: | |
| 1225 XferEffect(SkXfermode::Mode mode, GrTexture* background) | |
| 1226 : fMode(mode) { | |
| 1227 this->initClassID<XferEffect>(); | |
| 1228 if (background) { | |
| 1229 fBackgroundTransform.reset(kLocal_GrCoordSet, background, | |
| 1230 GrTextureParams::kNone_FilterMode); | |
| 1231 this->addCoordTransform(&fBackgroundTransform); | |
| 1232 fBackgroundAccess.reset(background); | |
| 1233 this->addTextureAccess(&fBackgroundAccess); | |
| 1234 } else { | |
| 1235 this->setWillReadDstColor(); | |
| 1236 } | |
| 1237 } | |
| 1238 bool onIsEqual(const GrFragmentProcessor& other) const SK_OVERRIDE { | |
| 1239 const XferEffect& s = other.cast<XferEffect>(); | |
| 1240 return fMode == s.fMode; | |
| 1241 } | |
| 1242 | |
| 1243 void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE { | |
| 1244 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | |
| 1245 } | |
| 1246 | |
| 1247 SkXfermode::Mode fMode; | |
| 1248 GrCoordTransform fBackgroundTransform; | |
| 1249 GrTextureAccess fBackgroundAccess; | |
| 1250 | |
| 1251 typedef GrFragmentProcessor INHERITED; | |
| 1252 }; | |
| 1253 | |
| 1254 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(XferEffect); | |
| 1255 GrFragmentProcessor* XferEffect::TestCreate(SkRandom* rand, | |
| 1256 GrContext*, | |
| 1257 const GrDrawTargetCaps&, | |
| 1258 GrTexture*[]) { | |
| 1259 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); | |
| 1260 | |
| 1261 return SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)); | |
| 1262 } | |
| 1263 | |
| 1264 #endif | |
| 1265 | |
| 1266 /////////////////////////////////////////////////////////////////////////////// | 798 /////////////////////////////////////////////////////////////////////////////// |
| 1267 /////////////////////////////////////////////////////////////////////////////// | 799 /////////////////////////////////////////////////////////////////////////////// |
| 1268 | 800 |
| 1269 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) { | 801 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) { |
| 1270 uint32_t mode32 = buffer.read32(); | 802 uint32_t mode32 = buffer.read32(); |
| 1271 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) { | 803 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) { |
| 1272 return NULL; | 804 return NULL; |
| 1273 } | 805 } |
| 1274 return SkXfermode::Create((SkXfermode::Mode)mode32); | 806 return SkXfermode::Create((SkXfermode::Mode)mode32); |
| 1275 } | 807 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); | 912 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); |
| 1381 } | 913 } |
| 1382 dst[i] = SkToU8(A); | 914 dst[i] = SkToU8(A); |
| 1383 } | 915 } |
| 1384 } | 916 } |
| 1385 } | 917 } |
| 1386 } | 918 } |
| 1387 } | 919 } |
| 1388 | 920 |
| 1389 #if SK_SUPPORT_GPU | 921 #if SK_SUPPORT_GPU |
| 922 #include "effects/GrCustomXfermode.h" |
| 923 |
| 1390 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp, | 924 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp, |
| 1391 GrTexture* background) const { | 925 GrTexture* background) const { |
| 1392 if (XferEffect::IsSupportedMode(fMode)) { | 926 if (GrCustomXfermode::IsSupportedMode(fMode)) { |
| 1393 if (fp) { | 927 if (fp) { |
| 1394 *fp = XferEffect::Create(fMode, background); | 928 *fp = GrCustomXfermode::CreateFP(fMode, background); |
| 1395 SkASSERT(*fp); | 929 SkASSERT(*fp); |
| 1396 } | 930 } |
| 1397 return true; | 931 return true; |
| 1398 } | 932 } |
| 1399 return false; | 933 return false; |
| 1400 } | 934 } |
| 1401 #endif | 935 #endif |
| 1402 | 936 |
| 1403 const char* SkXfermode::ModeName(Mode mode) { | 937 const char* SkXfermode::ModeName(Mode mode) { |
| 1404 SkASSERT((unsigned) mode <= (unsigned)kLastMode); | 938 SkASSERT((unsigned) mode <= (unsigned)kLastMode); |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1953 } else { | 1487 } else { |
| 1954 proc16 = rec.fProc16_General; | 1488 proc16 = rec.fProc16_General; |
| 1955 } | 1489 } |
| 1956 } | 1490 } |
| 1957 return proc16; | 1491 return proc16; |
| 1958 } | 1492 } |
| 1959 | 1493 |
| 1960 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1494 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
| 1961 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1495 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
| 1962 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1496 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |