xref: /aosp_15_r20/external/skia/bench/GameBench.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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