blob: 28316478b1caa0fea075ddf11fe22b098b2258c2 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
reed6c225732014-06-09 19:52:07 -07007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "bench/Benchmark.h"
9#include "include/core/SkBitmap.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColorPriv.h"
12#include "include/core/SkPaint.h"
13#include "include/core/SkString.h"
14#include "include/utils/SkRandom.h"
15#include "tools/ToolUtils.h"
reed@android.comf523e252009-01-26 23:15:37 +000016
reed@android.comf523e252009-01-26 23:15:37 +000017/* Variants for bitmaps
rmistry@google.comfbfcd562012-08-23 18:09:54 +000018
reed@android.comf523e252009-01-26 23:15:37 +000019 - src depth (32 w+w/o alpha), 565, 4444, index, a8
20 - paint options: filtering, dither, alpha
21 - matrix options: translate, scale, rotate, persp
22 - tiling: none, repeat, mirror, clamp
rmistry@google.comfbfcd562012-08-23 18:09:54 +000023
reed@android.comf523e252009-01-26 23:15:37 +000024 */
25
tfarinaf168b862014-06-19 12:32:29 -070026class BitmapBench : public Benchmark {
reed6c225732014-06-09 19:52:07 -070027 const SkColorType fColorType;
28 const SkAlphaType fAlphaType;
29 const bool fForceUpdate; //bitmap marked as dirty before each draw. forces bitmap to be updated on device cache
mtklein14e4d392014-10-23 14:35:01 -070030 const bool fDoScale;
reed6c225732014-06-09 19:52:07 -070031
32 SkBitmap fBitmap;
33 SkPaint fPaint;
34 SkString fName;
35
djsollen@google.comc2532dd2013-04-09 18:06:06 +000036 enum { W = 128 };
37 enum { H = 128 };
reed@android.comf523e252009-01-26 23:15:37 +000038public:
Mike Reed609ea212020-07-12 15:07:25 -040039 BitmapBench(SkColorType ct, SkAlphaType at, bool forceUpdate, bool doScale)
reed6c225732014-06-09 19:52:07 -070040 : fColorType(ct)
41 , fAlphaType(at)
djsollen@google.comc2532dd2013-04-09 18:06:06 +000042 , fForceUpdate(forceUpdate)
mtklein14e4d392014-10-23 14:35:01 -070043 , fDoScale(doScale)
reed6c225732014-06-09 19:52:07 -070044 {}
reed@android.comf523e252009-01-26 23:15:37 +000045
46protected:
mtkleinf0599002015-07-13 06:18:39 -070047 const char* onGetName() override {
reed@android.comf523e252009-01-26 23:15:37 +000048 fName.set("bitmap");
Mike Kleinea3f0142019-03-20 11:12:10 -050049 fName.appendf("_%s%s",
50 ToolUtils::colortype_name(fColorType),
reed6c225732014-06-09 19:52:07 -070051 kOpaque_SkAlphaType == fAlphaType ? "" : "_A");
mtklein14e4d392014-10-23 14:35:01 -070052 if (fDoScale) {
53 fName.append("_scale");
54 }
55 if (fForceUpdate) {
junov@google.com4ee7ae52011-06-30 17:30:49 +000056 fName.append("_update");
mtklein14e4d392014-10-23 14:35:01 -070057 }
junov@google.com4ee7ae52011-06-30 17:30:49 +000058
reed@android.comf523e252009-01-26 23:15:37 +000059 return fName.c_str();
60 }
61
joshualitt8a6697a2015-09-30 12:11:07 -070062 void onDelayedSetup() override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +000063 SkBitmap bm;
64
Mike Reeda920d362017-07-03 13:36:17 -040065 bm.allocPixels(SkImageInfo::Make(W, H, fColorType, fAlphaType));
reed6c225732014-06-09 19:52:07 -070066 bm.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorBLACK : 0);
djsollen@google.comc2532dd2013-04-09 18:06:06 +000067
mtkleinf0599002015-07-13 06:18:39 -070068 this->onDrawIntoBitmap(bm);
djsollen@google.comc2532dd2013-04-09 18:06:06 +000069
Mike Reeda920d362017-07-03 13:36:17 -040070 fBitmap = bm;
Mike Reeddb0b9982020-11-12 11:26:43 -050071 if (!fForceUpdate) {
72 fBitmap.setImmutable();
73 }
djsollen@google.comc2532dd2013-04-09 18:06:06 +000074 }
75
mtkleina1ebeb22015-10-01 09:43:39 -070076 void onDraw(int loops, SkCanvas* canvas) override {
mtklein14e4d392014-10-23 14:35:01 -070077 if (fDoScale) {
78 canvas->scale(.99f, .99f);
79 }
reed@android.comf523e252009-01-26 23:15:37 +000080 SkIPoint dim = this->getSize();
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000081 SkRandom rand;
reed@android.comf523e252009-01-26 23:15:37 +000082
83 SkPaint paint(fPaint);
84 this->setupPaint(&paint);
85
86 const SkBitmap& bitmap = fBitmap;
87 const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
88 const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
rmistry@google.comfbfcd562012-08-23 18:09:54 +000089
commit-bot@chromium.org33614712013-12-03 18:17:16 +000090 for (int i = 0; i < loops; i++) {
reed@android.comf523e252009-01-26 23:15:37 +000091 SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
92 SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
junov@google.com4ee7ae52011-06-30 17:30:49 +000093
94 if (fForceUpdate)
95 bitmap.notifyPixelsChanged();
96
reed@android.comf523e252009-01-26 23:15:37 +000097 canvas->drawBitmap(bitmap, x, y, &paint);
98 }
99 }
100
mtkleinf0599002015-07-13 06:18:39 -0700101 virtual void onDrawIntoBitmap(const SkBitmap& bm) {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000102 const int w = bm.width();
103 const int h = bm.height();
104
105 SkCanvas canvas(bm);
106 SkPaint p;
107 p.setAntiAlias(true);
108 p.setColor(SK_ColorRED);
109 canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
Brian Osman7f364052020-02-06 11:25:43 -0500110 SkIntToScalar(std::min(w, h))*3/8, p);
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000111
112 SkRect r;
Mike Reed92b33352019-08-24 19:39:13 -0400113 r.setWH(SkIntToScalar(w), SkIntToScalar(h));
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000114 p.setStyle(SkPaint::kStroke_Style);
115 p.setStrokeWidth(SkIntToScalar(4));
116 p.setColor(SK_ColorBLUE);
117 canvas.drawRect(r, p);
118 }
119
reed@android.comf523e252009-01-26 23:15:37 +0000120private:
John Stiles7571f9e2020-09-02 22:42:33 -0400121 using INHERITED = Benchmark;
reed@android.comf523e252009-01-26 23:15:37 +0000122};
123
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000124/** Explicitly invoke some filter types to improve coverage of acceleration
125 procs. */
126
reed@google.comef77ec22013-05-29 15:39:54 +0000127enum Flags {
128 kScale_Flag = 1 << 0,
129 kRotate_Flag = 1 << 1,
130 kBilerp_Flag = 1 << 2,
131 kBicubic_Flag = 1 << 3,
132};
133
134static bool isBilerp(uint32_t flags) {
135 return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag);
136}
137
138static bool isBicubic(uint32_t flags) {
139 return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag);
140}
141
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000142class FilterBitmapBench : public BitmapBench {
reed@google.comef77ec22013-05-29 15:39:54 +0000143 uint32_t fFlags;
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000144 SkString fFullName;
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000145public:
Mike Reed609ea212020-07-12 15:07:25 -0400146 FilterBitmapBench(SkColorType ct, SkAlphaType at, bool forceUpdate, uint32_t flags)
147 : INHERITED(ct, at, forceUpdate, false)
reed@google.comef77ec22013-05-29 15:39:54 +0000148 , fFlags(flags) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000149 }
150
151protected:
mtkleinf0599002015-07-13 06:18:39 -0700152 const char* onGetName() override {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000153 fFullName.set(INHERITED::onGetName());
reed@google.comef77ec22013-05-29 15:39:54 +0000154 if (fFlags & kScale_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000155 fFullName.append("_scale");
reed@google.comef77ec22013-05-29 15:39:54 +0000156 }
157 if (fFlags & kRotate_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000158 fFullName.append("_rotate");
reed@google.comef77ec22013-05-29 15:39:54 +0000159 }
160 if (isBilerp(fFlags)) {
161 fFullName.append("_bilerp");
162 } else if (isBicubic(fFlags)) {
163 fFullName.append("_bicubic");
164 }
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000165
166 return fFullName.c_str();
167 }
168
mtkleina1ebeb22015-10-01 09:43:39 -0700169 void onDraw(int loops, SkCanvas* canvas) override {
Mike Reed3661bc92017-02-22 13:21:42 -0500170 SkISize dim = canvas->getBaseLayerSize();
reed@google.comef77ec22013-05-29 15:39:54 +0000171 if (fFlags & kScale_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000172 const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
173 const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000174
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000175 canvas->translate(x, y);
176 // just enough so we can't take the sprite case
Mike Reed76c6ff02019-07-31 16:33:55 -0400177 canvas->scale(1.1f, 1.1f);
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000178 canvas->translate(-x, -y);
179 }
reed@google.comef77ec22013-05-29 15:39:54 +0000180 if (fFlags & kRotate_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000181 const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
182 const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
bungeman7438bfc2016-07-12 15:01:19 -0700183 canvas->rotate(SkIntToScalar(35), x, y);
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000184 }
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000185 INHERITED::onDraw(loops, canvas);
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000186 }
187
mtklein36352bf2015-03-25 18:17:31 -0700188 void setupPaint(SkPaint* paint) override {
reed@google.com9cfc83c2013-07-22 17:18:18 +0000189 this->INHERITED::setupPaint(paint);
190
191 int index = 0;
192 if (fFlags & kBilerp_Flag) {
193 index |= 1;
194 }
195 if (fFlags & kBicubic_Flag) {
196 index |= 2;
197 }
reed93a12152015-03-16 10:08:34 -0700198 static const SkFilterQuality gQualitys[] = {
199 kNone_SkFilterQuality,
200 kLow_SkFilterQuality,
201 kMedium_SkFilterQuality,
202 kHigh_SkFilterQuality
reed@google.com9cfc83c2013-07-22 17:18:18 +0000203 };
reed93a12152015-03-16 10:08:34 -0700204 paint->setFilterQuality(gQualitys[index]);
reed@google.com9cfc83c2013-07-22 17:18:18 +0000205}
206
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000207private:
John Stiles7571f9e2020-09-02 22:42:33 -0400208 using INHERITED = BitmapBench;
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000209};
210
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000211/** Verify optimizations that test source alpha values. */
212
213class SourceAlphaBitmapBench : public BitmapBench {
214public:
215 enum SourceAlpha { kOpaque_SourceAlpha, kTransparent_SourceAlpha,
216 kTwoStripes_SourceAlpha, kThreeStripes_SourceAlpha};
217private:
218 SkString fFullName;
219 SourceAlpha fSourceAlpha;
220public:
Mike Reed609ea212020-07-12 15:07:25 -0400221 SourceAlphaBitmapBench(SourceAlpha alpha, SkColorType ct, bool forceUpdate = false)
222 : INHERITED(ct, kPremul_SkAlphaType, forceUpdate, false)
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000223 , fSourceAlpha(alpha) {
224 }
225
226protected:
mtkleinf0599002015-07-13 06:18:39 -0700227 const char* onGetName() override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000228 fFullName.set(INHERITED::onGetName());
229
230 if (fSourceAlpha == kOpaque_SourceAlpha) {
231 fFullName.append("_source_opaque");
232 } else if (fSourceAlpha == kTransparent_SourceAlpha) {
233 fFullName.append("_source_transparent");
234 } else if (fSourceAlpha == kTwoStripes_SourceAlpha) {
235 fFullName.append("_source_stripes_two");
236 } else if (fSourceAlpha == kThreeStripes_SourceAlpha) {
237 fFullName.append("_source_stripes_three");
238 }
239
240 return fFullName.c_str();
241 }
242
mtklein36352bf2015-03-25 18:17:31 -0700243 void onDrawIntoBitmap(const SkBitmap& bm) override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000244 const int w = bm.width();
245 const int h = bm.height();
246
247 if (kOpaque_SourceAlpha == fSourceAlpha) {
248 bm.eraseColor(SK_ColorBLACK);
249 } else if (kTransparent_SourceAlpha == fSourceAlpha) {
250 bm.eraseColor(0);
251 } else if (kTwoStripes_SourceAlpha == fSourceAlpha) {
252 bm.eraseColor(0);
253
254 SkCanvas canvas(bm);
255 SkPaint p;
256 p.setAntiAlias(false);
257 p.setStyle(SkPaint::kFill_Style);
258 p.setColor(SK_ColorRED);
259
260 // Draw red vertical stripes on transparent background
261 SkRect r;
262 for (int x = 0; x < w; x+=2)
263 {
Mike Reed92b33352019-08-24 19:39:13 -0400264 r.setLTRB(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000265 canvas.drawRect(r, p);
266 }
267
268 } else if (kThreeStripes_SourceAlpha == fSourceAlpha) {
269 bm.eraseColor(0);
270
271 SkCanvas canvas(bm);
272 SkPaint p;
273 p.setAntiAlias(false);
274 p.setStyle(SkPaint::kFill_Style);
275
276 // Draw vertical stripes on transparent background with a pattern
277 // where the first pixel is fully transparent, the next is semi-transparent
278 // and the third is fully opaque.
279 SkRect r;
280 for (int x = 0; x < w; x++)
281 {
282 if (x % 3 == 0) {
283 continue; // Keep transparent
284 } else if (x % 3 == 1) {
285 p.setColor(SkColorSetARGB(127, 127, 127, 127)); // Semi-transparent
286 } else if (x % 3 == 2) {
287 p.setColor(SK_ColorRED); // Opaque
288 }
Mike Reed92b33352019-08-24 19:39:13 -0400289 r.setLTRB(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000290 canvas.drawRect(r, p);
291 }
292 }
293 }
294
295private:
John Stiles7571f9e2020-09-02 22:42:33 -0400296 using INHERITED = BitmapBench;
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000297};
reed@google.com2ece2872013-05-28 20:48:14 +0000298
Mike Reed609ea212020-07-12 15:07:25 -0400299DEF_BENCH( return new BitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false); )
300DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false); )
301DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, true); )
302DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false); )
303DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false); )
304DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false); )
reed@android.comf523e252009-01-26 23:15:37 +0000305
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000306// scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2
Mike Reed609ea212020-07-12 15:07:25 -0400307DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, kScale_Flag | kBilerp_Flag); )
308DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, kScale_Flag | kBilerp_Flag); )
309DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, kScale_Flag | kBilerp_Flag); )
310DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, kScale_Flag | kBilerp_Flag); )
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000311
Yuqian Li24e963d2017-12-06 11:30:58 -0500312// The following two cases test the performance regression of b/70172912 .
Mike Reed609ea212020-07-12 15:07:25 -0400313DEF_BENCH( return new FilterBitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, kScale_Flag | kBilerp_Flag); )
314DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, true); )
Yuqian Li24e963d2017-12-06 11:30:58 -0500315
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000316// scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3}
Mike Reed609ea212020-07-12 15:07:25 -0400317DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
318DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
319DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
320DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
reed@google.comef77ec22013-05-29 15:39:54 +0000321
Mike Reed609ea212020-07-12 15:07:25 -0400322DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); )
323DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); )
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000324
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000325// source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon}
reed6c225732014-06-09 19:52:07 -0700326DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kOpaque_SourceAlpha, kN32_SkColorType); )
327DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTransparent_SourceAlpha, kN32_SkColorType); )
328DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTwoStripes_SourceAlpha, kN32_SkColorType); )
329DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kThreeStripes_SourceAlpha, kN32_SkColorType); )