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");
 }