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

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) {
robertphillips 2013/04/19 14:16:32 return(!<expression>)?
bsalomon 2013/04/19 14:24:28 will do
959 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 958 if (mode <= SkXfermode::kLastCoeffMode || mode > SkXfermode::kLastSepara bleMode) {
960 return CreateEffectRef(gEffect); 959 return false;
960 }
961 return true;
962 }
963
964 static GrEffectRef* Create(SkXfermode::Mode mode) {
965 if (!IsSupportedMode(mode)) {
966 return NULL;
967 } else {
968 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode)));
969 return CreateEffectRef(effect);
970 }
961 } 971 }
962 972
963 virtual void getConstantColorComponents(GrColor* color, 973 virtual void getConstantColorComponents(GrColor* color,
964 uint32_t* validFlags) const SK_OVERR IDE { 974 uint32_t* validFlags) const SK_OVERR IDE {
965 *validFlags = 0; 975 *validFlags = 0;
966 } 976 }
967 977
968 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 978 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
969 return GrTBackendEffectFactory<DarkenEffect>::getInstance(); 979 return GrTBackendEffectFactory<XferEffect>::getInstance();
970 } 980 }
971 981
972 static const char* Name() { return "XfermodeDarken"; } 982 static const char* Name() { return "XferEffect"; }
983
984 SkXfermode::Mode mode() const { return fMode; }
973 985
974 class GLEffect : public GrGLEffect { 986 class GLEffect : public GrGLEffect {
975 public: 987 public:
976 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 988 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
977 : GrGLEffect(factory ) { 989 : GrGLEffect(factory ) {
978 } 990 }
979 virtual void emitCode(GrGLShaderBuilder* builder, 991 virtual void emitCode(GrGLShaderBuilder* builder,
980 const GrDrawEffect& drawEffect, 992 const GrDrawEffect& drawEffect,
981 EffectKey key, 993 EffectKey key,
982 const char* outputColor, 994 const char* outputColor,
983 const char* inputColor, 995 const char* inputColor,
984 const TextureSamplerArray& samplers) SK_OVERRIDE { 996 const TextureSamplerArray& samplers) SK_OVERRIDE {
985 const char* dstColorName = builder->dstColor(); 997 const char* dstColor = builder->dstColor();
986 GrAssert(NULL != dstColorName); 998 GrAssert(NULL != dstColor);
999
1000 // We don't try to optimize for this case at all
987 if (NULL == inputColor) { 1001 if (NULL == inputColor) {
988 // the input color is solid white 1002 builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVe cf(4));
989 builder->fsCodeAppendf("\t\t%s.a = 1.0;\n", outputColor); 1003 inputColor = "ones";
990 builder->fsCodeAppendf("\t\t%s.rgb = vec3(1.0, 1.0, 1.0) - %s.aa a + %s.rgb;\n", 1004 }
991 outputColor, dstColorName, dstColorName); 1005
992 } else { 1006 // These all perform src-over on the alpha channel.
993 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - % s.a);\n", 1007 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
994 outputColor, dstColorName, inputColor); 1008 outputColor, inputColor, inputColor, dstColo r);
995 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb," 1009
996 " (1.0 - %s.a) * %s.rgb + %s.rgb);\n", 1010 switch (drawEffect.castEffect<XferEffect>().mode()) {
997 outputColor, 1011 case SkXfermode::kOverlay_Mode:
998 inputColor, dstColorName, inputColor, 1012 // Overlay is Hard-Light with the src and dst reversed
999 dstColorName, inputColor, dstColorName); 1013 HardLight(builder, outputColor, dstColor, inputColor);
1014 break;
1015 case SkXfermode::kDarken_Mode:
1016 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.r gb + %s.rgb, "
1017 "(1.0 - %s.a) * %s.r gb + %s.rgb);\n",
1018 outputColor,
1019 inputColor, dstColor, inputColor,
1020 dstColor, inputColor, dstColor);
1021 break;
1022 case SkXfermode::kLighten_Mode:
1023 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.r gb + %s.rgb, "
1024 "(1.0 - %s.a) * %s.r gb + %s.rgb);\n",
1025 outputColor,
1026 inputColor, dstColor, inputColor,
1027 dstColor, inputColor, dstColor);
1028 break;
1029 case SkXfermode::kColorDodge_Mode:
1030 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'r');
jvanverth1 2013/04/19 14:16:15 Is there a reason these (and following) are separa
bsalomon 2013/04/19 14:24:28 Just that they couldn't be easily be done vectored
1031 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'g');
1032 ColorDodgeComponent(builder, outputColor, inputColor, dstCol or, 'b');
1033 break;
1034 case SkXfermode::kColorBurn_Mode:
1035 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'r');
1036 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'g');
1037 ColorBurnComponent(builder, outputColor, inputColor, dstColo r, 'b');
1038 break;
1039 case SkXfermode::kHardLight_Mode:
1040 HardLight(builder, outputColor, inputColor, dstColor);
1041 break;
1042 case SkXfermode::kSoftLight_Mode:
1043 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor) ;
1044 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
1045 builder->fsCodeAppendf("\t\t} else {\n");
1046 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'r');
1047 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'g');
1048 SoftLightComponentPosDstAlpha(builder, outputColor, inputCol or, dstColor, 'b');
1049 builder->fsCodeAppendf("\t\t}\n");
1050 break;
1051 case SkXfermode::kDifference_Mode:
1052 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1053 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1054 outputColor, inputColor, dstColor, in putColor, dstColor,
1055 dstColor, inputColor);
1056 break;
1057 case SkXfermode::kExclusion_Mode:
1058 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1059 "2.0 * %s.rgb * %s.rgb;\ n",
1060 outputColor, dstColor, inputColor, ds tColor, inputColor);
1061 break;
1062 case SkXfermode::kMultiply_Mode:
1063 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1064 "(1.0 - %s.a) * %s.rgb + "
1065 "%s.rgb * %s.rgb;\n",
1066 outputColor, inputColor, dstColor, ds tColor, inputColor,
1067 inputColor, dstColor);
1068 break;
1069 case SkXfermode::kHue_Mode:
1070 case SkXfermode::kSaturation_Mode:
1071 case SkXfermode::kColor_Mode:
1072 case SkXfermode::kLuminosity_Mode:
1073 GrCrash("Unimplemented XferEffect mode.");
1074 break;
1075 default:
1076 GrCrash("Unknown XferEffect mode.");
1077 break;
1000 } 1078 }
1001 } 1079 }
1002 1080
1003 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { r eturn 0; } 1081 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
1082 return drawEffect.castEffect<XferEffect>().mode();
1083 }
1004 1084
1005 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {} 1085 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
1006 1086
1007 private: 1087 private:
1088 static void HardLight(GrGLShaderBuilder* builder, const char* final, con st char* src, const char* dst) {
1089 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a) ;\n", final, dst, src);
bsalomon 2013/04/19 13:59:21 I can wrap these, but I'm not sure that it helps a
jvanverth1 2013/04/19 14:16:15 It'd probably help to put the varargs on the follo
bsalomon 2013/04/19 14:24:28 will do
1090 builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ", f inal, src, dst);
1091 builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),", src, dst, dst, dst, src, src);
1092 builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n" , src, src);
1093 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", final, src, dst, dst, src);
1094 }
1095
1096 // Does one component of color-dodge
1097 static void ColorDodgeComponent(GrGLShaderBuilder* builder, const char* final, const char* src, const char* dst, const char component) {
jvanverth1 2013/04/19 14:16:15 Wrap function decls at least?
bsalomon 2013/04/19 14:24:28 will do
1098 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1099 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1 - %s.a);\n", final, component, src, component, dst);
1100 builder->fsCodeAppend("\t\t} else {\n");
1101 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1102 builder->fsCodeAppend("\t\t\tif (0 == d) {\n");
1103 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", final, component, src, dst, src, component, d st, dst, component, src);
1104 builder->fsCodeAppend("\t\t\t} else {\n");
1105 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", dst, dst, component, src);
1106 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s .a) + %s.%c * (1.0 - %s.a);\n", final, component, src, src, component, dst, dst, component, src);
1107 builder->fsCodeAppend("\t\t\t}\n");
1108 builder->fsCodeAppend("\t\t}\n");
1109 }
1110
1111 // Does one component of color-burn
1112 static void ColorBurnComponent(GrGLShaderBuilder* builder, const char* f inal, const char* src, const char* dst, const char component) {
1113 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, compo nent);
1114 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - % s.a) + %s.%c * (1.0 - %s.a);\n", final, component, src, dst, src, component, dst , dst, component, src);
1115 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, comp onent);
1116 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", fina l, component, dst, component, src);
1117 builder->fsCodeAppend("\t\t} else {\n");
1118 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.% c) * %s.a / %s.%c);\n", dst, dst, dst, component, src, src, component);
1119 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a ) + %s.%c * (1.0 - %s.a);\n", final, component, src, src, component, dst, dst, c omponent, src);
1120 builder->fsCodeAppend("\t\t}\n");
1121 }
1122
1123 // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1124 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, co nst char* final, const char* src, const char* dst, const char component) {
1125 // if (2S < Sa)
1126 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, co mponent, src);
1127 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1128 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", final, compone nt, dst, component, dst, component, src, src, component, dst, dst, src, componen t, dst, component, src, src, component);
1129 // else if (4D < Da)
1130 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", dst, component, dst);
1131 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", dst, component, dst, component);
1132 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1133 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1134 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst) ;
1135 // (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
1136 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", final, component, src, component, src, component, dst, component, src, src, component, dst, src, src, component, src, src, compone nt);
1137 builder->fsCodeAppendf("\t\t\t} else {\n");
1138 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1139 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", final, component, dst, dst, component, src, src, component, dst, src, component, dst, component, s rc, src, component, src, component);
1140 builder->fsCodeAppendf("\t\t\t}\n");
1141 }
1142
1008 typedef GrGLEffect INHERITED; 1143 typedef GrGLEffect INHERITED;
1009 }; 1144 };
1010 1145
1011 GR_DECLARE_EFFECT_TEST; 1146 GR_DECLARE_EFFECT_TEST;
1012 1147
1013 private: 1148 private:
1014 DarkenEffect() { this->setWillReadDst(); } 1149 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); }
1015 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; } 1150 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return tru e; }
1151
1152 SkXfermode::Mode fMode;
1016 1153
1017 typedef GrEffect INHERITED; 1154 typedef GrEffect INHERITED;
1018 }; 1155 };
1019 1156
1020 GR_DEFINE_EFFECT_TEST(DarkenEffect); 1157 GR_DEFINE_EFFECT_TEST(XferEffect);
1021 GrEffectRef* DarkenEffect::TestCreate(SkMWCRandom*, 1158 GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand,
1022 GrContext*, 1159 GrContext*,
1023 const GrDrawTargetCaps&, 1160 const GrDrawTargetCaps&,
1024 GrTexture*[]) { 1161 GrTexture*[]) {
1025 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 1162 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas tSeparableMode);
1163 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermod e::Mode>(mode))));
1026 return CreateEffectRef(gEffect); 1164 return CreateEffectRef(gEffect);
1027 } 1165 }
1028 1166
1029 #endif 1167 #endif
1030 1168
1031 /////////////////////////////////////////////////////////////////////////////// 1169 ///////////////////////////////////////////////////////////////////////////////
1032 /////////////////////////////////////////////////////////////////////////////// 1170 ///////////////////////////////////////////////////////////////////////////////
1033 1171
1034 class SkProcCoeffXfermode : public SkProcXfermode { 1172 class SkProcCoeffXfermode : public SkProcXfermode {
1035 public: 1173 public:
(...skipping 27 matching lines...) Expand all
1063 } 1201 }
1064 1202
1065 #if SK_SUPPORT_GPU 1203 #if SK_SUPPORT_GPU
1066 virtual bool asNewEffectOrCoeff(GrContext*, 1204 virtual bool asNewEffectOrCoeff(GrContext*,
1067 GrEffectRef** effect, 1205 GrEffectRef** effect,
1068 Coeff* src, 1206 Coeff* src,
1069 Coeff* dst) const SK_OVERRIDE { 1207 Coeff* dst) const SK_OVERRIDE {
1070 if (this->asCoeff(src, dst)) { 1208 if (this->asCoeff(src, dst)) {
1071 return true; 1209 return true;
1072 } 1210 }
1073 if (kDarken_Mode == fMode) { 1211 if (XferEffect::IsSupportedMode(fMode)) {
1074 if (NULL != effect) { 1212 if (NULL != effect) {
1075 *effect = DarkenEffect::Create(); 1213 *effect = XferEffect::Create(fMode);
1214 SkASSERT(NULL != *effect);
1076 } 1215 }
1077 return true; 1216 return true;
1078 } 1217 }
1079 return false; 1218 return false;
1080 } 1219 }
1081 #endif 1220 #endif
1082 1221
1083 SK_DEVELOPER_TO_STRING() 1222 SK_DEVELOPER_TO_STRING()
1084 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 1223 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
1085 1224
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 return proc16; 1757 return proc16;
1619 } 1758 }
1620 1759
1621 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1760 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1622 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1761 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1623 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1762 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1624 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1763 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1625 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1764 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1626 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1765 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1627 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1766 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