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