xref: /aosp_15_r20/external/skia/bench/MatrixBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
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  */
7 #include "bench/Benchmark.h"
8 #include "include/core/SkMatrix.h"
9 #include "include/core/SkString.h"
10 #include "src/base/SkRandom.h"
11 #include "src/core/SkMatrixUtils.h"
12 
13 class MatrixBench : public Benchmark {
14     SkString    fName;
15 public:
MatrixBench(const char name[])16     MatrixBench(const char name[])  {
17         fName.printf("matrix_%s", name);
18     }
19 
isSuitableFor(Backend backend)20     bool isSuitableFor(Backend backend) override {
21         return backend == Backend::kNonRendering;
22     }
23 
24     virtual void performTest() = 0;
25 
26 protected:
mulLoopCount() const27     virtual int mulLoopCount() const { return 1; }
28 
onGetName()29     const char* onGetName() override {
30         return fName.c_str();
31     }
32 
onDraw(int loops,SkCanvas *)33     void onDraw(int loops, SkCanvas*) override {
34         for (int i = 0; i < loops; i++) {
35             this->performTest();
36         }
37     }
38 
39 private:
40     using INHERITED = Benchmark;
41 };
42 
43 class ScaleMatrixBench : public MatrixBench {
44 public:
ScaleMatrixBench()45     ScaleMatrixBench() : INHERITED("scale") {
46         fSX = fSY = 1.5f;
47         fM0.reset();
48         fM1.setScale(fSX, fSY);
49         fM2.setTranslate(fSX, fSY);
50     }
51 protected:
performTest()52     void performTest() override {
53         SkMatrix m;
54         m = fM0; m.preScale(fSX, fSY);
55         m = fM1; m.preScale(fSX, fSY);
56         m = fM2; m.preScale(fSX, fSY);
57     }
58 private:
59     SkMatrix fM0, fM1, fM2;
60     SkScalar fSX, fSY;
61     using INHERITED = MatrixBench;
62 };
63 
64 // having unknown values in our arrays can throw off the timing a lot, perhaps
65 // handling NaN values is a lot slower. Anyway, this is just meant to put
66 // reasonable values in our arrays.
init9(T array[9])67 template <typename T> void init9(T array[9]) {
68     SkRandom rand;
69     for (int i = 0; i < 9; i++) {
70         array[i] = rand.nextSScalar1();
71     }
72 }
73 
74 class DecomposeMatrixBench : public MatrixBench {
75 public:
DecomposeMatrixBench()76     DecomposeMatrixBench() : INHERITED("decompose") {}
77 
78 protected:
onDelayedSetup()79     void onDelayedSetup() override {
80         for (int i = 0; i < 10; ++i) {
81             SkScalar rot0 = (fRandom.nextBool()) ? fRandom.nextRangeF(-180, 180) : 0.0f;
82             SkScalar sx = fRandom.nextRangeF(-3000.f, 3000.f);
83             SkScalar sy = (fRandom.nextBool()) ? fRandom.nextRangeF(-3000.f, 3000.f) : sx;
84             SkScalar rot1 = fRandom.nextRangeF(-180, 180);
85             fMatrix[i].setRotate(rot0);
86             fMatrix[i].postScale(sx, sy);
87             fMatrix[i].postRotate(rot1);
88         }
89     }
performTest()90     void performTest() override {
91         SkPoint rotation1, scale, rotation2;
92         for (int i = 0; i < 10; ++i) {
93             (void) SkDecomposeUpper2x2(fMatrix[i], &rotation1, &scale, &rotation2);
94         }
95     }
96 private:
97     SkMatrix fMatrix[10];
98     SkRandom fRandom;
99     using INHERITED = MatrixBench;
100 };
101 
102 class InvertMapRectMatrixBench : public MatrixBench {
103 public:
InvertMapRectMatrixBench(const char * name,int flags)104     InvertMapRectMatrixBench(const char* name, int flags)
105         : INHERITED(name)
106         , fFlags(flags) {
107         fMatrix.reset();
108         fIteration = 0;
109         if (flags & kScale_Flag) {
110             fMatrix.postScale(1.5f, 2.5f);
111         }
112         if (flags & kTranslate_Flag) {
113             fMatrix.postTranslate(1.5f, 2.5f);
114         }
115         if (flags & kRotate_Flag) {
116             fMatrix.postRotate(45.0f);
117         }
118         if (flags & kPerspective_Flag) {
119             fMatrix.setPerspX(1.5f);
120             fMatrix.setPerspY(2.5f);
121         }
122         if (0 == (flags & kUncachedTypeMask_Flag)) {
123             fMatrix.getType();
124         }
125     }
126     enum Flag {
127         kScale_Flag             = 0x01,
128         kTranslate_Flag         = 0x02,
129         kRotate_Flag            = 0x04,
130         kPerspective_Flag       = 0x08,
131         kUncachedTypeMask_Flag  = 0x10,
132     };
133 protected:
performTest()134     void performTest() override {
135         if (fFlags & kUncachedTypeMask_Flag) {
136             // This will invalidate the typemask without
137             // changing the matrix.
138             fMatrix.setPerspX(fMatrix.getPerspX());
139         }
140         SkMatrix inv;
141         bool invertible = fMatrix.invert(&inv);
142         SkASSERT(invertible);
143         SkRect transformedRect;
144         // an arbitrary, small, non-zero rect to transform
145         SkRect srcRect = SkRect::MakeWH(SkIntToScalar(10), SkIntToScalar(10));
146         if (invertible) {
147             inv.mapRect(&transformedRect, srcRect);
148         }
149     }
150 private:
151     SkMatrix fMatrix;
152     int fFlags;
153     unsigned fIteration;
154     using INHERITED = MatrixBench;
155 };
156 
157 ///////////////////////////////////////////////////////////////////////////////
158 
159 DEF_BENCH( return new ScaleMatrixBench(); )
DEF_BENCH(return new DecomposeMatrixBench ();)160 DEF_BENCH( return new DecomposeMatrixBench(); )
161 
162 DEF_BENCH( return new InvertMapRectMatrixBench("invert_maprect_identity", 0); )
163 
164 DEF_BENCH(return new InvertMapRectMatrixBench(
165                                   "invert_maprect_rectstaysrect",
166                                   InvertMapRectMatrixBench::kScale_Flag |
167                                   InvertMapRectMatrixBench::kTranslate_Flag); )
168 
169 DEF_BENCH(return new InvertMapRectMatrixBench(
170                                   "invert_maprect_translate",
171                                   InvertMapRectMatrixBench::kTranslate_Flag); )
172 
173 DEF_BENCH(return new InvertMapRectMatrixBench(
174                                   "invert_maprect_nonpersp",
175                                   InvertMapRectMatrixBench::kScale_Flag |
176                                   InvertMapRectMatrixBench::kRotate_Flag |
177                                   InvertMapRectMatrixBench::kTranslate_Flag); )
178 
179 DEF_BENCH( return new InvertMapRectMatrixBench(
180                                "invert_maprect_persp",
181                                InvertMapRectMatrixBench::kPerspective_Flag); )
182 
183 DEF_BENCH( return new InvertMapRectMatrixBench(
184                            "invert_maprect_typemask_rectstaysrect",
185                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
186                            InvertMapRectMatrixBench::kScale_Flag |
187                            InvertMapRectMatrixBench::kTranslate_Flag); )
188 
189 DEF_BENCH( return new InvertMapRectMatrixBench(
190                            "invert_maprect_typemask_nonpersp",
191                            InvertMapRectMatrixBench::kUncachedTypeMask_Flag |
192                            InvertMapRectMatrixBench::kScale_Flag |
193                            InvertMapRectMatrixBench::kRotate_Flag |
194                            InvertMapRectMatrixBench::kTranslate_Flag); )
195 
196 ///////////////////////////////////////////////////////////////////////////////
197 
198 static SkMatrix make_trans() { return SkMatrix::Translate(2, 3); }
make_scale()199 static SkMatrix make_scale() { SkMatrix m(make_trans()); m.postScale(1.5f, 0.5f); return m; }
make_afine()200 static SkMatrix make_afine() { SkMatrix m(make_trans()); m.postRotate(15); return m; }
201 
202 class MapPointsMatrixBench : public MatrixBench {
203 protected:
204     SkMatrix fM;
205     enum {
206         N = 32
207     };
208     SkPoint fSrc[N], fDst[N];
209 public:
MapPointsMatrixBench(const char name[],const SkMatrix & m)210     MapPointsMatrixBench(const char name[], const SkMatrix& m)
211         : MatrixBench(name), fM(m)
212     {
213         SkRandom rand;
214         for (int i = 0; i < N; ++i) {
215             fSrc[i].set(rand.nextSScalar1(), rand.nextSScalar1());
216         }
217     }
218 
performTest()219     void performTest() override {
220         for (int i = 0; i < 1000000; ++i) {
221             fM.mapPoints(fDst, fSrc, N);
222         }
223     }
224 };
225 DEF_BENCH( return new MapPointsMatrixBench("mappoints_identity", SkMatrix::I()); )
226 DEF_BENCH( return new MapPointsMatrixBench("mappoints_trans", make_trans()); )
227 DEF_BENCH( return new MapPointsMatrixBench("mappoints_scale", make_scale()); )
228 DEF_BENCH( return new MapPointsMatrixBench("mappoints_affine", make_afine()); )
229 
230 ///////////////////////////////////////////////////////////////////////////////
231 
232 class MapRectMatrixBench : public MatrixBench {
233     SkMatrix fM;
234     SkRect   fR;
235     bool     fScaleTrans;
236 
237     enum { MEGA_LOOP = 1000 * 1000 };
238 public:
MapRectMatrixBench(const char name[],bool scale_trans)239     MapRectMatrixBench(const char name[], bool scale_trans)
240         : MatrixBench(name), fScaleTrans(scale_trans)
241     {
242         fM.setScale(2, 3);
243         fM.postTranslate(1, 2);
244 
245         fR.setLTRB(10, 10, 100, 200);
246     }
247 
performTest()248     void performTest() override {
249         SkRect dst;
250         if (fScaleTrans) {
251             for (int i = 0; i < MEGA_LOOP; ++i) {
252                 fM.mapRectScaleTranslate(&dst, fR);
253             }
254         } else {
255             for (int i = 0; i < MEGA_LOOP; ++i) {
256                 fM.mapRect(&dst, fR);
257             }
258         }
259     }
260 };
261 DEF_BENCH( return new MapRectMatrixBench("maprect", false); )
262 DEF_BENCH( return new MapRectMatrixBench("maprectscaletrans", true); )
263