Exclusion and Difference modes using Sk4f
authorreed <reed@chromium.org>
Fri, 3 Apr 2015 02:19:13 +0000 (19:19 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 3 Apr 2015 02:19:14 +0000 (19:19 -0700)
Before:
   7M 1 15.3ms 15.5ms 15.8ms 17.2ms 4% ▁█▄▁▇▂▁▁▂▁ 8888 Xfermode_Exclusion
   7M 1 16.5ms 17.1ms 17.3ms 18.8ms 5% ▁█▃█▃▂▂▃▂▂ 8888 Xfermode_Difference

After:
   7M 1 9.06ms 9.34ms 9.42ms 10.4ms 4% ▁▁▅▄█▁▂▁▂▃ 8888 Xfermode_Exclusion
   7M 1 10.5ms 10.9ms 11ms 12ms 5% ▃▁▆█▂▁▅▂▁▃ 8888 Xfermode_Difference

TBR=mtklein@google.com

Review URL: https://codereview.chromium.org/1060493002

src/core/SkXfermode.cpp

index 92743c2..d78dcd8 100644 (file)
@@ -1201,6 +1201,13 @@ static Sk4f clamp_0_255(const Sk4f& value) {
     return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
 }
 
+// return a swizzle of a | rgb
+static Sk4f set_a_rgb(const Sk4f& a, const Sk4f& rgb) {
+    SkPMFloat pma = a;
+    SkPMFloat pmc = rgb;
+    return SkPMFloat(pma.a(), pmc.r(), pmc.g(), pmc.b());
+}
+
 /**
  *  Some modes can, due to very slight numerical error, generate "invalid" pmcolors...
  *
@@ -1311,6 +1318,34 @@ struct Multiply4f {
     static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
 };
 
+struct Difference4f {
+    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
+        const Sk4f inv255(gInv255);
+        Sk4f sa = Sk4f(src.a());
+        Sk4f da = Sk4f(dst.a());
+        Sk4f sc = src;
+        Sk4f dc = dst;
+        Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255;
+        Sk4f ra = sc + dc - min;
+        return check_as_pmfloat(set_a_rgb(ra, ra - min));
+    }
+    static const bool kFoldCoverageIntoSrcAlpha = false;
+    static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode;
+};
+
+struct Exclusion4f {
+    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
+        const Sk4f inv255(gInv255);
+        Sk4f sc = src;
+        Sk4f dc = dst;
+        Sk4f prod = sc * dc * inv255;
+        Sk4f ra = sc + dc - prod;
+        return check_as_pmfloat(set_a_rgb(ra, ra - prod));
+    }
+    static const bool kFoldCoverageIntoSrcAlpha = false;
+    static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode;
+};
+
 template <typename ProcType>
 class SkT4fXfermode : public SkProcCoeffXfermode {
 public:
@@ -1445,6 +1480,12 @@ SkXfermode* create_mode(int iMode) {
         case SkXfermode::kMultiply_Mode:
             xfer = SkT4fXfermode<Multiply4f>::Create(rec);
             break;
+        case SkXfermode::kDifference_Mode:
+            xfer = SkT4fXfermode<Difference4f>::Create(rec);
+            break;
+        case SkXfermode::kExclusion_Mode:
+            xfer = SkT4fXfermode<Exclusion4f>::Create(rec);
+            break;
         default:
             break;
     }