blob: 59701a99bbef36407cf91652a2d6389e1f52f340 [file] [log] [blame]
sugoi@google.com580a1722013-04-23 14:20:45 +00001/*
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 */
reedaa4c7a72015-04-02 20:31:17 -07007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "bench/Benchmark.h"
9#include "include/core/SkCanvas.h"
Michael Ludwig23003182019-08-05 11:25:23 -040010#include "include/core/SkColorFilter.h"
Florin Malita953efcc2019-10-23 16:26:58 -040011#include "include/core/SkSurface.h"
Mike Reed3e191dc2020-03-26 16:01:49 -040012#include "include/effects/SkHighContrastFilter.h"
Michael Ludwig23003182019-08-05 11:25:23 -040013#include "include/effects/SkImageFilters.h"
Mike Reedea1d1052020-03-27 12:25:44 -040014#include "include/effects/SkOverdrawColorFilter.h"
Brian Osmanee426f22020-01-02 11:55:24 -050015#include "include/effects/SkRuntimeEffect.h"
Mike Reedf36b37f2020-03-27 15:11:10 -040016#include "src/core/SkColorFilterPriv.h"
Florin Malita953efcc2019-10-23 16:26:58 -040017#include "tools/Resources.h"
sugoi@google.com580a1722013-04-23 14:20:45 +000018
Mike Reedd93ee532019-05-20 12:30:37 -040019// Just need an interesting filter, nothing to special about colormatrix
20static sk_sp<SkColorFilter> make_grayscale() {
Mike Reede869a1e2019-04-30 12:18:54 -040021 float matrix[20];
22 memset(matrix, 0, 20 * sizeof(float));
robertphillips5605b562016-04-05 11:50:42 -070023 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 Reedd93ee532019-05-20 12:30:37 -040027 return SkColorFilters::Matrix(matrix);
robertphillips5605b562016-04-05 11:50:42 -070028}
29
Mike Reedd93ee532019-05-20 12:30:37 -040030/**
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 */
35class FilteredRectBench : public Benchmark {
sugoi@google.com580a1722013-04-23 14:20:45 +000036public:
Mike Reedd93ee532019-05-20 12:30:37 -040037 enum Type {
38 kNoFilter_Type,
39 kColorFilter_Type,
40 kImageFilter_Type,
41 };
sugoi@google.com580a1722013-04-23 14:20:45 +000042
Mike Reedd93ee532019-05-20 12:30:37 -040043 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.com580a1722013-04-23 14:20:45 +000047 }
48
Mike Reedd93ee532019-05-20 12:30:37 -040049protected:
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 Ludwig23003182019-08-05 11:25:23 -040062 fPaint.setImageFilter(SkImageFilters::ColorFilter(make_grayscale(), nullptr));
Mike Reedd93ee532019-05-20 12:30:37 -040063 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 }
reedaa4c7a72015-04-02 20:31:17 -070073
sugoi@google.com580a1722013-04-23 14:20:45 +000074private:
Mike Reedd93ee532019-05-20 12:30:37 -040075 SkPaint fPaint;
76 SkString fName;
77 Type fType;
sugoi@google.com580a1722013-04-23 14:20:45 +000078
John Stiles7571f9e2020-09-02 22:42:33 -040079 using INHERITED = Benchmark;
sugoi@google.com580a1722013-04-23 14:20:45 +000080};
81
Mike Reedd93ee532019-05-20 12:30:37 -040082DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kNoFilter_Type); )
83DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kColorFilter_Type); )
84DEF_BENCH( return new FilteredRectBench(FilteredRectBench::kImageFilter_Type); )
Florin Malita953efcc2019-10-23 16:26:58 -040085
86namespace {
87
Mike Reed3e191dc2020-03-26 16:01:49 -040088class ColorFilterBench final : public Benchmark {
Florin Malita953efcc2019-10-23 16:26:58 -040089public:
90 using Factory = sk_sp<SkColorFilter>(*)();
91
Mike Reed3e191dc2020-03-26 16:01:49 -040092 explicit ColorFilterBench(const char* suffix, Factory f)
Florin Malita953efcc2019-10-23 16:26:58 -040093 : fFactory(f)
94 , fName(SkStringPrintf("colorfilter_%s", suffix)) {}
95
96private:
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 Reede02d7f82021-01-21 22:25:21 -0500119 canvas->drawImage(fImage, 0, 0, SkSamplingOptions(), &p);
Florin Malita953efcc2019-10-23 16:26:58 -0400120 }
121 }
122
123 const Factory fFactory;
124 const SkString fName;
125
126 sk_sp<SkImage> fImage;
127 sk_sp<SkColorFilter> fColorFilter;
128};
129
Florin Malita953efcc2019-10-23 16:26:58 -0400130const char RuntimeNone_GPU_SRC[] = R"(
Brian Osman577c6062021-04-12 17:17:19 -0400131 half4 main(half4 inColor) { return inColor; }
Florin Malita953efcc2019-10-23 16:26:58 -0400132)";
133
Florin Malita953efcc2019-10-23 16:26:58 -0400134const char RuntimeColorMatrix_GPU_SRC[] = R"(
135 // WTB matrix/vector inputs.
Brian Osman9d10abe2019-12-13 16:31:40 -0500136 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 Osman577c6062021-04-12 17:17:19 -0400140 half4 main(half4 inColor) {
141 half4 c = unpremul(inColor);
Florin Malita953efcc2019-10-23 16:26:58 -0400142
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 Osmand5f937b2020-05-04 12:07:29 -0400149 c = saturate(c);
Florin Malita953efcc2019-10-23 16:26:58 -0400150 c.rgb *= c.a;
Brian Osman767f4442020-08-13 16:59:48 -0400151 return c;
Florin Malita953efcc2019-10-23 16:26:58 -0400152 }
153)";
154
155static 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 Reed3e191dc2020-03-26 16:01:49 -0400164DEF_BENCH( return new ColorFilterBench("none",
Florin Malita953efcc2019-10-23 16:26:58 -0400165 []() { return sk_sp<SkColorFilter>(nullptr); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400166DEF_BENCH( return new ColorFilterBench("blend_src",
Florin Malita953efcc2019-10-23 16:26:58 -0400167 []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400168DEF_BENCH( return new ColorFilterBench("blend_srcover",
Florin Malita953efcc2019-10-23 16:26:58 -0400169 []() { return SkColorFilters::Blend(0x80808080, SkBlendMode::kSrcOver); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400170DEF_BENCH( return new ColorFilterBench("linear_to_srgb",
Florin Malita953efcc2019-10-23 16:26:58 -0400171 []() { return SkColorFilters::LinearToSRGBGamma(); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400172DEF_BENCH( return new ColorFilterBench("srgb_to_linear",
Florin Malita953efcc2019-10-23 16:26:58 -0400173 []() { return SkColorFilters::SRGBToLinearGamma(); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400174DEF_BENCH( return new ColorFilterBench("matrix_rgba",
Florin Malita953efcc2019-10-23 16:26:58 -0400175 []() { return SkColorFilters::Matrix(gColorMatrix); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400176DEF_BENCH( return new ColorFilterBench("matrix_hsla",
Florin Malita953efcc2019-10-23 16:26:58 -0400177 []() { return SkColorFilters::HSLAMatrix(gColorMatrix); }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400178DEF_BENCH( return new ColorFilterBench("compose_src",
Florin Malita953efcc2019-10-23 16:26:58 -0400179 []() { return SkColorFilters::Compose(SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc),
180 SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc));
181 }); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400182DEF_BENCH( return new ColorFilterBench("lerp_src",
Florin Malita953efcc2019-10-23 16:26:58 -0400183 []() { return SkColorFilters::Lerp(0.3f,
184 SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc),
185 SkColorFilters::Blend(0x80808080, SkBlendMode::kSrc));
186 }); )
187
Mike Reed3e191dc2020-03-26 16:01:49 -0400188DEF_BENCH( return new ColorFilterBench("highcontrast", []() {
189 return SkHighContrastFilter::Make({
190 false, SkHighContrastConfig::InvertStyle::kInvertLightness, 0.2f
191 });
192}); )
Mike Reedea1d1052020-03-27 12:25:44 -0400193DEF_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 Reedf36b37f2020-03-27 15:11:10 -0400199DEF_BENCH( return new ColorFilterBench("gaussian", []() {
200 return SkColorFilterPriv::MakeGaussian();
201}); )
Mike Reed3e191dc2020-03-26 16:01:49 -0400202
Adlai Holler872a32c2020-07-10 14:33:22 -0400203#if SK_SUPPORT_GPU
Mike Reed3e191dc2020-03-26 16:01:49 -0400204DEF_BENCH( return new ColorFilterBench("src_runtime", []() {
John Stiles1f19ce22021-02-11 17:40:03 -0500205 static sk_sp<SkRuntimeEffect> gEffect =
Brian Osmanf6123f12021-04-15 13:52:43 -0400206 SkRuntimeEffect::MakeForColorFilter(SkString(RuntimeNone_GPU_SRC)).effect;
Brian Osman577c6062021-04-12 17:17:19 -0400207 return gEffect->makeColorFilter(SkData::MakeEmpty());
Florin Malita953efcc2019-10-23 16:26:58 -0400208 });)
Mike Reed3e191dc2020-03-26 16:01:49 -0400209DEF_BENCH( return new ColorFilterBench("matrix_runtime", []() {
John Stiles1f19ce22021-02-11 17:40:03 -0500210 static sk_sp<SkRuntimeEffect> gEffect =
Brian Osmanf6123f12021-04-15 13:52:43 -0400211 SkRuntimeEffect::MakeForColorFilter(SkString(RuntimeColorMatrix_GPU_SRC)).effect;
Brian Osman577c6062021-04-12 17:17:19 -0400212 return gEffect->makeColorFilter(SkData::MakeWithCopy(gColorMatrix, sizeof(gColorMatrix)));
Florin Malita953efcc2019-10-23 16:26:58 -0400213 });)
214#endif
Brian Osman35273892021-03-11 10:32:55 -0500215
216class FilterColorBench final : public Benchmark {
217public:
218 explicit FilterColorBench() {}
219
220 bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
221
222private:
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
246DEF_BENCH( return new FilterColorBench(); )