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

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

Issue 14371014: Add non-separable xfer modes to GPU backend. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Add non-separable xfer modes to GPU backend. 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 | « src/core/SkString.cpp ('k') | src/gpu/gl/GrGLShaderBuilder.cpp » ('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 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 all the separable xfer modes that cannot be expr essed as Coeffs. 953 * GrEffect that implements the all the separable xfer modes that cannot be expr essed as Coeffs.
954 */ 954 */
955 class XferEffect : public GrEffect { 955 class XferEffect : public GrEffect {
956 public: 956 public:
957 static bool IsSupportedMode(SkXfermode::Mode mode) { 957 static bool IsSupportedMode(SkXfermode::Mode mode) {
958 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastSep arableMode; 958 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMod e;
959 } 959 }
960 960
961 static GrEffectRef* Create(SkXfermode::Mode mode) { 961 static GrEffectRef* Create(SkXfermode::Mode mode) {
962 if (!IsSupportedMode(mode)) { 962 if (!IsSupportedMode(mode)) {
963 return NULL; 963 return NULL;
964 } else { 964 } else {
965 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode))); 965 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode)));
966 return CreateEffectRef(effect); 966 return CreateEffectRef(effect);
967 } 967 }
968 } 968 }
(...skipping 24 matching lines...) Expand all
993 const TextureSamplerArray& samplers) SK_OVERRIDE { 993 const TextureSamplerArray& samplers) SK_OVERRIDE {
994 const char* dstColor = builder->dstColor(); 994 const char* dstColor = builder->dstColor();
995 GrAssert(NULL != dstColor); 995 GrAssert(NULL != dstColor);
996 996
997 // We don't try to optimize for this case at all 997 // We don't try to optimize for this case at all
998 if (NULL == inputColor) { 998 if (NULL == inputColor) {
999 builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVe cf(4)); 999 builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVe cf(4));
1000 inputColor = "ones"; 1000 inputColor = "ones";
1001 } 1001 }
1002 1002
1003 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
1004 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode:: ModeName(mode));
1005
1003 // These all perform src-over on the alpha channel. 1006 // These all perform src-over on the alpha channel.
1004 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 1007 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
1005 outputColor, inputColor, inputColor, dstColo r); 1008 outputColor, inputColor, inputColor, dstColo r);
1006 1009
1007 switch (drawEffect.castEffect<XferEffect>().mode()) { 1010 switch (mode) {
1008 case SkXfermode::kOverlay_Mode: 1011 case SkXfermode::kOverlay_Mode:
1009 // Overlay is Hard-Light with the src and dst reversed 1012 // Overlay is Hard-Light with the src and dst reversed
1010 HardLight(builder, outputColor, dstColor, inputColor); 1013 HardLight(builder, outputColor, dstColor, inputColor);
1011 break; 1014 break;
1012 case SkXfermode::kDarken_Mode: 1015 case SkXfermode::kDarken_Mode:
1013 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.r gb + %s.rgb, " 1016 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", 1017 "(1.0 - %s.a) * %s.r gb + %s.rgb);\n",
1015 outputColor, 1018 outputColor,
1016 inputColor, dstColor, inputColor, 1019 inputColor, dstColor, inputColor,
1017 dstColor, inputColor, dstColor); 1020 dstColor, inputColor, dstColor);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 "2.0 * %s.rgb * %s.rgb;\ n", 1059 "2.0 * %s.rgb * %s.rgb;\ n",
1057 outputColor, dstColor, inputColor, ds tColor, inputColor); 1060 outputColor, dstColor, inputColor, ds tColor, inputColor);
1058 break; 1061 break;
1059 case SkXfermode::kMultiply_Mode: 1062 case SkXfermode::kMultiply_Mode:
1060 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1063 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1061 "(1.0 - %s.a) * %s.rgb + " 1064 "(1.0 - %s.a) * %s.rgb + "
1062 "%s.rgb * %s.rgb;\n", 1065 "%s.rgb * %s.rgb;\n",
1063 outputColor, inputColor, dstColor, ds tColor, inputColor, 1066 outputColor, inputColor, dstColor, ds tColor, inputColor,
1064 inputColor, dstColor); 1067 inputColor, dstColor);
1065 break; 1068 break;
1066 case SkXfermode::kHue_Mode: 1069 case SkXfermode::kHue_Mode: {
1067 case SkXfermode::kSaturation_Mode: 1070 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1068 case SkXfermode::kColor_Mode: 1071 SkString setSat, setLum;
1069 case SkXfermode::kLuminosity_Mode: 1072 AddSatFunction(builder, &setSat);
1070 GrCrash("Unimplemented XferEffect mode."); 1073 AddLumFunction(builder, &setLum);
robertphillips 2013/04/22 15:46:31 \n before dstColor?
bsalomon 2013/04/22 17:36:17 Done.
1074 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n" , dstColor, inputColor);
1075 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, ds tSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
robertphillips 2013/04/22 15:46:31 \n before inputColor?
bsalomon 2013/04/22 17:36:17 Done.
1076 outputColor, setLum.c_str(), setSat.c _str(), inputColor, dstColor);
1077 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1078 outputColor, inputColor, dstColor, ds tColor, inputColor);
1071 break; 1079 break;
1080 }
1081 case SkXfermode::kSaturation_Mode: {
1082 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1083 SkString setSat, setLum;
1084 AddSatFunction(builder, &setSat);
1085 AddLumFunction(builder, &setLum);
robertphillips 2013/04/22 15:46:31 \n
bsalomon 2013/04/22 17:36:17 Done.
1086 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n" , dstColor, inputColor);
1087 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
robertphillips 2013/04/22 15:46:31 /n
bsalomon 2013/04/22 17:36:17 Done.
1088 outputColor, setLum.c_str(), setSat.c _str(), inputColor, dstColor);
1089 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1090 outputColor, inputColor, dstColor, ds tColor, inputColor);
1091 break;
1092 }
1093 case SkXfermode::kColor_Mode: {
1094 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1095 SkString setLum;
1096 AddLumFunction(builder, &setLum);
robertphillips 2013/04/22 15:46:31 \n
bsalomon 2013/04/22 17:36:17 Done.
1097 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n" , inputColor, dstColor);
1098 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, src DstAlpha.a, %s.rgb * %s.a);\n",
1099 outputColor, setLum.c_str(), dstColor , inputColor);
1100 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1101 outputColor, inputColor, dstColor, ds tColor, inputColor);
1102 break;
1103 }
1104 case SkXfermode::kLuminosity_Mode: {
1105 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1106 SkString setLum;
1107 AddLumFunction(builder, &setLum);
robertphillips 2013/04/22 15:46:31 \n
bsalomon 2013/04/22 17:36:17 Done.
1108 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n" , inputColor, dstColor);
1109 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDs tAlpha.a, srcDstAlpha.rgb);\n",
1110 outputColor, setLum.c_str(), dstColor , inputColor);
1111 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1112 outputColor, inputColor, dstColor, ds tColor, inputColor);
1113 break;
1114 }
1072 default: 1115 default:
1073 GrCrash("Unknown XferEffect mode."); 1116 GrCrash("Unknown XferEffect mode.");
1074 break; 1117 break;
1075 } 1118 }
1076 } 1119 }
1077 1120
1078 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { 1121 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
1079 return drawEffect.castEffect<XferEffect>().mode(); 1122 return drawEffect.castEffect<XferEffect>().mode();
1080 } 1123 }
1081 1124
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 src, src, component, dst, src, src, component , src, src, 1213 src, src, component, dst, src, src, component , src, src,
1171 component); 1214 component);
1172 builder->fsCodeAppendf("\t\t\t} else {\n"); 1215 builder->fsCodeAppendf("\t\t\t} else {\n");
1173 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1216 // -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. 0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", 1217 builder->fsCodeAppendf("\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",
1175 final, component, dst, dst, component, src, src, component, dst, 1218 final, component, dst, dst, component, src, src, component, dst,
1176 src, component, dst, component, src, src, co mponent, src, 1219 src, component, dst, component, src, src, co mponent, src,
1177 component); 1220 component);
1178 builder->fsCodeAppendf("\t\t\t}\n"); 1221 builder->fsCodeAppendf("\t\t\t}\n");
1179 } 1222 }
1180 1223
robertphillips 2013/04/22 15:46:31 It also emits "luminance" method
bsalomon 2013/04/22 17:36:17 But it doesn't return the name of it, so it isn't
1224 // Adds a function that takes two colors and an alpha as input. It produ ces a color with the
1225 // hue and saturation of the first color, the luminosity of the second c olor, and the input
1226 // alpha. It has this signature:
1227 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor) .
1228 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumF unction) {
1229 SkString getFunction;
robertphillips 2013/04/22 15:46:31 Is the indent right after this {?
bsalomon 2013/04/22 17:36:17 I removed the blocks.
1230 {
robertphillips 2013/04/22 15:46:31 one line?
bsalomon 2013/04/22 17:36:17 Done.
1231 GrGLShaderVar args[] = {
1232 GrGLShaderVar("color", kVec3f_GrSLType),
1233 };
1234 SkString body("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1235 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1236 kFloat_GrSLType,
1237 "luminance",
1238 SK_ARRAY_COUNT(args), args,
1239 body.c_str(),
1240 &getFunction);
1241 }
1242
1243 {
1244 GrGLShaderVar args[] = {
1245 GrGLShaderVar("hueSat", kVec3f_GrSLType),
1246 GrGLShaderVar("alpha", kFloat_GrSLType),
1247 GrGLShaderVar("lumColor", kVec3f_GrSLType),
1248 };
1249 SkString body;
1250 body.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c _str());
1251 body.append("\tvec3 outColor = hueSat + diff;\n");
1252 body.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str() );
robertphillips 2013/04/22 15:46:31 Is this code happy with black?
bsalomon 2013/04/22 17:36:17 yup
1253 body.append("\tfloat minComp = min(min(outColor.r, outColor.g), outC olor.b);\n"
1254 "\tfloat maxComp = max(max(outColor.r, outColor.g), outC olor.b);\n"
1255 "\tif (minComp < 0.0) {\n"
1256 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLu m, outLum)) * outLum) / (outLum - minComp);\n"
1257 "\t}\n"
1258 "\tif (maxComp > alpha) {\n"
1259 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLu m, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1260 "\t}\n"
1261 "\treturn outColor;\n");
1262 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1263 kVec3f_GrSLType,
1264 "set_luminance",
1265 SK_ARRAY_COUNT(args), args,
1266 body.c_str(),
1267 setLumFunction);
1268 }
1269 }
1270
robertphillips 2013/04/22 15:46:31 functions that create?
bsalomon 2013/04/22 17:36:17 Changed to "Adds a function that creates"
1271 // Adds functions that creates a color with the hue and luminosity of on e input color and
1272 // the saturation of another color. It will have this signature:
1273 // float set_saturation(vec3 hueLumColor, vec3 satColor)
1274 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatF unction) {
1275 SkString getFunction;
robertphillips 2013/04/22 15:46:31 // emit 'saturation' function?
bsalomon 2013/04/22 17:36:17 Done.
1276 {
1277 GrGLShaderVar args[] = {
1278 GrGLShaderVar("color", kVec3f_GrSLType),
1279 };
1280 SkString body;
1281 body.appendf("\treturn max(max(color.r, color.g), color.b) - "
1282 "min(min(color.r, color.g), color.b);\n");
1283 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1284 kFloat_GrSLType,
1285 "saturation",
1286 SK_ARRAY_COUNT(args), args,
1287 body.c_str(),
1288 &getFunction);
1289 }
1290
1291 SkString helper;
robertphillips 2013/04/22 15:46:31 emit "set_saturation_helper" method?
bsalomon 2013/04/22 17:36:17 Done.
1292 {
1293 GrGLShaderVar args[] = {
1294 GrGLShaderVar("minComp", kFloat_GrSLType),
1295 GrGLShaderVar("midComp", kFloat_GrSLType),
1296 GrGLShaderVar("maxComp", kFloat_GrSLType),
1297 GrGLShaderVar("sat", kFloat_GrSLType),
1298 };
1299 args[0].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1300 args[1].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1301 args[2].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1302 SkString body;
1303 body.append("\tif (minComp < maxComp) {\n"
1304 "\t\tmidComp = sat * (midComp - minComp) / (maxComp - mi nComp);\n"
1305 "\t\tmaxComp = sat;\n"
1306 "\t} else {\n"
1307 "\t\tmidComp = midComp = 0.0;\n"
1308 "\t}\n"
1309 "\tminComp = 0.0;\n");
1310 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1311 kVoid_GrSLType,
1312 "set_saturation_helper",
1313 SK_ARRAY_COUNT(args), args,
1314 body.c_str(),
1315 &helper);
1316 }
1317 {
1318 GrGLShaderVar args[] = {
1319 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1320 GrGLShaderVar("satColor", kVec3f_GrSLType),
1321 };
1322 SkString body;
1323 const char* helpFunc = helper.c_str();
1324 body.appendf("\tfloat sat = %s(satColor);\n"
1325 "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1326 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1327 "\t\t\t%s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1328 "\t\t} else {\n"
1329 "\t\t\t%s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1330 "\t\t}\n"
1331 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1332 "\t\t%s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sa t);\n"
1333 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1334 "\t\t%s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sa t);\n"
1335 "\t} else {\n"
1336 "\t\t%s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sa t);\n"
1337 "\t}\n"
1338 "\treturn hueLumColor;",
1339 getFunction.c_str(), helpFunc, helpFunc, helpFunc, help Func, helpFunc);
1340 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1341 kVec3f_GrSLType,
1342 "set_saturation",
1343 SK_ARRAY_COUNT(args), args,
1344 body.c_str(),
1345 setSatFunction);
1346 }
1347
1348 }
1349
1181 typedef GrGLEffect INHERITED; 1350 typedef GrGLEffect INHERITED;
1182 }; 1351 };
1183 1352
1184 GR_DECLARE_EFFECT_TEST; 1353 GR_DECLARE_EFFECT_TEST;
1185 1354
1186 private: 1355 private:
1187 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); } 1356 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); }
1188 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; } 1357 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; }
1189 1358
1190 SkXfermode::Mode fMode; 1359 SkXfermode::Mode fMode;
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 return proc16; 1964 return proc16;
1796 } 1965 }
1797 1966
1798 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1967 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1799 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1968 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1800 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1969 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1801 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1970 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1802 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1971 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1803 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1972 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1804 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1973 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
OLDNEW
« no previous file with comments | « src/core/SkString.cpp ('k') | src/gpu/gl/GrGLShaderBuilder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698