blob: 07683ead7e572474c197849080b1ae0557650256 [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 */
Mike Kleinc0bd9f92019-04-23 12:05:21 -05007#include "bench/Benchmark.h"
8#include "include/core/SkMatrix.h"
9#include "include/core/SkString.h"
10#include "include/utils/SkRandom.h"
11#include "src/core/SkMatrixUtils.h"
reed@google.com3fb51872011-06-01 15:11:22 +000012
tfarinaf168b862014-06-19 12:32:29 -070013class MatrixBench : public Benchmark {
reed@google.com3fb51872011-06-01 15:11:22 +000014 SkString fName;
reed@google.com3fb51872011-06-01 15:11:22 +000015public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000016 MatrixBench(const char name[]) {
reed@google.com3fb51872011-06-01 15:11:22 +000017 fName.printf("matrix_%s", name);
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000018 }
19
mtklein36352bf2015-03-25 18:17:31 -070020 bool isSuitableFor(Backend backend) override {
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000021 return backend == kNonRendering_Backend;
reed@google.com3fb51872011-06-01 15:11:22 +000022 }
23
24 virtual void performTest() = 0;
25
26protected:
reed@google.comcbefd7d2011-06-06 13:31:30 +000027 virtual int mulLoopCount() const { return 1; }
28
mtkleinf0599002015-07-13 06:18:39 -070029 const char* onGetName() override {
reed@google.com3fb51872011-06-01 15:11:22 +000030 return fName.c_str();
31 }
32
mtkleina1ebeb22015-10-01 09:43:39 -070033 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +000034 for (int i = 0; i < loops; i++) {
reed@google.com3fb51872011-06-01 15:11:22 +000035 this->performTest();
36 }
37 }
38
39private:
John Stiles7571f9e2020-09-02 22:42:33 -040040 using INHERITED = Benchmark;
reed@google.com3fb51872011-06-01 15:11:22 +000041};
42
reed@google.com3fb51872011-06-01 15:11:22 +000043
44class EqualsMatrixBench : public MatrixBench {
45public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000046 EqualsMatrixBench() : INHERITED("equals") {}
reed@google.com3fb51872011-06-01 15:11:22 +000047protected:
mtkleinf0599002015-07-13 06:18:39 -070048 void performTest() override {
reed@google.com3fb51872011-06-01 15:11:22 +000049 SkMatrix m0, m1, m2;
tomhudson@google.com7b4e1072011-06-03 19:16:56 +000050
reed@google.com3fb51872011-06-01 15:11:22 +000051 m0.reset();
52 m1.reset();
53 m2.reset();
mtkleincf44feb2014-06-02 18:22:12 -070054
55 // xor into a volatile prevents these comparisons from being optimized away.
Brian Salomon54fd96b2021-08-05 12:16:07 -040056 SK_MAYBE_UNUSED volatile bool junk = false;
mtkleincf44feb2014-06-02 18:22:12 -070057 junk ^= (m0 == m1);
58 junk ^= (m1 == m2);
59 junk ^= (m2 == m0);
reed@google.com3fb51872011-06-01 15:11:22 +000060 }
61private:
John Stiles7571f9e2020-09-02 22:42:33 -040062 using INHERITED = MatrixBench;
reed@google.com3fb51872011-06-01 15:11:22 +000063};
64
65class ScaleMatrixBench : public MatrixBench {
66public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000067 ScaleMatrixBench() : INHERITED("scale") {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000068 fSX = fSY = 1.5f;
reed@google.com3fb51872011-06-01 15:11:22 +000069 fM0.reset();
70 fM1.setScale(fSX, fSY);
71 fM2.setTranslate(fSX, fSY);
reed@google.com3fb51872011-06-01 15:11:22 +000072 }
73protected:
mtkleinf0599002015-07-13 06:18:39 -070074 void performTest() override {
reed@google.com3fb51872011-06-01 15:11:22 +000075 SkMatrix m;
76 m = fM0; m.preScale(fSX, fSY);
77 m = fM1; m.preScale(fSX, fSY);
78 m = fM2; m.preScale(fSX, fSY);
79 }
80private:
81 SkMatrix fM0, fM1, fM2;
82 SkScalar fSX, fSY;
John Stiles7571f9e2020-09-02 22:42:33 -040083 using INHERITED = MatrixBench;
reed@google.com3fb51872011-06-01 15:11:22 +000084};
85
reed@google.come0dcde72011-06-06 13:20:29 +000086// having unknown values in our arrays can throw off the timing a lot, perhaps
Leon Scroggins IIIa4c80982020-07-28 10:20:58 -040087// handling NaN values is a lot slower. Anyway, this is just meant to put
reed@google.come0dcde72011-06-06 13:20:29 +000088// reasonable values in our arrays.
89template <typename T> void init9(T array[9]) {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000090 SkRandom rand;
reed@google.come0dcde72011-06-06 13:20:29 +000091 for (int i = 0; i < 9; i++) {
92 array[i] = rand.nextSScalar1();
93 }
94}
95
tomhudson@google.com317d5402011-06-24 18:30:49 +000096class GetTypeMatrixBench : public MatrixBench {
97public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000098 GetTypeMatrixBench()
99 : INHERITED("gettype") {
bsalomon@google.com820e80a2011-10-24 21:09:40 +0000100 fArray[0] = (float) fRnd.nextS();
101 fArray[1] = (float) fRnd.nextS();
102 fArray[2] = (float) fRnd.nextS();
103 fArray[3] = (float) fRnd.nextS();
104 fArray[4] = (float) fRnd.nextS();
105 fArray[5] = (float) fRnd.nextS();
106 fArray[6] = (float) fRnd.nextS();
107 fArray[7] = (float) fRnd.nextS();
108 fArray[8] = (float) fRnd.nextS();
tomhudson@google.com317d5402011-06-24 18:30:49 +0000109 }
110protected:
111 // Putting random generation of the matrix inside performTest()
112 // would help us avoid anomalous runs, but takes up 25% or
113 // more of the function time.
mtkleinf0599002015-07-13 06:18:39 -0700114 void performTest() override {
tomhudson@google.com317d5402011-06-24 18:30:49 +0000115 fMatrix.setAll(fArray[0], fArray[1], fArray[2],
116 fArray[3], fArray[4], fArray[5],
117 fArray[6], fArray[7], fArray[8]);
mtkleincf44feb2014-06-02 18:22:12 -0700118 // xoring into a volatile prevents the compiler from optimizing these away
Brian Salomon54fd96b2021-08-05 12:16:07 -0400119 SK_MAYBE_UNUSED volatile int junk = 0;
mtkleincf44feb2014-06-02 18:22:12 -0700120 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000121 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700122 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000123 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700124 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000125 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700126 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000127 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700128 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000129 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700130 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000131 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700132 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000133 fMatrix.dirtyMatrixTypeCache();
mtkleincf44feb2014-06-02 18:22:12 -0700134 junk ^= (fMatrix.getType());
tomhudson@google.com317d5402011-06-24 18:30:49 +0000135 }
136private:
137 SkMatrix fMatrix;
138 float fArray[9];
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000139 SkRandom fRnd;
John Stiles7571f9e2020-09-02 22:42:33 -0400140 using INHERITED = MatrixBench;
tomhudson@google.com317d5402011-06-24 18:30:49 +0000141};
142
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000143class DecomposeMatrixBench : public MatrixBench {
144public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000145 DecomposeMatrixBench() : INHERITED("decompose") {}
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000146
147protected:
joshualitt8a6697a2015-09-30 12:11:07 -0700148 void onDelayedSetup() override {
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000149 for (int i = 0; i < 10; ++i) {
150 SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
151 SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
152 SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
153 SkScalar rot1 = fRandom.nextRangeF(-180, 180);
154 fMatrix[i].setRotate(rot0);
155 fMatrix[i].postScale(sx, sy);
156 fMatrix[i].postRotate(rot1);
157 }
158 }
mtkleinf0599002015-07-13 06:18:39 -0700159 void performTest() override {
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000160 SkPoint rotation1, scale, rotation2;
161 for (int i = 0; i < 10; ++i) {
162 (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
163 }
164 }
165private:
166 SkMatrix fMatrix[10];
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000167 SkRandom fRandom;
John Stiles7571f9e2020-09-02 22:42:33 -0400168 using INHERITED = MatrixBench;
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000169};
170
junov@chromium.org6fc56992012-07-12 14:01:32 +0000171class InvertMapRectMatrixBench : public MatrixBench {
172public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000173 InvertMapRectMatrixBench(const char* name, int flags)
174 : INHERITED(name)
junov@chromium.org6fc56992012-07-12 14:01:32 +0000175 , fFlags(flags) {
176 fMatrix.reset();
177 fIteration = 0;
178 if (flags & kScale_Flag) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000179 fMatrix.postScale(1.5f, 2.5f);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000180 }
181 if (flags & kTranslate_Flag) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000182 fMatrix.postTranslate(1.5f, 2.5f);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000183 }
184 if (flags & kRotate_Flag) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000185 fMatrix.postRotate(45.0f);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000186 }
187 if (flags & kPerspective_Flag) {
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000188 fMatrix.setPerspX(1.5f);
189 fMatrix.setPerspY(2.5f);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000190 }
191 if (0 == (flags & kUncachedTypeMask_Flag)) {
192 fMatrix.getType();
193 }
194 }
195 enum Flag {
196 kScale_Flag = 0x01,
197 kTranslate_Flag = 0x02,
198 kRotate_Flag = 0x04,
199 kPerspective_Flag = 0x08,
200 kUncachedTypeMask_Flag = 0x10,
201 };
202protected:
mtkleinf0599002015-07-13 06:18:39 -0700203 void performTest() override {
junov@chromium.org6fc56992012-07-12 14:01:32 +0000204 if (fFlags & kUncachedTypeMask_Flag) {
205 // This will invalidate the typemask without
206 // changing the matrix.
207 fMatrix.setPerspX(fMatrix.getPerspX());
208 }
209 SkMatrix inv;
robertphillips@google.com31f8f732012-09-17 13:36:47 +0000210 bool invertible = fMatrix.invert(&inv);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000211 SkASSERT(invertible);
212 SkRect transformedRect;
robertphillips@google.com31f8f732012-09-17 13:36:47 +0000213 // an arbitrary, small, non-zero rect to transform
214 SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
junov@chromium.org6fc56992012-07-12 14:01:32 +0000215 if (invertible) {
robertphillips@google.com31f8f732012-09-17 13:36:47 +0000216 inv.mapRect(&transformedRect, srcRect);
junov@chromium.org6fc56992012-07-12 14:01:32 +0000217 }
218 }
219private:
220 SkMatrix fMatrix;
junov@chromium.org6fc56992012-07-12 14:01:32 +0000221 int fFlags;
222 unsigned fIteration;
John Stiles7571f9e2020-09-02 22:42:33 -0400223 using INHERITED = MatrixBench;
junov@chromium.org6fc56992012-07-12 14:01:32 +0000224};
tomhudson@google.com288ff332011-06-07 14:31:38 +0000225
reed@google.com82bf8bb2013-01-04 14:04:08 +0000226///////////////////////////////////////////////////////////////////////////////
tomhudson@google.com288ff332011-06-07 14:31:38 +0000227
mtklein@google.com410e6e82013-09-13 19:52:27 +0000228DEF_BENCH( return new EqualsMatrixBench(); )
229DEF_BENCH( return new ScaleMatrixBench(); )
mtklein@google.com410e6e82013-09-13 19:52:27 +0000230DEF_BENCH( return new GetTypeMatrixBench(); )
231DEF_BENCH( return new DecomposeMatrixBench(); )
commit-bot@chromium.org5b2e2642013-09-03 19:08:14 +0000232
mtklein@google.com410e6e82013-09-13 19:52:27 +0000233DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )
tomhudson@google.com288ff332011-06-07 14:31:38 +0000234
mtklein@google.com410e6e82013-09-13 19:52:27 +0000235DEF_BENCH(return new InvertMapRectMatrixBench(
reed@google.com90533be2013-01-04 15:46:42 +0000236 "invert_maprect_rectstaysrect",
237 InvertMapRectMatrixBench::kScale_Flag |
238 InvertMapRectMatrixBench::kTranslate_Flag); )
239
mtklein@google.com410e6e82013-09-13 19:52:27 +0000240DEF_BENCH(return new InvertMapRectMatrixBench(
reed@google.com90533be2013-01-04 15:46:42 +0000241 "invert_maprect_translate",
242 InvertMapRectMatrixBench::kTranslate_Flag); )
tomhudson@google.com7b4e1072011-06-03 19:16:56 +0000243
mtklein@google.com410e6e82013-09-13 19:52:27 +0000244DEF_BENCH(return new InvertMapRectMatrixBench(
reed@google.com82bf8bb2013-01-04 14:04:08 +0000245 "invert_maprect_nonpersp",
246 InvertMapRectMatrixBench::kScale_Flag |
247 InvertMapRectMatrixBench::kRotate_Flag |
248 InvertMapRectMatrixBench::kTranslate_Flag); )
reed@google.com3fb51872011-06-01 15:11:22 +0000249
mtklein@google.com410e6e82013-09-13 19:52:27 +0000250DEF_BENCH( return new InvertMapRectMatrixBench(
reed@google.com82bf8bb2013-01-04 14:04:08 +0000251 "invert_maprect_persp",
252 InvertMapRectMatrixBench::kPerspective_Flag); )
tomhudson@google.com288ff332011-06-07 14:31:38 +0000253
mtklein@google.com410e6e82013-09-13 19:52:27 +0000254DEF_BENCH( return new InvertMapRectMatrixBench(
reed@google.com82bf8bb2013-01-04 14:04:08 +0000255 "invert_maprect_typemask_rectstaysrect",
256 InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
257 InvertMapRectMatrixBench::kScale_Flag |
258 InvertMapRectMatrixBench::kTranslate_Flag); )
259
mtklein@google.com410e6e82013-09-13 19:52:27 +0000260DEF_BENCH( return new InvertMapRectMatrixBench(
reed@google.com82bf8bb2013-01-04 14:04:08 +0000261 "invert_maprect_typemask_nonpersp",
262 InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
263 InvertMapRectMatrixBench::kScale_Flag |
264 InvertMapRectMatrixBench::kRotate_Flag |
265 InvertMapRectMatrixBench::kTranslate_Flag); )
266
reed80106322015-03-23 08:15:14 -0700267///////////////////////////////////////////////////////////////////////////////
268
Mike Reed1f607332020-05-21 12:11:27 -0400269static SkMatrix make_trans() { return SkMatrix::Translate(2, 3); }
reed80106322015-03-23 08:15:14 -0700270static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
271static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
272
273class MapPointsMatrixBench : public MatrixBench {
274protected:
275 SkMatrix fM;
276 enum {
277 N = 32
278 };
279 SkPoint fSrc[N], fDst[N];
reed80106322015-03-23 08:15:14 -0700280public:
reed7da19012015-03-29 11:58:48 -0700281 MapPointsMatrixBench(const char name[], const SkMatrix& m)
282 : MatrixBench(name), fM(m)
reed80106322015-03-23 08:15:14 -0700283 {
284 SkRandom rand;
285 for (int i = 0; i < N; ++i) {
286 fSrc[i].set(rand.nextSScalar1(), rand.nextSScalar1());
287 }
288 }
289
mtklein36352bf2015-03-25 18:17:31 -0700290 void performTest() override {
reed7da19012015-03-29 11:58:48 -0700291 for (int i = 0; i < 1000000; ++i) {
292 fM.mapPoints(fDst, fSrc, N);
reed80106322015-03-23 08:15:14 -0700293 }
294 }
295};
reed7da19012015-03-29 11:58:48 -0700296DEF_BENCH( return new MapPointsMatrixBench("mappoints_identity", SkMatrix::I()); )
297DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
298DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
299DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )
reed47df89e2016-06-30 06:38:54 -0700300
301///////////////////////////////////////////////////////////////////////////////
302
303class MapRectMatrixBench : public MatrixBench {
304 SkMatrix fM;
305 SkRect fR;
306 bool fScaleTrans;
307
308 enum { MEGA_LOOP = 1000 * 1000 };
309public:
310 MapRectMatrixBench(const char name[], bool scale_trans)
311 : MatrixBench(name), fScaleTrans(scale_trans)
312 {
313 fM.setScale(2, 3);
314 fM.postTranslate(1, 2);
315
Mike Reed92b33352019-08-24 19:39:13 -0400316 fR.setLTRB(10, 10, 100, 200);
reed47df89e2016-06-30 06:38:54 -0700317 }
318
319 void performTest() override {
320 SkRect dst;
321 if (fScaleTrans) {
322 for (int i = 0; i < MEGA_LOOP; ++i) {
halcanaryc5769b22016-08-10 07:13:21 -0700323 fM.mapRectScaleTranslate(&dst, fR);
reed47df89e2016-06-30 06:38:54 -0700324 }
325 } else {
326 for (int i = 0; i < MEGA_LOOP; ++i) {
327 fM.mapRect(&dst, fR);
328 }
329 }
330 }
331};
332DEF_BENCH( return new MapRectMatrixBench("maprect", false); )
333DEF_BENCH( return new MapRectMatrixBench("maprectscaletrans", true); )