Color filter benchmarks

Add a bunch of color filter benches:

      3.35 !	colorfilter_matrix_runtime  gl
      2.43  	colorfilter_src_runtime     gl
      2.41 !	colorfilter_lerp_src        gl
      2.40 ?	colorfilter_compose_src     gl
      6.72  	colorfilter_matrix_hsla     gl
      3.41 ?	colorfilter_matrix_rgba     gl
      4.41 !	colorfilter_srgb_to_linear  gl
      4.31 ?	colorfilter_linear_to_srgb  gl
      2.53  	colorfilter_blend_srcover   gl
      2.43 ?	colorfilter_blend_src	    gl
      2.44 !	colorfilter_none            gl

    753.31 ?	colorfilter_matrix_runtime  8888
    257.59 ?	colorfilter_src_runtime     8888
    111.94 ?	colorfilter_lerp_src        8888
     82.35 ?	colorfilter_compose_src     8888
    600.24 !	colorfilter_matrix_hsla     8888
    304.49  	colorfilter_matrix_rgba     8888
    457.25 ?	colorfilter_srgb_to_linear  8888
    493.23 ?	colorfilter_linear_to_srgb  8888
     95.61 ?	colorfilter_blend_srcover   8888
     74.41 ?	colorfilter_blend_src	    8888
     19.15 ?	colorfilter_none            8888


Change-Id: I08dfc81b14cba098b00edf2af150b82541003139
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/250260
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/bench/ColorFilterBench.cpp b/bench/ColorFilterBench.cpp
index 86a9f60..8005cf5 100644
--- a/bench/ColorFilterBench.cpp
+++ b/bench/ColorFilterBench.cpp
@@ -8,7 +8,10 @@
 #include "bench/Benchmark.h"
 #include "include/core/SkCanvas.h"
 #include "include/core/SkColorFilter.h"
+#include "include/core/SkSurface.h"
 #include "include/effects/SkImageFilters.h"
+#include "src/core/SkColorFilterPriv.h"
+#include "tools/Resources.h"
 
 // Just need an interesting filter, nothing to special about colormatrix
 static sk_sp<SkColorFilter> make_grayscale() {
@@ -76,3 +79,136 @@
 DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kNoFilter_Type); )
 DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kColorFilter_Type); )
 DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kImageFilter_Type); )
+
+namespace  {
+
+class ColorMatrixBench final : public Benchmark {
+public:
+    using Factory = sk_sp<SkColorFilter>(*)();
+
+    explicit ColorMatrixBench(const char* suffix, Factory f)
+        : fFactory(f)
+        , fName(SkStringPrintf("colorfilter_%s", suffix)) {}
+
+private:
+    const char* onGetName() override {
+        return fName.c_str();
+    }
+
+    SkIPoint onGetSize() override {
+        return { 256, 256 };
+    }
+
+    void onDelayedSetup() override {
+        // Pass the image though a premul canvas so that we "forget" it is opaque.
+        auto surface = SkSurface::MakeRasterN32Premul(256, 256);
+        surface->getCanvas()->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0);
+
+        fImage = surface->makeImageSnapshot();
+        fColorFilter = fFactory();
+    }
+
+    void onDraw(int loops, SkCanvas* canvas) override {
+        SkPaint p;
+        p.setColorFilter(fColorFilter);
+
+        for (int i = 0; i < loops; ++i) {
+            canvas->drawImage(fImage, 0, 0, &p);
+        }
+    }
+
+    const Factory  fFactory;
+    const SkString fName;
+
+    sk_sp<SkImage>       fImage;
+    sk_sp<SkColorFilter> fColorFilter;
+};
+
+void RuntimeNone_CPU(float[4], const void*) {}
+
+const char RuntimeNone_GPU_SRC[] = R"(
+    void main(inout half4 c) {}
+)";
+
+void RuntimeColorMatrix_CPU(float colors[4], const void* ctx) {
+    auto c = reinterpret_cast<SkRGBA4f<kPremul_SkAlphaType>*>(colors)->unpremul();
+
+    const auto* m = static_cast<const float*>(ctx);
+    const auto c0 = c[0]*m[ 0] + c[1]*m[ 1] + c[2]*m[ 2] + c[3]*m[ 3] + m[ 4],
+               c1 = c[0]*m[ 5] + c[1]*m[ 6] + c[2]*m[ 7] + c[3]*m[ 8] + m[ 9],
+               c2 = c[0]*m[10] + c[1]*m[11] + c[2]*m[12] + c[3]*m[13] + m[14],
+               c3 = c[0]*m[15] + c[1]*m[16] + c[2]*m[17] + c[3]*m[18] + m[19];
+    c[0] = c0;
+    c[1] = c1;
+    c[2] = c2;
+    c[3] = c3;
+
+    *reinterpret_cast<SkRGBA4f<kPremul_SkAlphaType>*>(colors) = c.premul();
+}
+
+const char RuntimeColorMatrix_GPU_SRC[] = R"(
+    // WTB matrix/vector inputs.
+    layout(ctype=float) in uniform half m0 , m1 , m2 , m3 , m4 ,
+                                        m5 , m6 , m7 , m8 , m9 ,
+                                        m10, m11, m12, m13, m14,
+                                        m15, m16, m17, m18, m19;
+    void main(inout half4 c) {
+        half nonZeroAlpha = max(c.a, 0.0001);
+        c = half4(c.rgb / nonZeroAlpha, nonZeroAlpha);
+
+        half4x4 m = half4x4(m0, m5, m10, m15,
+                            m1, m6, m11, m16,
+                            m2, m7, m12, m17,
+                            m3, m8, m13, m18);
+        c = m * c + half4  (m4, m9, m14, m19);
+
+        c = saturate(c);
+        c.rgb *= c.a;
+    }
+)";
+
+static constexpr float gColorMatrix[] = {
+    0.3f, 0.3f, 0.0f, 0.0f, 0.3f,
+    0.0f, 0.3f, 0.3f, 0.0f, 0.3f,
+    0.0f, 0.0f, 0.3f, 0.3f, 0.3f,
+    0.3f, 0.0f, 0.3f, 0.3f, 0.0f,
+};
+
+} // namespace
+
+DEF_BENCH( return new ColorMatrixBench("none",
+    []() { return sk_sp<SkColorFilter>(nullptr); }); )
+DEF_BENCH( return new ColorMatrixBench("blend_src",
+    []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc); }); )
+DEF_BENCH( return new ColorMatrixBench("blend_srcover",
+    []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrcOver); }); )
+DEF_BENCH( return new ColorMatrixBench("linear_to_srgb",
+    []() { return SkColorFilters::LinearToSRGBGamma(); }); )
+DEF_BENCH( return new ColorMatrixBench("srgb_to_linear",
+    []() { return SkColorFilters::SRGBToLinearGamma(); }); )
+DEF_BENCH( return new ColorMatrixBench("matrix_rgba",
+    []() { return SkColorFilters::Matrix(gColorMatrix); }); )
+DEF_BENCH( return new ColorMatrixBench("matrix_hsla",
+    []() { return SkColorFilters::HSLAMatrix(gColorMatrix); }); )
+DEF_BENCH( return new ColorMatrixBench("compose_src",
+    []() { return SkColorFilters::Compose(SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc),
+                                          SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc));
+    }); )
+DEF_BENCH( return new ColorMatrixBench("lerp_src",
+    []() { return SkColorFilters::Lerp(0.3f,
+                                       SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc),
+                                       SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc));
+    }); )
+
+#ifdef SK_SUPPORT_GPU
+DEF_BENCH( return new ColorMatrixBench("src_runtime", []() {
+        static SkRuntimeColorFilterFactory gRuntimeFact(SkString(RuntimeNone_GPU_SRC),
+                                                        RuntimeNone_CPU);
+        return gRuntimeFact.make(SkData::MakeWithCopy(gColorMatrix, sizeof(gColorMatrix)));
+    });)
+DEF_BENCH( return new ColorMatrixBench("matrix_runtime", []() {
+        static SkRuntimeColorFilterFactory gRuntimeFact(SkString(RuntimeColorMatrix_GPU_SRC),
+                                                        RuntimeColorMatrix_CPU);
+        return gRuntimeFact.make(SkData::MakeWithCopy(gColorMatrix, sizeof(gColorMatrix)));
+    });)
+#endif