Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/core/SkXfermode.cpp

Issue 14189024: Add all remaining separable xfer modes to GPU backend. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/core/SkXfermode.h ('k') | src/gpu/gl/GrGLSL_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 9
10 #include "SkXfermode.h" 10 #include "SkXfermode.h"
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 ////////////////////////////////////////////////////////////////////////////// 943 //////////////////////////////////////////////////////////////////////////////
944 944
945 #if SK_SUPPORT_GPU 945 #if SK_SUPPORT_GPU
946 946
947 #include "GrEffect.h" 947 #include "GrEffect.h"
948 #include "GrEffectUnitTest.h" 948 #include "GrEffectUnitTest.h"
949 #include "GrTBackendEffectFactory.h" 949 #include "GrTBackendEffectFactory.h"
950 #include "gl/GrGLEffect.h" 950 #include "gl/GrGLEffect.h"
951 951
952 /** 952 /**
953 * GrEffect that implements the kDarken_Mode Xfermode. It requires access to the dst pixel color 953 * GrEffect that implements the all the separable xfer modes that cannot be expr essed as Coeffs.
954 * in the shader. TODO: Make this work for all non-Coeff SkXfermode::Mode values .
955 */ 954 */
956 class DarkenEffect : public GrEffect { 955 class XferEffect : public GrEffect {
957 public: 956 public:
958 static GrEffectRef* Create() { 957 static bool IsSupportedMode(SkXfermode::Mode mode) {
959 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 958 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastSep arableMode;
960 return CreateEffectRef(gEffect); 959 }
960
961 static GrEffectRef* Create(SkXfermode::Mode mode) {
962 if (!IsSupportedMode(mode)) {
963 return NULL;
964 } else {
965 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode)));
966 return CreateEffectRef(effect);
967 }
961 } 968 }
962 969
963 virtual void getConstantColorComponents(GrColor* color, 970 virtual void getConstantColorComponents(GrColor* color,
964 uint32_t* validFlags) const SK_OVERR IDE { 971 uint32_t* validFlags) const SK_OVERR IDE {
965 *validFlags = 0; 972 *validFlags = 0;
966 } 973 }
967 974
968 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 975 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
969 return GrTBackendEffectFactory<DarkenEffect>::getInstance(); 976 return GrTBackendEffectFactory<XferEffect>::getInstance();
970 } 977 }
971 978
972 static const char* Name() { return "XfermodeDarken"; } 979 static const char* Name() { return "XferEffect"; }
980
981 SkXfermode::Mode mode() const { return fMode; }
973 982
974 class GLEffect : public GrGLEffect { 983 class GLEffect : public GrGLEffect {
975 public: 984 public:
976 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 985 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
977 : GrGLEffect(factory ) { 986 : GrGLEffect(factory ) {
978 } 987 }
979 virtual void emitCode(GrGLShaderBuilder* builder, 988 virtual void emitCode(GrGLShaderBuilder* builder,
980 const GrDrawEffect& drawEffect, 989 const GrDrawEffect& drawEffect,
981 EffectKey key, 990 EffectKey key,
982 const char* outputColor, 991 const char* outputColor,
983 const char* inputColor, 992 const char* inputColor,
984 const TextureSamplerArray& samplers) SK_OVERRIDE { 993 const TextureSamplerArray& samplers) SK_OVERRIDE {
985 const char* dstColorName = builder->dstColor(); 994 const char* dstColor = builder->dstColor();
986 GrAssert(NULL != dstColorName); 995 GrAssert(NULL != dstColor);
996
997 // We don't try to optimize for this case at all
987 if (NULL == inputColor) { 998 if (NULL == inputColor) {
988 // the input color is solid white 999 builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVe cf(4));
989 builder->fsCodeAppendf("\t\t%s.a = 1.0;\n", outputColor); 1000 inputColor = "ones";
990 builder->fsCodeAppendf("\t\t%s.rgb = vec3(1.0, 1.0, 1.0) - %s.aa a + %s.rgb;\n",
991 outputColor, dstColorName, dstColorName);
992 } else {
993 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - % s.a);\n",
994 outputColor, dstColorName, inputColor);
995 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb,"
996 " (1.0 - %s.a) * %s.rgb + %s.rgb);\n",
997 outputColor,
998 inputColor, dstColorName, inputColor,
999 dstColorName, inputColor, dstColorName);
1000 } 1001 }
1001 } 1002
1002 1003 // These all perform src-over on the alpha channel.
1003 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { r eturn 0; } 1004 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
1005 outputColor, inputColor, inputColor, dstColo r);
1006
1007 switch (drawEffect.castEffect<XferEffect>().mode()) {
1008 case SkXfermode::kOverlay_Mode:
1009 // Overlay is Hard-Light with the src and dst reversed
1010 HardLight(builder, outputColor, dstColor, inputColor);
1011 break;
1012 case SkXfermode::kDarken_Mode:
1013 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.r gb + %s.rgb, "
1014 "(1.0 - %s.a) * %s.r gb + %s.rgb);\n",
1015 outputColor,
1016 inputColor, dstColor, inputColor,
1017 dstColor, inputColor, dstColor);
1018 break;
1019 case SkXfermode::kLighten_Mode:
1020 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.r gb + %s.rgb, "
1021 "(1.0 - %s.a) * %s.r gb + %s.rgb);\n",
1022 outputColor,
1023 inputColor, dstColor, inputColor,
1024 dstColor, inputColor, dstColor);
1025 break;
1026 case SkXfermode::kColorDodge_Mode:
1027 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'r');
1028 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'g');
1029 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'b');
1030 break;
1031 case SkXfermode::kColorBurn_Mode:
1032 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'r');
1033 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'g');
1034 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'b');
1035 break;
1036 case SkXfermode::kHardLight_Mode:
1037 HardLight(builder, outputColor, inputColor, dstColor);
1038 break;
1039 case SkXfermode::kSoftLight_Mode:
1040 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor) ;
1041 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
1042 builder->fsCodeAppendf("\t\t} else {\n");
1043 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'r');
1044 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'g');
1045 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'b');
1046 builder->fsCodeAppendf("\t\t}\n");
1047 break;
1048 case SkXfermode::kDifference_Mode:
1049 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1050 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1051 outputColor, inputColor, dstColor, in putColor, dstColor,
1052 dstColor, inputColor);
1053 break;
1054 case SkXfermode::kExclusion_Mode:
1055 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1056 "2.0 * %s.rgb * %s.rgb;\ n",
1057 outputColor, dstColor, inputColor, ds tColor, inputColor);
1058 break;
1059 case SkXfermode::kMultiply_Mode:
1060 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1061 "(1.0 - %s.a) * %s.rgb + "
1062 "%s.rgb * %s.rgb;\n",
1063 outputColor, inputColor, dstColor, ds tColor, inputColor,
1064 inputColor, dstColor);
1065 break;
1066 case SkXfermode::kHue_Mode:
1067 case SkXfermode::kSaturation_Mode:
1068 case SkXfermode::kColor_Mode:
1069 case SkXfermode::kLuminosity_Mode:
1070 GrCrash("Unimplemented XferEffect mode.");
1071 break;
1072 default:
1073 GrCrash("Unknown XferEffect mode.");
1074 break;
1075 }
1076 }
1077
1078 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
1079 return drawEffect.castEffect<XferEffect>().mode();
1080 }
1004 1081
1005 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {} 1082 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
1006 1083
1007 private: 1084 private:
1085 static void HardLight(GrGLShaderBuilder* builder,
1086 const char* final,
1087 const char* src,
1088 const char* dst) {
1089 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a) ;\n",
1090 final, dst, src);
1091 builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ",
1092 final, src, dst);
1093 builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),",
1094 src, dst, dst, dst, src, src);
1095 builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n" ,
1096 src, src);
1097 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1098 final, src, dst, dst, src);
1099 }
1100
1101 // Does one component of color-dodge
1102 static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1103 const char* final,
1104 const char* src,
1105 const char* dst,
1106 const char component) {
1107 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1108 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1 - %s.a);\n",
1109 final, component, src, component, dst);
1110 builder->fsCodeAppend("\t\t} else {\n");
1111 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1112 builder->fsCodeAppend("\t\t\tif (0 == d) {\n");
1113 builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1114 final, component, src, dst, src, component, d st, dst, component,
1115 src);
1116 builder->fsCodeAppend("\t\t\t} else {\n");
1117 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1118 dst, dst, component, src);
1119 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s .a) + %s.%c * (1.0 - %s.a);\n",
1120 final, component, src, src, component, dst, d st, component, src);
1121 builder->fsCodeAppend("\t\t\t}\n");
1122 builder->fsCodeAppend("\t\t}\n");
1123 }
1124
1125 // Does one component of color-burn
1126 static void ColorBurnComponent(GrGLShaderBuilder* builder,
1127 const char* final,
1128 const char* src,
1129 const char* dst,
1130 const char component) {
1131 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, compo nent);
1132 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - % s.a) + %s.%c * (1.0 - %s.a);\n",
1133 final, component, src, dst, src, component, d st, dst, component,
1134 src);
1135 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, comp onent);
1136 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1137 final, component, dst, component, src);
1138 builder->fsCodeAppend("\t\t} else {\n");
1139 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.% c) * %s.a / %s.%c);\n",
1140 dst, dst, dst, component, src, src, component );
1141 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a ) + %s.%c * (1.0 - %s.a);\n",
1142 final, component, src, src, component, dst, d st, component, src);
1143 builder->fsCodeAppend("\t\t}\n");
1144 }
1145
1146 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1147 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1148 const char* final,
1149 const char* src,
1150 const char* dst,
1151 const char component) {
1152 // if (2S < Sa)
1153 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, co mponent, src);
1154 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1155 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2*%s.%c )) / %s.a + (1 - %s.a) * %s.%c + %s.%c*(-%s.a + 2*%s.%c + 1);\n",
1156 final, component, dst, component, dst, compon ent, src, src,
1157 component, dst, dst, src, component, dst, com ponent, src, src,
1158 component);
1159 // else if (4D < Da)
1160 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1161 dst, component, dst);
1162 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1163 dst, component, dst, component);
1164 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1165 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1166 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst) ;
1167 // (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
1168 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3*%s.a - 6*%s.%c - 1)) + 12*%s.a*DSqd*(%s.a - 2*%s.%c) - 16*DCub * ( %s.a - 2*%s.%c)) / DaSqd;\n",
1169 final, component, src, component, src, compon ent, dst, component,
1170 src, src, component, dst, src, src, component , src, src,
1171 component);
1172 builder->fsCodeAppendf("\t\t\t} else {\n");
1173 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1174 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2* %s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2*%s.%c + 1) + %s.%c;\n",
1175 final, component, dst, dst, component, src, src, component, dst,
1176 src, component, dst, component, src, src, co mponent, src,
1177 component);
1178 builder->fsCodeAppendf("\t\t\t}\n");
1179 }
1180
1008 typedef GrGLEffect INHERITED; 1181 typedef GrGLEffect INHERITED;
1009 }; 1182 };
1010 1183
1011 GR_DECLARE_EFFECT_TEST; 1184 GR_DECLARE_EFFECT_TEST;
1012 1185
1013 private: 1186 private:
1014 DarkenEffect() { this->setWillReadDst(); } 1187 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); }
1015 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; } 1188 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; }
1189
1190 SkXfermode::Mode fMode;
1016 1191
1017 typedef GrEffect INHERITED; 1192 typedef GrEffect INHERITED;
1018 }; 1193 };
1019 1194
1020 GR_DEFINE_EFFECT_TEST(DarkenEffect); 1195 GR_DEFINE_EFFECT_TEST(XferEffect);
1021 GrEffectRef* DarkenEffect::TestCreate(SkMWCRandom*, 1196 GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand,
1022 GrContext*, 1197 GrContext*,
1023 const GrDrawTargetCaps&, 1198 const GrDrawTargetCaps&,
1024 GrTexture*[]) { 1199 GrTexture*[]) {
1025 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 1200 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas tSeparableMode);
1201 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermod e::Mode>(mode))));
1026 return CreateEffectRef(gEffect); 1202 return CreateEffectRef(gEffect);
1027 } 1203 }
1028 1204
1029 #endif 1205 #endif
1030 1206
1031 /////////////////////////////////////////////////////////////////////////////// 1207 ///////////////////////////////////////////////////////////////////////////////
1032 /////////////////////////////////////////////////////////////////////////////// 1208 ///////////////////////////////////////////////////////////////////////////////
1033 1209
1034 class SkProcCoeffXfermode : public SkProcXfermode { 1210 class SkProcCoeffXfermode : public SkProcXfermode {
1035 public: 1211 public:
(...skipping 27 matching lines...) Expand all
1063 } 1239 }
1064 1240
1065 #if SK_SUPPORT_GPU 1241 #if SK_SUPPORT_GPU
1066 virtual bool asNewEffectOrCoeff(GrContext*, 1242 virtual bool asNewEffectOrCoeff(GrContext*,
1067 GrEffectRef** effect, 1243 GrEffectRef** effect,
1068 Coeff* src, 1244 Coeff* src,
1069 Coeff* dst) const SK_OVERRIDE { 1245 Coeff* dst) const SK_OVERRIDE {
1070 if (this->asCoeff(src, dst)) { 1246 if (this->asCoeff(src, dst)) {
1071 return true; 1247 return true;
1072 } 1248 }
1073 if (kDarken_Mode == fMode) { 1249 if (XferEffect::IsSupportedMode(fMode)) {
1074 if (NULL != effect) { 1250 if (NULL != effect) {
1075 *effect = DarkenEffect::Create(); 1251 *effect = XferEffect::Create(fMode);
1252 SkASSERT(NULL != *effect);
1076 } 1253 }
1077 return true; 1254 return true;
1078 } 1255 }
1079 return false; 1256 return false;
1080 } 1257 }
1081 #endif 1258 #endif
1082 1259
1083 SK_DEVELOPER_TO_STRING() 1260 SK_DEVELOPER_TO_STRING()
1084 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 1261 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
1085 1262
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 return proc16; 1795 return proc16;
1619 } 1796 }
1620 1797
1621 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1798 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1622 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1799 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1623 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1800 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1624 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1801 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1625 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1802 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1626 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1803 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1627 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1804 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« no previous file with comments | « include/core/SkXfermode.h ('k') | src/gpu/gl/GrGLSL_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698