blob: cc6f325f1ebc830aa481f81841515d6f7d1901d8 [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
tfarinaf168b862014-06-19 12:32:29 -07008#include "Benchmark.h"
reed@android.comf523e252009-01-26 23:15:37 +00009#include "SkBitmap.h"
reed@android.comf523e252009-01-26 23:15:37 +000010#include "SkCanvas.h"
11#include "SkColorPriv.h"
tfarinaf168b862014-06-19 12:32:29 -070012#include "SkPaint.h"
reed@android.comf523e252009-01-26 23:15:37 +000013#include "SkRandom.h"
14#include "SkString.h"
reed6c225732014-06-09 19:52:07 -070015#include "sk_tool_utils.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
30 const bool fIsVolatile;
mtklein14e4d392014-10-23 14:35:01 -070031 const bool fDoScale;
reed6c225732014-06-09 19:52:07 -070032
33 SkBitmap fBitmap;
34 SkPaint fPaint;
35 SkString fName;
36
djsollen@google.comc2532dd2013-04-09 18:06:06 +000037 enum { W = 128 };
38 enum { H = 128 };
reed@android.comf523e252009-01-26 23:15:37 +000039public:
mtklein14e4d392014-10-23 14:35:01 -070040 BitmapBench(SkColorType ct, SkAlphaType at, bool forceUpdate, bool isVolatile, bool doScale)
reed6c225732014-06-09 19:52:07 -070041 : fColorType(ct)
42 , fAlphaType(at)
djsollen@google.comc2532dd2013-04-09 18:06:06 +000043 , fForceUpdate(forceUpdate)
reed6c225732014-06-09 19:52:07 -070044 , fIsVolatile(isVolatile)
mtklein14e4d392014-10-23 14:35:01 -070045 , fDoScale(doScale)
reed6c225732014-06-09 19:52:07 -070046 {}
reed@android.comf523e252009-01-26 23:15:37 +000047
48protected:
mtkleinf0599002015-07-13 06:18:39 -070049 const char* onGetName() override {
reed@android.comf523e252009-01-26 23:15:37 +000050 fName.set("bitmap");
reed6c225732014-06-09 19:52:07 -070051 fName.appendf("_%s%s", sk_tool_utils::colortype_name(fColorType),
52 kOpaque_SkAlphaType == fAlphaType ? "" : "_A");
mtklein14e4d392014-10-23 14:35:01 -070053 if (fDoScale) {
54 fName.append("_scale");
55 }
56 if (fForceUpdate) {
junov@google.com4ee7ae52011-06-30 17:30:49 +000057 fName.append("_update");
mtklein14e4d392014-10-23 14:35:01 -070058 }
59 if (fIsVolatile) {
junov@google.com4ee7ae52011-06-30 17:30:49 +000060 fName.append("_volatile");
mtklein14e4d392014-10-23 14:35:01 -070061 }
junov@google.com4ee7ae52011-06-30 17:30:49 +000062
reed@android.comf523e252009-01-26 23:15:37 +000063 return fName.c_str();
64 }
65
joshualitt8a6697a2015-09-30 12:11:07 -070066 void onDelayedSetup() override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +000067 SkBitmap bm;
68
Mike Reeda920d362017-07-03 13:36:17 -040069 bm.allocPixels(SkImageInfo::Make(W, H, fColorType, fAlphaType));
reed6c225732014-06-09 19:52:07 -070070 bm.eraseColor(kOpaque_SkAlphaType == fAlphaType ? SK_ColorBLACK : 0);
djsollen@google.comc2532dd2013-04-09 18:06:06 +000071
mtkleinf0599002015-07-13 06:18:39 -070072 this->onDrawIntoBitmap(bm);
djsollen@google.comc2532dd2013-04-09 18:06:06 +000073
Mike Reeda920d362017-07-03 13:36:17 -040074 fBitmap = bm;
djsollen@google.comc2532dd2013-04-09 18:06:06 +000075 fBitmap.setIsVolatile(fIsVolatile);
76 }
77
mtkleina1ebeb22015-10-01 09:43:39 -070078 void onDraw(int loops, SkCanvas* canvas) override {
mtklein14e4d392014-10-23 14:35:01 -070079 if (fDoScale) {
80 canvas->scale(.99f, .99f);
81 }
reed@android.comf523e252009-01-26 23:15:37 +000082 SkIPoint dim = this->getSize();
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000083 SkRandom rand;
reed@android.comf523e252009-01-26 23:15:37 +000084
85 SkPaint paint(fPaint);
86 this->setupPaint(&paint);
87
88 const SkBitmap& bitmap = fBitmap;
89 const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
90 const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
rmistry@google.comfbfcd562012-08-23 18:09:54 +000091
commit-bot@chromium.org33614712013-12-03 18:17:16 +000092 for (int i = 0; i < loops; i++) {
reed@android.comf523e252009-01-26 23:15:37 +000093 SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
94 SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
junov@google.com4ee7ae52011-06-30 17:30:49 +000095
96 if (fForceUpdate)
97 bitmap.notifyPixelsChanged();
98
reed@android.comf523e252009-01-26 23:15:37 +000099 canvas->drawBitmap(bitmap, x, y, &paint);
100 }
101 }
102
mtkleinf0599002015-07-13 06:18:39 -0700103 virtual void onDrawIntoBitmap(const SkBitmap& bm) {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000104 const int w = bm.width();
105 const int h = bm.height();
106
107 SkCanvas canvas(bm);
108 SkPaint p;
109 p.setAntiAlias(true);
110 p.setColor(SK_ColorRED);
111 canvas.drawCircle(SkIntToScalar(w)/2, SkIntToScalar(h)/2,
112 SkIntToScalar(SkMin32(w, h))*3/8, p);
113
114 SkRect r;
115 r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
116 p.setStyle(SkPaint::kStroke_Style);
117 p.setStrokeWidth(SkIntToScalar(4));
118 p.setColor(SK_ColorBLUE);
119 canvas.drawRect(r, p);
120 }
121
reed@android.comf523e252009-01-26 23:15:37 +0000122private:
tfarinaf168b862014-06-19 12:32:29 -0700123 typedef Benchmark INHERITED;
reed@android.comf523e252009-01-26 23:15:37 +0000124};
125
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000126/** Explicitly invoke some filter types to improve coverage of acceleration
127 procs. */
128
reed@google.comef77ec22013-05-29 15:39:54 +0000129enum Flags {
130 kScale_Flag = 1 << 0,
131 kRotate_Flag = 1 << 1,
132 kBilerp_Flag = 1 << 2,
133 kBicubic_Flag = 1 << 3,
134};
135
136static bool isBilerp(uint32_t flags) {
137 return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag);
138}
139
140static bool isBicubic(uint32_t flags) {
141 return (flags & (kBilerp_Flag | kBicubic_Flag)) == (kBilerp_Flag | kBicubic_Flag);
142}
143
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000144class FilterBitmapBench : public BitmapBench {
reed@google.comef77ec22013-05-29 15:39:54 +0000145 uint32_t fFlags;
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000146 SkString fFullName;
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000147public:
reed6c225732014-06-09 19:52:07 -0700148 FilterBitmapBench(SkColorType ct, SkAlphaType at,
reed@google.comef77ec22013-05-29 15:39:54 +0000149 bool forceUpdate, bool isVolitile, uint32_t flags)
mtklein14e4d392014-10-23 14:35:01 -0700150 : INHERITED(ct, at, forceUpdate, isVolitile, false)
reed@google.comef77ec22013-05-29 15:39:54 +0000151 , fFlags(flags) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000152 }
153
154protected:
mtkleinf0599002015-07-13 06:18:39 -0700155 const char* onGetName() override {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000156 fFullName.set(INHERITED::onGetName());
reed@google.comef77ec22013-05-29 15:39:54 +0000157 if (fFlags & kScale_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000158 fFullName.append("_scale");
reed@google.comef77ec22013-05-29 15:39:54 +0000159 }
160 if (fFlags & kRotate_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000161 fFullName.append("_rotate");
reed@google.comef77ec22013-05-29 15:39:54 +0000162 }
163 if (isBilerp(fFlags)) {
164 fFullName.append("_bilerp");
165 } else if (isBicubic(fFlags)) {
166 fFullName.append("_bicubic");
167 }
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000168
169 return fFullName.c_str();
170 }
171
mtkleina1ebeb22015-10-01 09:43:39 -0700172 void onDraw(int loops, SkCanvas* canvas) override {
Mike Reed3661bc92017-02-22 13:21:42 -0500173 SkISize dim = canvas->getBaseLayerSize();
reed@google.comef77ec22013-05-29 15:39:54 +0000174 if (fFlags & kScale_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000175 const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
176 const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000177
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000178 canvas->translate(x, y);
179 // just enough so we can't take the sprite case
180 canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
181 canvas->translate(-x, -y);
182 }
reed@google.comef77ec22013-05-29 15:39:54 +0000183 if (fFlags & kRotate_Flag) {
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000184 const SkScalar x = SkIntToScalar(dim.fWidth) / 2;
185 const SkScalar y = SkIntToScalar(dim.fHeight) / 2;
bungeman7438bfc2016-07-12 15:01:19 -0700186 canvas->rotate(SkIntToScalar(35), x, y);
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000187 }
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000188 INHERITED::onDraw(loops, canvas);
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000189 }
190
mtklein36352bf2015-03-25 18:17:31 -0700191 void setupPaint(SkPaint* paint) override {
reed@google.com9cfc83c2013-07-22 17:18:18 +0000192 this->INHERITED::setupPaint(paint);
193
194 int index = 0;
195 if (fFlags & kBilerp_Flag) {
196 index |= 1;
197 }
198 if (fFlags & kBicubic_Flag) {
199 index |= 2;
200 }
reed93a12152015-03-16 10:08:34 -0700201 static const SkFilterQuality gQualitys[] = {
202 kNone_SkFilterQuality,
203 kLow_SkFilterQuality,
204 kMedium_SkFilterQuality,
205 kHigh_SkFilterQuality
reed@google.com9cfc83c2013-07-22 17:18:18 +0000206 };
reed93a12152015-03-16 10:08:34 -0700207 paint->setFilterQuality(gQualitys[index]);
reed@google.com9cfc83c2013-07-22 17:18:18 +0000208}
209
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000210private:
211 typedef BitmapBench INHERITED;
212};
213
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000214/** Verify optimizations that test source alpha values. */
215
216class SourceAlphaBitmapBench : public BitmapBench {
217public:
218 enum SourceAlpha { kOpaque_SourceAlpha, kTransparent_SourceAlpha,
219 kTwoStripes_SourceAlpha, kThreeStripes_SourceAlpha};
220private:
221 SkString fFullName;
222 SourceAlpha fSourceAlpha;
223public:
reed6c225732014-06-09 19:52:07 -0700224 SourceAlphaBitmapBench(SourceAlpha alpha, SkColorType ct,
reed@google.comef77ec22013-05-29 15:39:54 +0000225 bool forceUpdate = false, bool bitmapVolatile = false)
mtklein14e4d392014-10-23 14:35:01 -0700226 : INHERITED(ct, kPremul_SkAlphaType, forceUpdate, bitmapVolatile, false)
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000227 , fSourceAlpha(alpha) {
228 }
229
230protected:
mtkleinf0599002015-07-13 06:18:39 -0700231 const char* onGetName() override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000232 fFullName.set(INHERITED::onGetName());
233
234 if (fSourceAlpha == kOpaque_SourceAlpha) {
235 fFullName.append("_source_opaque");
236 } else if (fSourceAlpha == kTransparent_SourceAlpha) {
237 fFullName.append("_source_transparent");
238 } else if (fSourceAlpha == kTwoStripes_SourceAlpha) {
239 fFullName.append("_source_stripes_two");
240 } else if (fSourceAlpha == kThreeStripes_SourceAlpha) {
241 fFullName.append("_source_stripes_three");
242 }
243
244 return fFullName.c_str();
245 }
246
mtklein36352bf2015-03-25 18:17:31 -0700247 void onDrawIntoBitmap(const SkBitmap& bm) override {
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000248 const int w = bm.width();
249 const int h = bm.height();
250
251 if (kOpaque_SourceAlpha == fSourceAlpha) {
252 bm.eraseColor(SK_ColorBLACK);
253 } else if (kTransparent_SourceAlpha == fSourceAlpha) {
254 bm.eraseColor(0);
255 } else if (kTwoStripes_SourceAlpha == fSourceAlpha) {
256 bm.eraseColor(0);
257
258 SkCanvas canvas(bm);
259 SkPaint p;
260 p.setAntiAlias(false);
261 p.setStyle(SkPaint::kFill_Style);
262 p.setColor(SK_ColorRED);
263
264 // Draw red vertical stripes on transparent background
265 SkRect r;
266 for (int x = 0; x < w; x+=2)
267 {
268 r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
269 canvas.drawRect(r, p);
270 }
271
272 } else if (kThreeStripes_SourceAlpha == fSourceAlpha) {
273 bm.eraseColor(0);
274
275 SkCanvas canvas(bm);
276 SkPaint p;
277 p.setAntiAlias(false);
278 p.setStyle(SkPaint::kFill_Style);
279
280 // Draw vertical stripes on transparent background with a pattern
281 // where the first pixel is fully transparent, the next is semi-transparent
282 // and the third is fully opaque.
283 SkRect r;
284 for (int x = 0; x < w; x++)
285 {
286 if (x % 3 == 0) {
287 continue; // Keep transparent
288 } else if (x % 3 == 1) {
289 p.setColor(SkColorSetARGB(127, 127, 127, 127)); // Semi-transparent
290 } else if (x % 3 == 2) {
291 p.setColor(SK_ColorRED); // Opaque
292 }
293 r.set(SkIntToScalar(x), 0, SkIntToScalar(x+1), SkIntToScalar(h));
294 canvas.drawRect(r, p);
295 }
296 }
297 }
298
299private:
300 typedef BitmapBench INHERITED;
301};
reed@google.com2ece2872013-05-28 20:48:14 +0000302
mtklein14e4d392014-10-23 14:35:01 -0700303DEF_BENCH( return new BitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, false); )
304DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, false); )
305DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, true); )
306DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, false); )
mtklein14e4d392014-10-23 14:35:01 -0700307DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, false); )
308DEF_BENCH( return new BitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, false); )
reed@android.comf523e252009-01-26 23:15:37 +0000309
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000310// scale filter -> S32_opaque_D32_filter_DX_{SSE2,SSSE3} and Fact9 is also for S32_D16_filter_DX_SSE2
reed6c225732014-06-09 19:52:07 -0700311DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
312DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
313DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kBilerp_Flag); )
314DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kBilerp_Flag); )
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000315
Yuqian Li24e963d2017-12-06 11:30:58 -0500316// The following two cases test the performance regression of b/70172912 .
317DEF_BENCH( return new FilterBitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag); )
318DEF_BENCH( return new BitmapBench(kRGB_565_SkColorType, kOpaque_SkAlphaType, false, false, true); )
319
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000320// scale rotate filter -> S32_opaque_D32_filter_DXDY_{SSE2,SSSE3}
reed6c225732014-06-09 19:52:07 -0700321DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
322DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
323DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, true, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
324DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kOpaque_SkAlphaType, true, false, kScale_Flag | kRotate_Flag | kBilerp_Flag); )
reed@google.comef77ec22013-05-29 15:39:54 +0000325
reed6c225732014-06-09 19:52:07 -0700326DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kBilerp_Flag | kBicubic_Flag); )
327DEF_BENCH( return new FilterBitmapBench(kN32_SkColorType, kPremul_SkAlphaType, false, false, kScale_Flag | kRotate_Flag | kBilerp_Flag | kBicubic_Flag); )
tomhudson@google.comc3be34d2012-05-15 20:09:33 +0000328
djsollen@google.comc2532dd2013-04-09 18:06:06 +0000329// source alpha tests -> S32A_Opaque_BlitRow32_{arm,neon}
reed6c225732014-06-09 19:52:07 -0700330DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kOpaque_SourceAlpha, kN32_SkColorType); )
331DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTransparent_SourceAlpha, kN32_SkColorType); )
332DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kTwoStripes_SourceAlpha, kN32_SkColorType); )
333DEF_BENCH( return new SourceAlphaBitmapBench(SourceAlphaBitmapBench::kThreeStripes_SourceAlpha, kN32_SkColorType); )