sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2013 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
reed | aa4c7a7 | 2015-04-02 20:31:17 -0700 | [diff] [blame] | 7 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "bench/Benchmark.h" |
| 9 | #include "include/core/SkCanvas.h" |
Michael Ludwig | 2300318 | 2019-08-05 11:25:23 -0400 | [diff] [blame] | 10 | #include "include/core/SkColorFilter.h" |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 11 | #include "include/core/SkSurface.h" |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 12 | #include "include/effects/SkHighContrastFilter.h" |
Michael Ludwig | 2300318 | 2019-08-05 11:25:23 -0400 | [diff] [blame] | 13 | #include "include/effects/SkImageFilters.h" |
Mike Reed | ea1d105 | 2020-03-27 12:25:44 -0400 | [diff] [blame] | 14 | #include "include/effects/SkOverdrawColorFilter.h" |
Brian Osman | ee426f2 | 2020-01-02 11:55:24 -0500 | [diff] [blame] | 15 | #include "include/effects/SkRuntimeEffect.h" |
Mike Reed | f36b37f | 2020-03-27 15:11:10 -0400 | [diff] [blame] | 16 | #include "src/core/SkColorFilterPriv.h" |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 17 | #include "tools/Resources.h" |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 18 | |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 19 | // Just need an interesting filter, nothing to special about colormatrix |
| 20 | static sk_sp<SkColorFilter> make_grayscale() { |
Mike Reed | e869a1e | 2019-04-30 12:18:54 -0400 | [diff] [blame] | 21 | float matrix[20]; |
| 22 | memset(matrix, 0, 20 * sizeof(float)); |
robertphillips | 5605b56 | 2016-04-05 11:50:42 -0700 | [diff] [blame] | 23 | matrix[0] = matrix[5] = matrix[10] = 0.2126f; |
| 24 | matrix[1] = matrix[6] = matrix[11] = 0.7152f; |
| 25 | matrix[2] = matrix[7] = matrix[12] = 0.0722f; |
| 26 | matrix[18] = 1.0f; |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 27 | return SkColorFilters::Matrix(matrix); |
robertphillips | 5605b56 | 2016-04-05 11:50:42 -0700 | [diff] [blame] | 28 | } |
| 29 | |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 30 | /** |
| 31 | * Different ways to draw the same thing (a red rect) |
| 32 | * All of their timings should be about the same |
| 33 | * (we allow for slight overhead to figure out that we can undo the presence of the filters) |
| 34 | */ |
| 35 | class FilteredRectBench : public Benchmark { |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 36 | public: |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 37 | enum Type { |
| 38 | kNoFilter_Type, |
| 39 | kColorFilter_Type, |
| 40 | kImageFilter_Type, |
| 41 | }; |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 42 | |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 43 | FilteredRectBench(Type t) : fType(t) { |
| 44 | static const char* suffix[] = { "nofilter", "colorfilter", "imagefilter" }; |
| 45 | fName.printf("filteredrect_%s", suffix[t]); |
| 46 | fPaint.setColor(SK_ColorRED); |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 47 | } |
| 48 | |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 49 | protected: |
| 50 | const char* onGetName() override { |
| 51 | return fName.c_str(); |
| 52 | } |
| 53 | |
| 54 | void onDelayedSetup() override { |
| 55 | switch (fType) { |
| 56 | case kNoFilter_Type: |
| 57 | break; |
| 58 | case kColorFilter_Type: |
| 59 | fPaint.setColorFilter(make_grayscale()); |
| 60 | break; |
| 61 | case kImageFilter_Type: |
Michael Ludwig | 2300318 | 2019-08-05 11:25:23 -0400 | [diff] [blame] | 62 | fPaint.setImageFilter(SkImageFilters::ColorFilter(make_grayscale(), nullptr)); |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 63 | break; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | void onDraw(int loops, SkCanvas* canvas) override { |
| 68 | const SkRect r = { 0, 0, 256, 256 }; |
| 69 | for (int i = 0; i < loops; ++i) { |
| 70 | canvas->drawRect(r, fPaint); |
| 71 | } |
| 72 | } |
reed | aa4c7a7 | 2015-04-02 20:31:17 -0700 | [diff] [blame] | 73 | |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 74 | private: |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 75 | SkPaint fPaint; |
| 76 | SkString fName; |
| 77 | Type fType; |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 78 | |
John Stiles | 7571f9e | 2020-09-02 22:42:33 -0400 | [diff] [blame] | 79 | using INHERITED = Benchmark; |
sugoi@google.com | 580a172 | 2013-04-23 14:20:45 +0000 | [diff] [blame] | 80 | }; |
| 81 | |
Mike Reed | d93ee53 | 2019-05-20 12:30:37 -0400 | [diff] [blame] | 82 | DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kNoFilter_Type); ) |
| 83 | DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kColorFilter_Type); ) |
| 84 | DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kImageFilter_Type); ) |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 85 | |
| 86 | namespace { |
| 87 | |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 88 | class ColorFilterBench final : public Benchmark { |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 89 | public: |
| 90 | using Factory = sk_sp<SkColorFilter>(*)(); |
| 91 | |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 92 | explicit ColorFilterBench(const char* suffix, Factory f) |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 93 | : fFactory(f) |
| 94 | , fName(SkStringPrintf("colorfilter_%s", suffix)) {} |
| 95 | |
| 96 | private: |
| 97 | const char* onGetName() override { |
| 98 | return fName.c_str(); |
| 99 | } |
| 100 | |
| 101 | SkIPoint onGetSize() override { |
| 102 | return { 256, 256 }; |
| 103 | } |
| 104 | |
| 105 | void onDelayedSetup() override { |
| 106 | // Pass the image though a premul canvas so that we "forget" it is opaque. |
| 107 | auto surface = SkSurface::MakeRasterN32Premul(256, 256); |
| 108 | surface->getCanvas()->drawImage(GetResourceAsImage("images/mandrill_256.png"), 0, 0); |
| 109 | |
| 110 | fImage = surface->makeImageSnapshot(); |
| 111 | fColorFilter = fFactory(); |
| 112 | } |
| 113 | |
| 114 | void onDraw(int loops, SkCanvas* canvas) override { |
| 115 | SkPaint p; |
| 116 | p.setColorFilter(fColorFilter); |
| 117 | |
| 118 | for (int i = 0; i < loops; ++i) { |
Mike Reed | e02d7f8 | 2021-01-21 22:25:21 -0500 | [diff] [blame] | 119 | canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &p); |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 120 | } |
| 121 | } |
| 122 | |
| 123 | const Factory fFactory; |
| 124 | const SkString fName; |
| 125 | |
| 126 | sk_sp<SkImage> fImage; |
| 127 | sk_sp<SkColorFilter> fColorFilter; |
| 128 | }; |
| 129 | |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 130 | const char RuntimeNone_GPU_SRC[] = R"( |
Brian Osman | 577c606 | 2021-04-12 17:17:19 -0400 | [diff] [blame] | 131 | half4 main(half4 inColor) { return inColor; } |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 132 | )"; |
| 133 | |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 134 | const char RuntimeColorMatrix_GPU_SRC[] = R"( |
| 135 | // WTB matrix/vector inputs. |
Brian Osman | 9d10abe | 2019-12-13 16:31:40 -0500 | [diff] [blame] | 136 | uniform half m0 , m1 , m2 , m3 , m4 , |
| 137 | m5 , m6 , m7 , m8 , m9 , |
| 138 | m10, m11, m12, m13, m14, |
| 139 | m15, m16, m17, m18, m19; |
Brian Osman | 577c606 | 2021-04-12 17:17:19 -0400 | [diff] [blame] | 140 | half4 main(half4 inColor) { |
| 141 | half4 c = unpremul(inColor); |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 142 | |
| 143 | half4x4 m = half4x4(m0, m5, m10, m15, |
| 144 | m1, m6, m11, m16, |
| 145 | m2, m7, m12, m17, |
| 146 | m3, m8, m13, m18); |
| 147 | c = m * c + half4 (m4, m9, m14, m19); |
| 148 | |
Brian Osman | d5f937b | 2020-05-04 12:07:29 -0400 | [diff] [blame] | 149 | c = saturate(c); |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 150 | c.rgb *= c.a; |
Brian Osman | 767f444 | 2020-08-13 16:59:48 -0400 | [diff] [blame] | 151 | return c; |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 152 | } |
| 153 | )"; |
| 154 | |
| 155 | static constexpr float gColorMatrix[] = { |
| 156 | 0.3f, 0.3f, 0.0f, 0.0f, 0.3f, |
| 157 | 0.0f, 0.3f, 0.3f, 0.0f, 0.3f, |
| 158 | 0.0f, 0.0f, 0.3f, 0.3f, 0.3f, |
| 159 | 0.3f, 0.0f, 0.3f, 0.3f, 0.0f, |
| 160 | }; |
| 161 | |
| 162 | } // namespace |
| 163 | |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 164 | DEF_BENCH( return new ColorFilterBench("none", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 165 | []() { return sk_sp<SkColorFilter>(nullptr); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 166 | DEF_BENCH( return new ColorFilterBench("blend_src", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 167 | []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 168 | DEF_BENCH( return new ColorFilterBench("blend_srcover", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 169 | []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrcOver); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 170 | DEF_BENCH( return new ColorFilterBench("linear_to_srgb", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 171 | []() { return SkColorFilters::LinearToSRGBGamma(); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 172 | DEF_BENCH( return new ColorFilterBench("srgb_to_linear", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 173 | []() { return SkColorFilters::SRGBToLinearGamma(); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 174 | DEF_BENCH( return new ColorFilterBench("matrix_rgba", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 175 | []() { return SkColorFilters::Matrix(gColorMatrix); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 176 | DEF_BENCH( return new ColorFilterBench("matrix_hsla", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 177 | []() { return SkColorFilters::HSLAMatrix(gColorMatrix); }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 178 | DEF_BENCH( return new ColorFilterBench("compose_src", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 179 | []() { return SkColorFilters::Compose(SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc), |
| 180 | SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc)); |
| 181 | }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 182 | DEF_BENCH( return new ColorFilterBench("lerp_src", |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 183 | []() { return SkColorFilters::Lerp(0.3f, |
| 184 | SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc), |
| 185 | SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc)); |
| 186 | }); ) |
| 187 | |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 188 | DEF_BENCH( return new ColorFilterBench("highcontrast", []() { |
| 189 | return SkHighContrastFilter::Make({ |
| 190 | false, SkHighContrastConfig::InvertStyle::kInvertLightness, 0.2f |
| 191 | }); |
| 192 | }); ) |
Mike Reed | ea1d105 | 2020-03-27 12:25:44 -0400 | [diff] [blame] | 193 | DEF_BENCH( return new ColorFilterBench("overdraw", []() { |
| 194 | const SkColor colors[SkOverdrawColorFilter::kNumColors] = { |
| 195 | 0x80FF0000, 0x8000FF00, 0x800000FF, 0x80FFFF00, 0x8000FFFF, 0x80FF00FF, |
| 196 | }; |
| 197 | return SkOverdrawColorFilter::MakeWithSkColors(colors); |
| 198 | }); ) |
Mike Reed | f36b37f | 2020-03-27 15:11:10 -0400 | [diff] [blame] | 199 | DEF_BENCH( return new ColorFilterBench("gaussian", []() { |
| 200 | return SkColorFilterPriv::MakeGaussian(); |
| 201 | }); ) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 202 | |
Adlai Holler | 872a32c | 2020-07-10 14:33:22 -0400 | [diff] [blame] | 203 | #if SK_SUPPORT_GPU |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 204 | DEF_BENCH( return new ColorFilterBench("src_runtime", []() { |
John Stiles | 1f19ce2 | 2021-02-11 17:40:03 -0500 | [diff] [blame] | 205 | static sk_sp<SkRuntimeEffect> gEffect = |
Brian Osman | f6123f1 | 2021-04-15 13:52:43 -0400 | [diff] [blame] | 206 | SkRuntimeEffect::MakeForColorFilter(SkString(RuntimeNone_GPU_SRC)).effect; |
Brian Osman | 577c606 | 2021-04-12 17:17:19 -0400 | [diff] [blame] | 207 | return gEffect->makeColorFilter(SkData::MakeEmpty()); |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 208 | });) |
Mike Reed | 3e191dc | 2020-03-26 16:01:49 -0400 | [diff] [blame] | 209 | DEF_BENCH( return new ColorFilterBench("matrix_runtime", []() { |
John Stiles | 1f19ce2 | 2021-02-11 17:40:03 -0500 | [diff] [blame] | 210 | static sk_sp<SkRuntimeEffect> gEffect = |
Brian Osman | f6123f1 | 2021-04-15 13:52:43 -0400 | [diff] [blame] | 211 | SkRuntimeEffect::MakeForColorFilter(SkString(RuntimeColorMatrix_GPU_SRC)).effect; |
Brian Osman | 577c606 | 2021-04-12 17:17:19 -0400 | [diff] [blame] | 212 | return gEffect->makeColorFilter(SkData::MakeWithCopy(gColorMatrix, sizeof(gColorMatrix))); |
Florin Malita | 953efcc | 2019-10-23 16:26:58 -0400 | [diff] [blame] | 213 | });) |
| 214 | #endif |
Brian Osman | 3527389 | 2021-03-11 10:32:55 -0500 | [diff] [blame] | 215 | |
| 216 | class FilterColorBench final : public Benchmark { |
| 217 | public: |
| 218 | explicit FilterColorBench() {} |
| 219 | |
| 220 | bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } |
| 221 | |
| 222 | private: |
| 223 | const char* onGetName() override { return "matrix_filterColor4f"; } |
| 224 | |
| 225 | void onDelayedSetup() override { |
| 226 | SkScalar colorMatrix[20] = { |
| 227 | 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, |
| 228 | 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, |
| 229 | 0.9f, 0.9f, 0.9f, 0.9f, 0.9f, |
| 230 | 0.9f, 0.9f, 0.9f, 0.9f, 0.9f |
| 231 | }; |
| 232 | fColorFilter = SkColorFilters::Matrix(colorMatrix); |
| 233 | } |
| 234 | |
| 235 | void onDraw(int loops, SkCanvas*) override { |
| 236 | SkColor4f c = { 1.f, 1.f, 0.f, 1.0f }; |
| 237 | |
| 238 | for (int i = 0; i < loops; ++i) { |
| 239 | c = fColorFilter->filterColor4f(c, /*srcCS=*/nullptr, /*dstCS=*/nullptr); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | sk_sp<SkColorFilter> fColorFilter; |
| 244 | }; |
| 245 | |
| 246 | DEF_BENCH( return new FilterColorBench(); ) |