1d8e81115badb90c597ced0d332cdbd44e9cb4eb
[platform/upstream/libSkiaSharp.git] / bench / MatrixBench.cpp
1
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "Benchmark.h"
9 #include "SkMatrix.h"
10 #include "SkMatrixUtils.h"
11 #include "SkRandom.h"
12 #include "SkString.h"
13
14 class MatrixBench : public Benchmark {
15     SkString    fName;
16 public:
17     MatrixBench(const char name[])  {
18         fName.printf("matrix_%s", name);
19     }
20
21     bool isSuitableFor(Backend backend) SK_OVERRIDE {
22         return backend == kNonRendering_Backend;
23     }
24
25     virtual void performTest() = 0;
26
27 protected:
28     virtual int mulLoopCount() const { return 1; }
29
30     virtual const char* onGetName() {
31         return fName.c_str();
32     }
33
34     virtual void onDraw(const int loops, SkCanvas*) {
35         for (int i = 0; i < loops; i++) {
36             this->performTest();
37         }
38     }
39
40 private:
41     typedef Benchmark INHERITED;
42 };
43
44
45 class EqualsMatrixBench : public MatrixBench {
46 public:
47     EqualsMatrixBench() : INHERITED("equals") {}
48 protected:
49     virtual void performTest() {
50         SkMatrix m0, m1, m2;
51
52         m0.reset();
53         m1.reset();
54         m2.reset();
55
56         // xor into a volatile prevents these comparisons from being optimized away.
57         volatile bool junk = false;
58         junk ^= (m0 == m1);
59         junk ^= (m1 == m2);
60         junk ^= (m2 == m0);
61     }
62 private:
63     typedef MatrixBench INHERITED;
64 };
65
66 class ScaleMatrixBench : public MatrixBench {
67 public:
68     ScaleMatrixBench() : INHERITED("scale") {
69         fSX = fSY = 1.5f;
70         fM0.reset();
71         fM1.setScale(fSX, fSY);
72         fM2.setTranslate(fSX, fSY);
73     }
74 protected:
75     virtual void performTest() {
76         SkMatrix m;
77         m = fM0; m.preScale(fSX, fSY);
78         m = fM1; m.preScale(fSX, fSY);
79         m = fM2; m.preScale(fSX, fSY);
80     }
81 private:
82     SkMatrix fM0, fM1, fM2;
83     SkScalar fSX, fSY;
84     typedef MatrixBench INHERITED;
85 };
86
87 // having unknown values in our arrays can throw off the timing a lot, perhaps
88 // handling NaN values is a lot slower. Anyway, this guy is just meant to put
89 // reasonable values in our arrays.
90 template <typename T> void init9(T array[9]) {
91     SkRandom rand;
92     for (int i = 0; i < 9; i++) {
93         array[i] = rand.nextSScalar1();
94     }
95 }
96
97 class GetTypeMatrixBench : public MatrixBench {
98 public:
99     GetTypeMatrixBench()
100         : INHERITED("gettype") {
101         fArray[0] = (float) fRnd.nextS();
102         fArray[1] = (float) fRnd.nextS();
103         fArray[2] = (float) fRnd.nextS();
104         fArray[3] = (float) fRnd.nextS();
105         fArray[4] = (float) fRnd.nextS();
106         fArray[5] = (float) fRnd.nextS();
107         fArray[6] = (float) fRnd.nextS();
108         fArray[7] = (float) fRnd.nextS();
109         fArray[8] = (float) fRnd.nextS();
110     }
111 protected:
112     // Putting random generation of the matrix inside performTest()
113     // would help us avoid anomalous runs, but takes up 25% or
114     // more of the function time.
115     virtual void performTest() {
116         fMatrix.setAll(fArray[0], fArray[1], fArray[2],
117                        fArray[3], fArray[4], fArray[5],
118                        fArray[6], fArray[7], fArray[8]);
119         // xoring into a volatile prevents the compiler from optimizing these away
120         volatile int junk = 0;
121         junk ^= (fMatrix.getType());
122         fMatrix.dirtyMatrixTypeCache();
123         junk ^= (fMatrix.getType());
124         fMatrix.dirtyMatrixTypeCache();
125         junk ^= (fMatrix.getType());
126         fMatrix.dirtyMatrixTypeCache();
127         junk ^= (fMatrix.getType());
128         fMatrix.dirtyMatrixTypeCache();
129         junk ^= (fMatrix.getType());
130         fMatrix.dirtyMatrixTypeCache();
131         junk ^= (fMatrix.getType());
132         fMatrix.dirtyMatrixTypeCache();
133         junk ^= (fMatrix.getType());
134         fMatrix.dirtyMatrixTypeCache();
135         junk ^= (fMatrix.getType());
136     }
137 private:
138     SkMatrix fMatrix;
139     float fArray[9];
140     SkRandom fRnd;
141     typedef MatrixBench INHERITED;
142 };
143
144 class DecomposeMatrixBench : public MatrixBench {
145 public:
146     DecomposeMatrixBench() : INHERITED("decompose") {}
147
148 protected:
149     virtual void onPreDraw() {
150         for (int i = 0; i < 10; ++i) {
151             SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
152             SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
153             SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
154             SkScalar rot1 = fRandom.nextRangeF(-180, 180);
155             fMatrix[i].setRotate(rot0);
156             fMatrix[i].postScale(sx, sy);
157             fMatrix[i].postRotate(rot1);
158         }
159     }
160     virtual void performTest() {
161         SkPoint rotation1, scale, rotation2;
162         for (int i = 0; i < 10; ++i) {
163             (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
164         }
165     }
166 private:
167     SkMatrix fMatrix[10];
168     SkRandom fRandom;
169     typedef MatrixBench INHERITED;
170 };
171
172 class InvertMapRectMatrixBench : public MatrixBench {
173 public:
174     InvertMapRectMatrixBench(const char* name, int flags)
175         : INHERITED(name)
176         , fFlags(flags) {
177         fMatrix.reset();
178         fIteration = 0;
179         if (flags & kScale_Flag) {
180             fMatrix.postScale(1.5f, 2.5f);
181         }
182         if (flags & kTranslate_Flag) {
183             fMatrix.postTranslate(1.5f, 2.5f);
184         }
185         if (flags & kRotate_Flag) {
186             fMatrix.postRotate(45.0f);
187         }
188         if (flags & kPerspective_Flag) {
189             fMatrix.setPerspX(1.5f);
190             fMatrix.setPerspY(2.5f);
191         }
192         if (0 == (flags & kUncachedTypeMask_Flag)) {
193             fMatrix.getType();
194         }
195     }
196     enum Flag {
197         kScale_Flag             = 0x01,
198         kTranslate_Flag         = 0x02,
199         kRotate_Flag            = 0x04,
200         kPerspective_Flag       = 0x08,
201         kUncachedTypeMask_Flag  = 0x10,
202     };
203 protected:
204     virtual void performTest() {
205         if (fFlags & kUncachedTypeMask_Flag) {
206             // This will invalidate the typemask without
207             // changing the matrix.
208             fMatrix.setPerspX(fMatrix.getPerspX());
209         }
210         SkMatrix inv;
211         bool invertible = fMatrix.invert(&inv);
212         SkASSERT(invertible);
213         SkRect transformedRect;
214         // an arbitrary, small, non-zero rect to transform
215         SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
216         if (invertible) {
217             inv.mapRect(&transformedRect, srcRect);
218         }
219     }
220 private:
221     SkMatrix fMatrix;
222     int fFlags;
223     unsigned fIteration;
224     typedef MatrixBench INHERITED;
225 };
226
227 ///////////////////////////////////////////////////////////////////////////////
228
229 DEF_BENCH( return new EqualsMatrixBench(); )
230 DEF_BENCH( return new ScaleMatrixBench(); )
231 DEF_BENCH( return new GetTypeMatrixBench(); )
232 DEF_BENCH( return new DecomposeMatrixBench(); )
233
234 DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )
235
236 DEF_BENCH(return new InvertMapRectMatrixBench(
237                                   "invert_maprect_rectstaysrect",
238                                   InvertMapRectMatrixBench::kScale_Flag |
239                                   InvertMapRectMatrixBench::kTranslate_Flag); )
240
241 DEF_BENCH(return new InvertMapRectMatrixBench(
242                                   "invert_maprect_translate",
243                                   InvertMapRectMatrixBench::kTranslate_Flag); )
244
245 DEF_BENCH(return new InvertMapRectMatrixBench(
246                                   "invert_maprect_nonpersp",
247                                   InvertMapRectMatrixBench::kScale_Flag |
248                                   InvertMapRectMatrixBench::kRotate_Flag |
249                                   InvertMapRectMatrixBench::kTranslate_Flag); )
250
251 DEF_BENCH( return new InvertMapRectMatrixBench(
252                                "invert_maprect_persp",
253                                InvertMapRectMatrixBench::kPerspective_Flag); )
254
255 DEF_BENCH( return new InvertMapRectMatrixBench(
256                            "invert_maprect_typemask_rectstaysrect",
257                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
258                            InvertMapRectMatrixBench::kScale_Flag |
259                            InvertMapRectMatrixBench::kTranslate_Flag); )
260
261 DEF_BENCH( return new InvertMapRectMatrixBench(
262                            "invert_maprect_typemask_nonpersp",
263                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
264                            InvertMapRectMatrixBench::kScale_Flag |
265                            InvertMapRectMatrixBench::kRotate_Flag |
266                            InvertMapRectMatrixBench::kTranslate_Flag); )
267
268 ///////////////////////////////////////////////////////////////////////////////
269
270 static SkMatrix make_ident() { SkMatrix m; m.reset(); return m; }
271 static SkMatrix make_trans() { SkMatrix m; m.setTranslate(2, 3); return m; }
272 static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
273 static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
274
275 class MapPointsMatrixBench : public MatrixBench {
276 protected:
277     SkMatrix fM;
278     enum {
279         N = 32
280     };
281     SkPoint fSrc[N], fDst[N];
282     const bool fNewWay;
283 public:
284     MapPointsMatrixBench(const char name[], const SkMatrix& m, bool newWay)
285         : MatrixBench(name), fM(m), fNewWay(newWay)
286     {
287         SkRandom rand;
288         for (int i = 0; i < N; ++i) {
289             fSrc[i].set(rand.nextSScalar1(), rand.nextSScalar1());
290         }
291     }
292
293     void performTest() SK_OVERRIDE {
294         if (fNewWay) {
295             for (int i = 0; i < 1000000; ++i) {
296                 fM.mapPts(fDst, fSrc, N);
297             }
298         } else {
299             for (int i = 0; i < 1000000; ++i) {
300                 fM.mapPoints(fDst, fSrc, N);
301             }
302         }
303     }
304 };
305 DEF_BENCH( return new MapPointsMatrixBench("mappts_ident0", make_ident(), false); )
306 DEF_BENCH( return new MapPointsMatrixBench("mappts_ident1", make_ident(), true); )
307 DEF_BENCH( return new MapPointsMatrixBench("mappts_trans0", make_trans(), false); )
308 DEF_BENCH( return new MapPointsMatrixBench("mappts_trans1", make_trans(), true); )
309 DEF_BENCH( return new MapPointsMatrixBench("mappts_scale0", make_scale(), false); )
310 DEF_BENCH( return new MapPointsMatrixBench("mappts_scale1", make_scale(), true); )
311 DEF_BENCH( return new MapPointsMatrixBench("mappts_afine0", make_afine(), false); )
312 DEF_BENCH( return new MapPointsMatrixBench("mappts_afine1", make_afine(), true); )
313