Add extra blending modes.
This change adds the following blending modes for shaders and color filters:
Add
Multiply
Screen
Overlay
Darken
Lighten
Change-Id: Iff22f5ce6041b43c71b1857d73013f5010ab3413
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 2449b6d..39fe85a 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -137,7 +137,7 @@
// PorterDuff snippets
///////////////////////////////////////////////////////////////////////////////
-const char* gPorterDuff[12] = {
+const char* gBlendOps[18] = {
// Clear
"return vec4(0.0, 0.0, 0.0, 0.0);\n",
// Src
@@ -161,8 +161,26 @@
// DstAtop
"return vec4(dst.rgb * src.a + (1.0 - dst.a) * src.rgb, src.a);\n",
// Xor
- "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, 1.0, "
+ "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb, "
"src.a + dst.a - 2.0 * src.a * dst.a);\n",
+ // Add
+ "return min(src + dst, 1.0);\n",
+ // Multiply
+ "return src * dst;\n",
+ // Screen
+ "return src + dst - src * dst;\n",
+ // Overlay
+ "return clamp(vec4(mix("
+ "2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
+ "src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a), "
+ "step(dst.a, 2.0 * dst.rgb)), "
+ "src.a + dst.a - src.a * dst.a), 0.0, 1.0);\n",
+ // Darken
+ "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
+ "min(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
+ // Lighten
+ "return vec4(src.rgb * (1.0 - dst.a) + (1.0 - src.a) * dst.rgb + "
+ "max(src.rgb * dst.a, dst.rgb * src.a), src.a + dst.a - src.a * dst.a);\n",
};
///////////////////////////////////////////////////////////////////////////////
@@ -292,10 +310,10 @@
// Generate required functions
if (description.hasGradient && description.hasBitmap) {
- generatePorterDuffBlend(shader, "blendShaders", description.shadersMode);
+ generateBlend(shader, "blendShaders", description.shadersMode);
}
if (description.colorOp == ProgramDescription::kColorBlend) {
- generatePorterDuffBlend(shader, "blendColors", description.colorMode);
+ generateBlend(shader, "blendColors", description.colorMode);
}
if (description.isBitmapNpot) {
generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
@@ -354,13 +372,12 @@
return shader;
}
-void ProgramCache::generatePorterDuffBlend(String8& shader, const char* name,
- SkXfermode::Mode mode) {
+void ProgramCache::generateBlend(String8& shader, const char* name, SkXfermode::Mode mode) {
shader.append("\nvec4 ");
shader.append(name);
shader.append("(vec4 src, vec4 dst) {\n");
shader.append(" ");
- shader.append(gPorterDuff[mode]);
+ shader.append(gBlendOps[mode]);
shader.append("}\n");
}
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index a1a4a0e..54850ee 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -35,7 +35,7 @@
///////////////////////////////////////////////////////////////////////////////
// Debug
-#define DEBUG_PROGRAM_CACHE 0
+#define DEBUG_PROGRAM_CACHE 1
// Debug
#if DEBUG_PROGRAM_CACHE
@@ -57,9 +57,9 @@
#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
#define PROGRAM_KEY_BITMAP_WRAPT_MASK 0x1800
-// Support only the 12 Porter-Duff modes for now
-#define PROGRAM_MAX_XFERMODE 0xC
-#define PROGRAM_XFERMODE_SHADER_SHIFT 24
+// Encode the xfermodes on 6 bits
+#define PROGRAM_MAX_XFERMODE 0x1f
+#define PROGRAM_XFERMODE_SHADER_SHIFT 26
#define PROGRAM_XFERMODE_COLOR_OP_SHIFT 20
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
@@ -177,7 +177,7 @@
Program* generateProgram(const ProgramDescription& description, programid key);
String8 generateVertexShader(const ProgramDescription& description);
String8 generateFragmentShader(const ProgramDescription& description);
- void generatePorterDuffBlend(String8& shader, const char* name, SkXfermode::Mode mode);
+ void generateBlend(String8& shader, const char* name, SkXfermode::Mode mode);
void generateTextureWrap(String8& shader, GLenum wrapS, GLenum wrapT);
void printLongString(const String8& shader) const;