1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 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 8*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkM44.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkVertices.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker // This bench simulates the calls Skia sees from various HTML5 canvas 20*c8dee2aaSAndroid Build Coastguard Worker // game bench marks 21*c8dee2aaSAndroid Build Coastguard Worker class GameBench : public Benchmark { 22*c8dee2aaSAndroid Build Coastguard Worker public: 23*c8dee2aaSAndroid Build Coastguard Worker enum Type { 24*c8dee2aaSAndroid Build Coastguard Worker kScale_Type, 25*c8dee2aaSAndroid Build Coastguard Worker kTranslate_Type, 26*c8dee2aaSAndroid Build Coastguard Worker kRotate_Type 27*c8dee2aaSAndroid Build Coastguard Worker }; 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker enum Clear { 30*c8dee2aaSAndroid Build Coastguard Worker kFull_Clear, 31*c8dee2aaSAndroid Build Coastguard Worker kPartial_Clear 32*c8dee2aaSAndroid Build Coastguard Worker }; 33*c8dee2aaSAndroid Build Coastguard Worker GameBench(Type type,Clear clear,bool aligned=false,bool useAtlas=false,bool useDrawVertices=false)34*c8dee2aaSAndroid Build Coastguard Worker GameBench(Type type, Clear clear, 35*c8dee2aaSAndroid Build Coastguard Worker bool aligned = false, bool useAtlas = false, 36*c8dee2aaSAndroid Build Coastguard Worker bool useDrawVertices = false) 37*c8dee2aaSAndroid Build Coastguard Worker : fType(type) 38*c8dee2aaSAndroid Build Coastguard Worker , fClear(clear) 39*c8dee2aaSAndroid Build Coastguard Worker , fAligned(aligned) 40*c8dee2aaSAndroid Build Coastguard Worker , fUseAtlas(useAtlas) 41*c8dee2aaSAndroid Build Coastguard Worker , fUseDrawVertices(useDrawVertices) 42*c8dee2aaSAndroid Build Coastguard Worker , fName("game") 43*c8dee2aaSAndroid Build Coastguard Worker , fNumSaved(0) 44*c8dee2aaSAndroid Build Coastguard Worker , fInitialized(false) { 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker switch (fType) { 47*c8dee2aaSAndroid Build Coastguard Worker case kScale_Type: 48*c8dee2aaSAndroid Build Coastguard Worker fName.append("_scale"); 49*c8dee2aaSAndroid Build Coastguard Worker break; 50*c8dee2aaSAndroid Build Coastguard Worker case kTranslate_Type: 51*c8dee2aaSAndroid Build Coastguard Worker fName.append("_trans"); 52*c8dee2aaSAndroid Build Coastguard Worker break; 53*c8dee2aaSAndroid Build Coastguard Worker case kRotate_Type: 54*c8dee2aaSAndroid Build Coastguard Worker fName.append("_rot"); 55*c8dee2aaSAndroid Build Coastguard Worker break; 56*c8dee2aaSAndroid Build Coastguard Worker } 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker if (aligned) { 59*c8dee2aaSAndroid Build Coastguard Worker fName.append("_aligned"); 60*c8dee2aaSAndroid Build Coastguard Worker } 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker if (kPartial_Clear == clear) { 63*c8dee2aaSAndroid Build Coastguard Worker fName.append("_partial"); 64*c8dee2aaSAndroid Build Coastguard Worker } else { 65*c8dee2aaSAndroid Build Coastguard Worker fName.append("_full"); 66*c8dee2aaSAndroid Build Coastguard Worker } 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker if (useAtlas) { 69*c8dee2aaSAndroid Build Coastguard Worker fName.append("_atlas"); 70*c8dee2aaSAndroid Build Coastguard Worker } 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker if (useDrawVertices) { 73*c8dee2aaSAndroid Build Coastguard Worker fName.append("_drawVerts"); 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker // It's HTML 5 canvas, so always AA 77*c8dee2aaSAndroid Build Coastguard Worker fName.append("_aa"); 78*c8dee2aaSAndroid Build Coastguard Worker } 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()81*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 82*c8dee2aaSAndroid Build Coastguard Worker return fName.c_str(); 83*c8dee2aaSAndroid Build Coastguard Worker } 84*c8dee2aaSAndroid Build Coastguard Worker onDelayedSetup()85*c8dee2aaSAndroid Build Coastguard Worker void onDelayedSetup() override { 86*c8dee2aaSAndroid Build Coastguard Worker if (!fInitialized) { 87*c8dee2aaSAndroid Build Coastguard Worker this->makeCheckerboard(); 88*c8dee2aaSAndroid Build Coastguard Worker this->makeAtlas(); 89*c8dee2aaSAndroid Build Coastguard Worker fInitialized = true; 90*c8dee2aaSAndroid Build Coastguard Worker } 91*c8dee2aaSAndroid Build Coastguard Worker } 92*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)93*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 94*c8dee2aaSAndroid Build Coastguard Worker SkRandom scaleRand; 95*c8dee2aaSAndroid Build Coastguard Worker SkRandom transRand; 96*c8dee2aaSAndroid Build Coastguard Worker SkRandom rotRand; 97*c8dee2aaSAndroid Build Coastguard Worker 98*c8dee2aaSAndroid Build Coastguard Worker int width, height; 99*c8dee2aaSAndroid Build Coastguard Worker if (fUseAtlas) { 100*c8dee2aaSAndroid Build Coastguard Worker width = kAtlasCellWidth; 101*c8dee2aaSAndroid Build Coastguard Worker height = kAtlasCellHeight; 102*c8dee2aaSAndroid Build Coastguard Worker } else { 103*c8dee2aaSAndroid Build Coastguard Worker width = kCheckerboardWidth; 104*c8dee2aaSAndroid Build Coastguard Worker height = kCheckerboardHeight; 105*c8dee2aaSAndroid Build Coastguard Worker } 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker SkPaint clearPaint; 108*c8dee2aaSAndroid Build Coastguard Worker clearPaint.setColor(0xFF000000); 109*c8dee2aaSAndroid Build Coastguard Worker clearPaint.setAntiAlias(true); 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker SkISize size = canvas->getBaseLayerSize(); 112*c8dee2aaSAndroid Build Coastguard Worker 113*c8dee2aaSAndroid Build Coastguard Worker SkScalar maxTransX, maxTransY; 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker if (kScale_Type == fType) { 116*c8dee2aaSAndroid Build Coastguard Worker maxTransX = size.fWidth - (1.5f * width); 117*c8dee2aaSAndroid Build Coastguard Worker maxTransY = size.fHeight - (1.5f * height); 118*c8dee2aaSAndroid Build Coastguard Worker } else if (kTranslate_Type == fType) { 119*c8dee2aaSAndroid Build Coastguard Worker maxTransX = SkIntToScalar(size.fWidth - width); 120*c8dee2aaSAndroid Build Coastguard Worker maxTransY = SkIntToScalar(size.fHeight - height); 121*c8dee2aaSAndroid Build Coastguard Worker } else { 122*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(kRotate_Type == fType); 123*c8dee2aaSAndroid Build Coastguard Worker // Yes, some rotations will be off the top and left sides 124*c8dee2aaSAndroid Build Coastguard Worker maxTransX = size.fWidth - SK_ScalarSqrt2 * height; 125*c8dee2aaSAndroid Build Coastguard Worker maxTransY = size.fHeight - SK_ScalarSqrt2 * height; 126*c8dee2aaSAndroid Build Coastguard Worker } 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Worker SkMatrix mat; 129*c8dee2aaSAndroid Build Coastguard Worker SkRect dst = { 0, 0, SkIntToScalar(width), SkIntToScalar(height) }; 130*c8dee2aaSAndroid Build Coastguard Worker SkRect clearRect = { -1.0f, -1.0f, width+1.0f, height+1.0f }; 131*c8dee2aaSAndroid Build Coastguard Worker SkPoint verts[4] = { // for drawVertices path 132*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 }, 133*c8dee2aaSAndroid Build Coastguard Worker { 0, SkIntToScalar(height) }, 134*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(width), SkIntToScalar(height) }, 135*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(width), 0 } 136*c8dee2aaSAndroid Build Coastguard Worker }; 137*c8dee2aaSAndroid Build Coastguard Worker uint16_t indices[6] = { 0, 1, 2, 0, 2, 3 }; 138*c8dee2aaSAndroid Build Coastguard Worker 139*c8dee2aaSAndroid Build Coastguard Worker SkPaint p; 140*c8dee2aaSAndroid Build Coastguard Worker p.setColor(0xFF000000); 141*c8dee2aaSAndroid Build Coastguard Worker 142*c8dee2aaSAndroid Build Coastguard Worker SkPaint p2; // for drawVertices path 143*c8dee2aaSAndroid Build Coastguard Worker p2.setColor(0xFF000000); 144*c8dee2aaSAndroid Build Coastguard Worker p2.setShader(fAtlas->makeShader(SkSamplingOptions(SkFilterMode::kLinear))); 145*c8dee2aaSAndroid Build Coastguard Worker 146*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i, ++fNumSaved) { 147*c8dee2aaSAndroid Build Coastguard Worker if (0 == i % kNumBeforeClear) { 148*c8dee2aaSAndroid Build Coastguard Worker if (kPartial_Clear == fClear) { 149*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < fNumSaved; ++j) { 150*c8dee2aaSAndroid Build Coastguard Worker canvas->setMatrix(SkMatrix::I()); 151*c8dee2aaSAndroid Build Coastguard Worker mat.setTranslate(fSaved[j][0], fSaved[j][1]); 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker if (kScale_Type == fType) { 154*c8dee2aaSAndroid Build Coastguard Worker mat.preScale(fSaved[j][2], fSaved[j][2]); 155*c8dee2aaSAndroid Build Coastguard Worker } else if (kRotate_Type == fType) { 156*c8dee2aaSAndroid Build Coastguard Worker mat.preRotate(fSaved[j][2]); 157*c8dee2aaSAndroid Build Coastguard Worker } 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(mat); 160*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(clearRect, clearPaint); 161*c8dee2aaSAndroid Build Coastguard Worker } 162*c8dee2aaSAndroid Build Coastguard Worker } else { 163*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(0xFF000000); 164*c8dee2aaSAndroid Build Coastguard Worker } 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker fNumSaved = 0; 167*c8dee2aaSAndroid Build Coastguard Worker } 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fNumSaved < kNumBeforeClear); 170*c8dee2aaSAndroid Build Coastguard Worker 171*c8dee2aaSAndroid Build Coastguard Worker canvas->setMatrix(SkMatrix::I()); 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][0] = transRand.nextRangeScalar(0.0f, maxTransX); 174*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][1] = transRand.nextRangeScalar(0.0f, maxTransY); 175*c8dee2aaSAndroid Build Coastguard Worker if (fAligned) { 176*c8dee2aaSAndroid Build Coastguard Worker // make the translations integer aligned 177*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][0] = SkScalarFloorToScalar(fSaved[fNumSaved][0]); 178*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][1] = SkScalarFloorToScalar(fSaved[fNumSaved][1]); 179*c8dee2aaSAndroid Build Coastguard Worker } 180*c8dee2aaSAndroid Build Coastguard Worker 181*c8dee2aaSAndroid Build Coastguard Worker mat.setTranslate(fSaved[fNumSaved][0], fSaved[fNumSaved][1]); 182*c8dee2aaSAndroid Build Coastguard Worker 183*c8dee2aaSAndroid Build Coastguard Worker if (kScale_Type == fType) { 184*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][2] = scaleRand.nextRangeScalar(0.5f, 1.5f); 185*c8dee2aaSAndroid Build Coastguard Worker mat.preScale(fSaved[fNumSaved][2], fSaved[fNumSaved][2]); 186*c8dee2aaSAndroid Build Coastguard Worker } else if (kRotate_Type == fType) { 187*c8dee2aaSAndroid Build Coastguard Worker fSaved[fNumSaved][2] = rotRand.nextRangeScalar(0.0f, 360.0f); 188*c8dee2aaSAndroid Build Coastguard Worker mat.preRotate(fSaved[fNumSaved][2]); 189*c8dee2aaSAndroid Build Coastguard Worker } 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(mat); 192*c8dee2aaSAndroid Build Coastguard Worker if (fUseAtlas) { 193*c8dee2aaSAndroid Build Coastguard Worker const int curCell = i % (kNumAtlasedX * kNumAtlasedY); 194*c8dee2aaSAndroid Build Coastguard Worker SkRect src = SkRect::Make( 195*c8dee2aaSAndroid Build Coastguard Worker fAtlasRects[curCell % (kNumAtlasedX)][curCell / (kNumAtlasedX)]); 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker if (fUseDrawVertices) { 198*c8dee2aaSAndroid Build Coastguard Worker SkPoint uvs[4] = { 199*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(src.fLeft), SkIntToScalar(src.fBottom) }, 200*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(src.fLeft), SkIntToScalar(src.fTop) }, 201*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(src.fRight), SkIntToScalar(src.fTop) }, 202*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(src.fRight), SkIntToScalar(src.fBottom) }, 203*c8dee2aaSAndroid Build Coastguard Worker }; 204*c8dee2aaSAndroid Build Coastguard Worker canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, 205*c8dee2aaSAndroid Build Coastguard Worker 4, verts, uvs, nullptr, 6, indices), 206*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode::kModulate, p2); 207*c8dee2aaSAndroid Build Coastguard Worker } else { 208*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(fAtlas, src, dst, SkSamplingOptions(), &p, 209*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::kFast_SrcRectConstraint); 210*c8dee2aaSAndroid Build Coastguard Worker } 211*c8dee2aaSAndroid Build Coastguard Worker } else { 212*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImageRect(fCheckerboard, dst, SkSamplingOptions(), &p); 213*c8dee2aaSAndroid Build Coastguard Worker } 214*c8dee2aaSAndroid Build Coastguard Worker } 215*c8dee2aaSAndroid Build Coastguard Worker } 216*c8dee2aaSAndroid Build Coastguard Worker 217*c8dee2aaSAndroid Build Coastguard Worker private: 218*c8dee2aaSAndroid Build Coastguard Worker static const int kCheckerboardWidth = 64; 219*c8dee2aaSAndroid Build Coastguard Worker static const int kCheckerboardHeight = 128; 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker static const int kAtlasCellWidth = 48; 222*c8dee2aaSAndroid Build Coastguard Worker static const int kAtlasCellHeight = 36; 223*c8dee2aaSAndroid Build Coastguard Worker static const int kNumAtlasedX = 5; 224*c8dee2aaSAndroid Build Coastguard Worker static const int kNumAtlasedY = 5; 225*c8dee2aaSAndroid Build Coastguard Worker static const int kAtlasSpacer = 2; 226*c8dee2aaSAndroid Build Coastguard Worker static const int kTotAtlasWidth = kNumAtlasedX * kAtlasCellWidth + 227*c8dee2aaSAndroid Build Coastguard Worker (kNumAtlasedX+1) * kAtlasSpacer; 228*c8dee2aaSAndroid Build Coastguard Worker static const int kTotAtlasHeight = kNumAtlasedY * kAtlasCellHeight + 229*c8dee2aaSAndroid Build Coastguard Worker (kNumAtlasedY+1) * kAtlasSpacer; 230*c8dee2aaSAndroid Build Coastguard Worker static const int kNumBeforeClear = 100; 231*c8dee2aaSAndroid Build Coastguard Worker 232*c8dee2aaSAndroid Build Coastguard Worker Type fType; 233*c8dee2aaSAndroid Build Coastguard Worker Clear fClear; 234*c8dee2aaSAndroid Build Coastguard Worker bool fAligned; 235*c8dee2aaSAndroid Build Coastguard Worker bool fUseAtlas; 236*c8dee2aaSAndroid Build Coastguard Worker bool fUseDrawVertices; 237*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 238*c8dee2aaSAndroid Build Coastguard Worker int fNumSaved; // num draws stored in 'fSaved' 239*c8dee2aaSAndroid Build Coastguard Worker bool fInitialized; 240*c8dee2aaSAndroid Build Coastguard Worker 241*c8dee2aaSAndroid Build Coastguard Worker // 0 & 1 are always x & y translate. 2 is either scale or rotate. 242*c8dee2aaSAndroid Build Coastguard Worker SkScalar fSaved[kNumBeforeClear][3]; 243*c8dee2aaSAndroid Build Coastguard Worker 244*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fCheckerboard, fAtlas; 245*c8dee2aaSAndroid Build Coastguard Worker SkIRect fAtlasRects[kNumAtlasedX][kNumAtlasedY]; 246*c8dee2aaSAndroid Build Coastguard Worker 247*c8dee2aaSAndroid Build Coastguard Worker // Note: the resulting checker board has transparency makeCheckerboard()248*c8dee2aaSAndroid Build Coastguard Worker void makeCheckerboard() { 249*c8dee2aaSAndroid Build Coastguard Worker static int kCheckSize = 16; 250*c8dee2aaSAndroid Build Coastguard Worker 251*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm; 252*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(kCheckerboardWidth, kCheckerboardHeight); 253*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kCheckerboardHeight; ++y) { 254*c8dee2aaSAndroid Build Coastguard Worker int even = (y / kCheckSize) % 2; 255*c8dee2aaSAndroid Build Coastguard Worker 256*c8dee2aaSAndroid Build Coastguard Worker SkPMColor* scanline = bm.getAddr32(0, y); 257*c8dee2aaSAndroid Build Coastguard Worker 258*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < kCheckerboardWidth; ++x) { 259*c8dee2aaSAndroid Build Coastguard Worker if (even == (x / kCheckSize) % 2) { 260*c8dee2aaSAndroid Build Coastguard Worker *scanline++ = 0xFFFF0000; 261*c8dee2aaSAndroid Build Coastguard Worker } else { 262*c8dee2aaSAndroid Build Coastguard Worker *scanline++ = 0x00000000; 263*c8dee2aaSAndroid Build Coastguard Worker } 264*c8dee2aaSAndroid Build Coastguard Worker } 265*c8dee2aaSAndroid Build Coastguard Worker } 266*c8dee2aaSAndroid Build Coastguard Worker fCheckerboard = bm.asImage(); 267*c8dee2aaSAndroid Build Coastguard Worker } 268*c8dee2aaSAndroid Build Coastguard Worker 269*c8dee2aaSAndroid Build Coastguard Worker // Note: the resulting atlas has transparency makeAtlas()270*c8dee2aaSAndroid Build Coastguard Worker void makeAtlas() { 271*c8dee2aaSAndroid Build Coastguard Worker SkRandom rand; 272*c8dee2aaSAndroid Build Coastguard Worker 273*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[kNumAtlasedX][kNumAtlasedY]; 274*c8dee2aaSAndroid Build Coastguard Worker 275*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kNumAtlasedY; ++y) { 276*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < kNumAtlasedX; ++x) { 277*c8dee2aaSAndroid Build Coastguard Worker colors[x][y] = rand.nextU() | 0xff000000; 278*c8dee2aaSAndroid Build Coastguard Worker fAtlasRects[x][y] = SkIRect::MakeXYWH(kAtlasSpacer + x * (kAtlasCellWidth + kAtlasSpacer), 279*c8dee2aaSAndroid Build Coastguard Worker kAtlasSpacer + y * (kAtlasCellHeight + kAtlasSpacer), 280*c8dee2aaSAndroid Build Coastguard Worker kAtlasCellWidth, 281*c8dee2aaSAndroid Build Coastguard Worker kAtlasCellHeight); 282*c8dee2aaSAndroid Build Coastguard Worker } 283*c8dee2aaSAndroid Build Coastguard Worker } 284*c8dee2aaSAndroid Build Coastguard Worker 285*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm; 286*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(kTotAtlasWidth, kTotAtlasHeight); 287*c8dee2aaSAndroid Build Coastguard Worker 288*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < kTotAtlasHeight; ++y) { 289*c8dee2aaSAndroid Build Coastguard Worker int colorY = y / (kAtlasCellHeight + kAtlasSpacer); 290*c8dee2aaSAndroid Build Coastguard Worker bool inColorY = (y % (kAtlasCellHeight + kAtlasSpacer)) >= kAtlasSpacer; 291*c8dee2aaSAndroid Build Coastguard Worker 292*c8dee2aaSAndroid Build Coastguard Worker SkPMColor* scanline = bm.getAddr32(0, y); 293*c8dee2aaSAndroid Build Coastguard Worker 294*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < kTotAtlasWidth; ++x, ++scanline) { 295*c8dee2aaSAndroid Build Coastguard Worker int colorX = x / (kAtlasCellWidth + kAtlasSpacer); 296*c8dee2aaSAndroid Build Coastguard Worker bool inColorX = (x % (kAtlasCellWidth + kAtlasSpacer)) >= kAtlasSpacer; 297*c8dee2aaSAndroid Build Coastguard Worker 298*c8dee2aaSAndroid Build Coastguard Worker if (inColorX && inColorY) { 299*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(colorX < kNumAtlasedX && colorY < kNumAtlasedY); 300*c8dee2aaSAndroid Build Coastguard Worker *scanline = colors[colorX][colorY]; 301*c8dee2aaSAndroid Build Coastguard Worker } else { 302*c8dee2aaSAndroid Build Coastguard Worker *scanline = 0x00000000; 303*c8dee2aaSAndroid Build Coastguard Worker } 304*c8dee2aaSAndroid Build Coastguard Worker } 305*c8dee2aaSAndroid Build Coastguard Worker } 306*c8dee2aaSAndroid Build Coastguard Worker fAtlas = bm.asImage(); 307*c8dee2aaSAndroid Build Coastguard Worker } 308*c8dee2aaSAndroid Build Coastguard Worker 309*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 310*c8dee2aaSAndroid Build Coastguard Worker }; 311*c8dee2aaSAndroid Build Coastguard Worker 312*c8dee2aaSAndroid Build Coastguard Worker // Partial clear 313*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kScale_Type, GameBench::kPartial_Clear);) 314*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kTranslate_Type, GameBench::kPartial_Clear);) 315*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kTranslate_Type, GameBench::kPartial_Clear, true);) 316*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kRotate_Type, GameBench::kPartial_Clear);) 317*c8dee2aaSAndroid Build Coastguard Worker 318*c8dee2aaSAndroid Build Coastguard Worker // Full clear 319*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kScale_Type, GameBench::kFull_Clear);) 320*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kTranslate_Type, GameBench::kFull_Clear);) 321*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kTranslate_Type, GameBench::kFull_Clear, true);) 322*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kRotate_Type, GameBench::kFull_Clear);) 323*c8dee2aaSAndroid Build Coastguard Worker 324*c8dee2aaSAndroid Build Coastguard Worker // Atlased 325*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench(GameBench::kTranslate_Type, GameBench::kFull_Clear, false, true);) 326*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new GameBench( 327*c8dee2aaSAndroid Build Coastguard Worker GameBench::kTranslate_Type, GameBench::kFull_Clear, false, true, true);) 328*c8dee2aaSAndroid Build Coastguard Worker 329*c8dee2aaSAndroid Build Coastguard Worker 330*c8dee2aaSAndroid Build Coastguard Worker class CanvasMatrixBench : public Benchmark { 331*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 332*c8dee2aaSAndroid Build Coastguard Worker public: 333*c8dee2aaSAndroid Build Coastguard Worker enum Type { 334*c8dee2aaSAndroid Build Coastguard Worker kTranslate_Type, 335*c8dee2aaSAndroid Build Coastguard Worker kScale_Type, 336*c8dee2aaSAndroid Build Coastguard Worker k2x3_Type, 337*c8dee2aaSAndroid Build Coastguard Worker k3x3_Type, 338*c8dee2aaSAndroid Build Coastguard Worker k4x4_Type, 339*c8dee2aaSAndroid Build Coastguard Worker }; 340*c8dee2aaSAndroid Build Coastguard Worker Type fType; 341*c8dee2aaSAndroid Build Coastguard Worker CanvasMatrixBench(Type t)342*c8dee2aaSAndroid Build Coastguard Worker CanvasMatrixBench(Type t) : fType(t) { 343*c8dee2aaSAndroid Build Coastguard Worker fName.set("canvas_matrix"); 344*c8dee2aaSAndroid Build Coastguard Worker switch (fType) { 345*c8dee2aaSAndroid Build Coastguard Worker case kTranslate_Type: fName.append("_trans"); break; 346*c8dee2aaSAndroid Build Coastguard Worker case kScale_Type: fName.append("_scale"); break; 347*c8dee2aaSAndroid Build Coastguard Worker case k2x3_Type: fName.append("_2x3"); break; 348*c8dee2aaSAndroid Build Coastguard Worker case k3x3_Type: fName.append("_3x3"); break; 349*c8dee2aaSAndroid Build Coastguard Worker case k4x4_Type: fName.append("_4x4"); break; 350*c8dee2aaSAndroid Build Coastguard Worker } 351*c8dee2aaSAndroid Build Coastguard Worker } 352*c8dee2aaSAndroid Build Coastguard Worker 353*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()354*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 355*c8dee2aaSAndroid Build Coastguard Worker return fName.c_str(); 356*c8dee2aaSAndroid Build Coastguard Worker } 357*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)358*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 359*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m; 360*c8dee2aaSAndroid Build Coastguard Worker m.setRotate(1); 361*c8dee2aaSAndroid Build Coastguard Worker if (fType == k3x3_Type) { 362*c8dee2aaSAndroid Build Coastguard Worker m[7] = 0.0001f; 363*c8dee2aaSAndroid Build Coastguard Worker } 364*c8dee2aaSAndroid Build Coastguard Worker SkM44 m4(m); 365*c8dee2aaSAndroid Build Coastguard Worker 366*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 367*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 368*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < 10000; ++j) { 369*c8dee2aaSAndroid Build Coastguard Worker switch (fType) { 370*c8dee2aaSAndroid Build Coastguard Worker case kTranslate_Type: canvas->translate(0.0001f, 0.0001f); break; 371*c8dee2aaSAndroid Build Coastguard Worker case kScale_Type: canvas->scale(1.0001f, 0.9999f); break; 372*c8dee2aaSAndroid Build Coastguard Worker case k2x3_Type: canvas->concat(m); break; 373*c8dee2aaSAndroid Build Coastguard Worker case k3x3_Type: canvas->concat(m); break; 374*c8dee2aaSAndroid Build Coastguard Worker case k4x4_Type: canvas->concat(m4); break; 375*c8dee2aaSAndroid Build Coastguard Worker } 376*c8dee2aaSAndroid Build Coastguard Worker } 377*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 378*c8dee2aaSAndroid Build Coastguard Worker } 379*c8dee2aaSAndroid Build Coastguard Worker } 380*c8dee2aaSAndroid Build Coastguard Worker 381*c8dee2aaSAndroid Build Coastguard Worker private: 382*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 383*c8dee2aaSAndroid Build Coastguard Worker }; 384*c8dee2aaSAndroid Build Coastguard Worker 385*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CanvasMatrixBench(CanvasMatrixBench::kTranslate_Type)); 386*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CanvasMatrixBench(CanvasMatrixBench::kScale_Type)); 387*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CanvasMatrixBench(CanvasMatrixBench::k2x3_Type)); 388*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CanvasMatrixBench(CanvasMatrixBench::k3x3_Type)); 389*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new CanvasMatrixBench(CanvasMatrixBench::k4x4_Type)); 390