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