blob: 0625174358f0940b93c64a89d88179e2840b2653 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.combd700c32009-01-05 03:34:50 +00008#include "SkCanvas.h"
reed@android.comf523e252009-01-26 23:15:37 +00009#include "SkColorPriv.h"
reed@android.com3a859a02009-01-28 00:56:29 +000010#include "SkGraphics.h"
reed@android.comb398fe82009-01-07 11:47:57 +000011#include "SkImageEncoder.h"
reed@android.com6c924ad2009-03-31 03:48:49 +000012#include "SkNWayCanvas.h"
13#include "SkPicture.h"
reed@android.combd700c32009-01-05 03:34:50 +000014#include "SkString.h"
mike@reedtribe.orga9015f82011-05-17 02:25:05 +000015#include "GrContext.h"
16#include "SkGpuDevice.h"
17#include "SkEGLContext.h"
reed@android.combd700c32009-01-05 03:34:50 +000018
19#include "SkBenchmark.h"
bungeman@google.combe9ad4e2011-06-07 19:16:02 +000020#include "BenchTimer.h"
reed@android.combd700c32009-01-05 03:34:50 +000021
reed@android.com29348cb2009-08-04 18:17:15 +000022#ifdef ANDROID
23static void log_error(const char msg[]) { SkDebugf("%s", msg); }
24static void log_progress(const char msg[]) { SkDebugf("%s", msg); }
25#else
26static void log_error(const char msg[]) { fprintf(stderr, "%s", msg); }
27static void log_progress(const char msg[]) { printf("%s", msg); }
28#endif
29
30static void log_error(const SkString& str) { log_error(str.c_str()); }
31static void log_progress(const SkString& str) { log_progress(str.c_str()); }
32
33///////////////////////////////////////////////////////////////////////////////
34
reed@android.com6c924ad2009-03-31 03:48:49 +000035static void erase(SkBitmap& bm) {
36 if (bm.config() == SkBitmap::kA8_Config) {
37 bm.eraseColor(0);
38 } else {
39 bm.eraseColor(SK_ColorWHITE);
40 }
41}
42
mike@reedtribe.orga9015f82011-05-17 02:25:05 +000043#if 0
reed@android.com6c924ad2009-03-31 03:48:49 +000044static bool equal(const SkBitmap& bm1, const SkBitmap& bm2) {
45 if (bm1.width() != bm2.width() ||
46 bm1.height() != bm2.height() ||
47 bm1.config() != bm2.config()) {
48 return false;
49 }
50
51 size_t pixelBytes = bm1.width() * bm1.bytesPerPixel();
52 for (int y = 0; y < bm1.height(); y++) {
53 if (memcmp(bm1.getAddr(0, y), bm2.getAddr(0, y), pixelBytes)) {
54 return false;
55 }
56 }
reed@android.com6c924ad2009-03-31 03:48:49 +000057 return true;
58}
mike@reedtribe.orga9015f82011-05-17 02:25:05 +000059#endif
reed@android.com6c924ad2009-03-31 03:48:49 +000060
reed@android.combd700c32009-01-05 03:34:50 +000061class Iter {
62public:
reed@android.come9d00602009-09-02 21:12:42 +000063 Iter(void* param) {
reed@android.combd700c32009-01-05 03:34:50 +000064 fBench = BenchRegistry::Head();
reed@android.come9d00602009-09-02 21:12:42 +000065 fParam = param;
reed@android.combd700c32009-01-05 03:34:50 +000066 }
67
68 SkBenchmark* next() {
69 if (fBench) {
70 BenchRegistry::Factory f = fBench->factory();
71 fBench = fBench->next();
reed@android.come9d00602009-09-02 21:12:42 +000072 return f(fParam);
reed@android.combd700c32009-01-05 03:34:50 +000073 }
74 return NULL;
75 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +000076
reed@android.combd700c32009-01-05 03:34:50 +000077private:
78 const BenchRegistry* fBench;
reed@android.come9d00602009-09-02 21:12:42 +000079 void* fParam;
reed@android.combd700c32009-01-05 03:34:50 +000080};
81
82static void make_filename(const char name[], SkString* path) {
83 path->set(name);
84 for (int i = 0; name[i]; i++) {
85 switch (name[i]) {
86 case '/':
87 case '\\':
88 case ' ':
89 case ':':
90 path->writable_str()[i] = '-';
91 break;
92 default:
93 break;
94 }
95 }
96}
97
reed@android.com4c7d3d62009-01-21 03:15:13 +000098static void saveFile(const char name[], const char config[], const char dir[],
99 const SkBitmap& bm) {
reed@android.com4c7d3d62009-01-21 03:15:13 +0000100 SkBitmap copy;
101 if (!bm.copyTo(&copy, SkBitmap::kARGB_8888_Config)) {
102 return;
103 }
reed@android.comf523e252009-01-26 23:15:37 +0000104
105 if (bm.config() == SkBitmap::kA8_Config) {
106 // turn alpha into gray-scale
107 size_t size = copy.getSize() >> 2;
108 SkPMColor* p = copy.getAddr32(0, 0);
109 for (size_t i = 0; i < size; i++) {
110 int c = (*p >> SK_A32_SHIFT) & 0xFF;
111 c = 255 - c;
112 c |= (c << 24) | (c << 16) | (c << 8);
113 *p++ = c | (SK_A32_MASK << SK_A32_SHIFT);
114 }
115 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000116
reed@android.com4c7d3d62009-01-21 03:15:13 +0000117 SkString str;
118 make_filename(name, &str);
119 str.appendf("_%s.png", config);
120 str.prepend(dir);
121 ::remove(str.c_str());
122 SkImageEncoder::EncodeFile(str.c_str(), copy, SkImageEncoder::kPNG_Type,
123 100);
reed@android.com4c7d3d62009-01-21 03:15:13 +0000124}
125
126static void performClip(SkCanvas* canvas, int w, int h) {
127 SkRect r;
128
129 r.set(SkIntToScalar(10), SkIntToScalar(10),
130 SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
131 canvas->clipRect(r, SkRegion::kIntersect_Op);
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000132
reed@android.com4c7d3d62009-01-21 03:15:13 +0000133 r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
134 SkIntToScalar(w-10), SkIntToScalar(h-10));
135 canvas->clipRect(r, SkRegion::kXOR_Op);
136}
137
138static void performRotate(SkCanvas* canvas, int w, int h) {
139 const SkScalar x = SkIntToScalar(w) / 2;
140 const SkScalar y = SkIntToScalar(h) / 2;
141
142 canvas->translate(x, y);
143 canvas->rotate(SkIntToScalar(35));
144 canvas->translate(-x, -y);
145}
146
reed@android.com387359e2009-08-04 01:51:09 +0000147static void performScale(SkCanvas* canvas, int w, int h) {
148 const SkScalar x = SkIntToScalar(w) / 2;
149 const SkScalar y = SkIntToScalar(h) / 2;
150
151 canvas->translate(x, y);
152 // just enough so we can't take the sprite case
153 canvas->scale(SK_Scalar1 * 99/100, SK_Scalar1 * 99/100);
154 canvas->translate(-x, -y);
155}
156
reed@android.com29348cb2009-08-04 18:17:15 +0000157static bool parse_bool_arg(char * const* argv, char* const* stop, bool* var) {
158 if (argv < stop) {
159 *var = atoi(*argv) != 0;
160 return true;
161 }
162 return false;
163}
164
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000165enum Backend {
166 kRaster_Backend,
167 kGPU_Backend,
168 kPDF_Backend,
169};
170
171static SkDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
172 Backend backend, GrContext* context) {
173 SkDevice* device = NULL;
174 SkBitmap bitmap;
175 bitmap.setConfig(config, size.fX, size.fY);
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000176
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000177 switch (backend) {
178 case kRaster_Backend:
179 bitmap.allocPixels();
180 erase(bitmap);
reed@google.comaf951c92011-06-16 19:10:39 +0000181 device = new SkDevice(bitmap);
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000182 break;
183 case kGPU_Backend:
reed@google.comaf951c92011-06-16 19:10:39 +0000184 device = new SkGpuDevice(context, SkGpuDevice::Current3DApiRenderTarget());
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000185// device->clear(0xFFFFFFFF);
186 break;
187 case kPDF_Backend:
188 default:
189 SkASSERT(!"unsupported");
190 }
191 return device;
192}
193
reed@android.com4bc19832009-01-19 20:08:35 +0000194static const struct {
195 SkBitmap::Config fConfig;
196 const char* fName;
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000197 Backend fBackend;
reed@android.com4bc19832009-01-19 20:08:35 +0000198} gConfigs[] = {
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000199 { SkBitmap::kARGB_8888_Config, "8888", kRaster_Backend },
200 { SkBitmap::kRGB_565_Config, "565", kRaster_Backend },
201 { SkBitmap::kARGB_8888_Config, "GPU", kGPU_Backend },
reed@android.com4bc19832009-01-19 20:08:35 +0000202};
203
reed@android.com4c7d3d62009-01-21 03:15:13 +0000204static int findConfig(const char config[]) {
205 for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
206 if (!strcmp(config, gConfigs[i].fName)) {
207 return i;
208 }
209 }
210 return -1;
211}
212
reed@android.combd700c32009-01-05 03:34:50 +0000213int main (int argc, char * const argv[]) {
reed@android.com3a859a02009-01-28 00:56:29 +0000214 SkAutoGraphics ag;
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000215
reed@android.come9d00602009-09-02 21:12:42 +0000216 SkTDict<const char*> defineDict(1024);
reed@android.com4bc19832009-01-19 20:08:35 +0000217 int repeatDraw = 1;
218 int forceAlpha = 0xFF;
219 bool forceAA = true;
reed@android.com29348cb2009-08-04 18:17:15 +0000220 bool forceFilter = false;
reed@android.com4e635f92009-10-19 17:39:46 +0000221 SkTriState::State forceDither = SkTriState::kDefault;
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000222 bool timerWall = false;
223 bool timerCpu = true;
224 bool timerGpu = true;
reed@android.com387359e2009-08-04 01:51:09 +0000225 bool doScale = false;
reed@android.com4c7d3d62009-01-21 03:15:13 +0000226 bool doRotate = false;
227 bool doClip = false;
reed@android.com387359e2009-08-04 01:51:09 +0000228 const char* matchStr = NULL;
agl@chromium.org652807b2010-04-27 15:47:34 +0000229 bool hasStrokeWidth = false;
230 float strokeWidth;
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000231
reed@android.comb398fe82009-01-07 11:47:57 +0000232 SkString outDir;
reed@android.com387359e2009-08-04 01:51:09 +0000233 SkBitmap::Config outConfig = SkBitmap::kNo_Config;
234 const char* configName = "";
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000235 Backend backend = kRaster_Backend; // for warning
reed@android.com387359e2009-08-04 01:51:09 +0000236 int configCount = SK_ARRAY_COUNT(gConfigs);
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000237
reed@android.comb398fe82009-01-07 11:47:57 +0000238 char* const* stop = argv + argc;
239 for (++argv; argv < stop; ++argv) {
240 if (strcmp(*argv, "-o") == 0) {
241 argv++;
242 if (argv < stop && **argv) {
243 outDir.set(*argv);
244 if (outDir.c_str()[outDir.size() - 1] != '/') {
245 outDir.append("/");
246 }
247 }
reed@android.com4bc19832009-01-19 20:08:35 +0000248 } else if (strcmp(*argv, "-repeat") == 0) {
249 argv++;
250 if (argv < stop) {
251 repeatDraw = atoi(*argv);
252 if (repeatDraw < 1) {
253 repeatDraw = 1;
254 }
255 } else {
reed@android.com29348cb2009-08-04 18:17:15 +0000256 log_error("missing arg for -repeat\n");
reed@android.com4bc19832009-01-19 20:08:35 +0000257 return -1;
258 }
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000259 } else if (strcmp(*argv, "-timers") == 0) {
260 argv++;
261 if (argv < stop) {
262 timerWall = false;
263 timerCpu = false;
264 timerGpu = false;
265 for (char* t = *argv; *t; ++t) {
266 switch (*t) {
267 case 'w': timerWall = true; break;
268 case 'c': timerCpu = true; break;
269 case 'g': timerGpu = true; break;
270 }
271 }
272 } else {
273 log_error("missing arg for -timers\n");
274 return -1;
275 }
reed@android.com4c7d3d62009-01-21 03:15:13 +0000276 } else if (!strcmp(*argv, "-rotate")) {
277 doRotate = true;
reed@android.com387359e2009-08-04 01:51:09 +0000278 } else if (!strcmp(*argv, "-scale")) {
279 doScale = true;
reed@android.com4c7d3d62009-01-21 03:15:13 +0000280 } else if (!strcmp(*argv, "-clip")) {
281 doClip = true;
reed@android.com4bc19832009-01-19 20:08:35 +0000282 } else if (strcmp(*argv, "-forceAA") == 0) {
reed@android.com29348cb2009-08-04 18:17:15 +0000283 if (!parse_bool_arg(++argv, stop, &forceAA)) {
284 log_error("missing arg for -forceAA\n");
285 return -1;
286 }
287 } else if (strcmp(*argv, "-forceFilter") == 0) {
288 if (!parse_bool_arg(++argv, stop, &forceFilter)) {
289 log_error("missing arg for -forceFilter\n");
290 return -1;
291 }
reed@android.com4e635f92009-10-19 17:39:46 +0000292 } else if (strcmp(*argv, "-forceDither") == 0) {
293 bool tmp;
294 if (!parse_bool_arg(++argv, stop, &tmp)) {
295 log_error("missing arg for -forceDither\n");
296 return -1;
297 }
298 forceDither = tmp ? SkTriState::kTrue : SkTriState::kFalse;
reed@android.com4bc19832009-01-19 20:08:35 +0000299 } else if (strcmp(*argv, "-forceBlend") == 0) {
reed@android.com29348cb2009-08-04 18:17:15 +0000300 bool wantAlpha = false;
301 if (!parse_bool_arg(++argv, stop, &wantAlpha)) {
302 log_error("missing arg for -forceBlend\n");
303 return -1;
304 }
305 forceAlpha = wantAlpha ? 0x80 : 0xFF;
agl@chromium.org652807b2010-04-27 15:47:34 +0000306 } else if (strcmp(*argv, "-strokeWidth") == 0) {
307 argv++;
308 if (argv < stop) {
309 const char *strokeWidthStr = *argv;
310 if (sscanf(strokeWidthStr, "%f", &strokeWidth) != 1) {
311 log_error("bad arg for -strokeWidth\n");
312 return -1;
313 }
314 hasStrokeWidth = true;
315 } else {
316 log_error("missing arg for -strokeWidth\n");
317 return -1;
318 }
reed@android.com387359e2009-08-04 01:51:09 +0000319 } else if (strcmp(*argv, "-match") == 0) {
320 argv++;
321 if (argv < stop) {
322 matchStr = *argv;
323 } else {
reed@android.com29348cb2009-08-04 18:17:15 +0000324 log_error("missing arg for -match\n");
reed@android.com387359e2009-08-04 01:51:09 +0000325 return -1;
reed@android.com4c7d3d62009-01-21 03:15:13 +0000326 }
reed@android.com387359e2009-08-04 01:51:09 +0000327 } else if (strcmp(*argv, "-config") == 0) {
328 argv++;
329 if (argv < stop) {
330 int index = findConfig(*argv);
331 if (index >= 0) {
332 outConfig = gConfigs[index].fConfig;
333 configName = gConfigs[index].fName;
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000334 backend = gConfigs[index].fBackend;
reed@android.com387359e2009-08-04 01:51:09 +0000335 configCount = 1;
336 } else {
reed@android.com29348cb2009-08-04 18:17:15 +0000337 SkString str;
338 str.printf("unrecognized config %s\n", *argv);
339 log_error(str);
reed@android.com387359e2009-08-04 01:51:09 +0000340 return -1;
341 }
342 } else {
reed@android.com29348cb2009-08-04 18:17:15 +0000343 log_error("missing arg for -config\n");
reed@android.com387359e2009-08-04 01:51:09 +0000344 return -1;
345 }
reed@android.com0c9da392010-02-22 19:50:13 +0000346 } else if (strlen(*argv) > 2 && strncmp(*argv, "-D", 2) == 0) {
reed@android.come9d00602009-09-02 21:12:42 +0000347 argv++;
reed@android.com0c9da392010-02-22 19:50:13 +0000348 if (argv < stop) {
reed@android.come9d00602009-09-02 21:12:42 +0000349 defineDict.set(argv[-1] + 2, *argv);
350 } else {
351 log_error("incomplete '-Dfoo bar' definition\n");
352 return -1;
353 }
reed@android.com387359e2009-08-04 01:51:09 +0000354 } else {
reed@android.com29348cb2009-08-04 18:17:15 +0000355 SkString str;
356 str.printf("unrecognized arg %s\n", *argv);
357 log_error(str);
reed@android.com387359e2009-08-04 01:51:09 +0000358 return -1;
reed@android.comb398fe82009-01-07 11:47:57 +0000359 }
360 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000361
reed@google.com3b14dc12011-04-04 14:31:36 +0000362 // report our current settings
363 {
364 SkString str;
bungeman@google.coma5d48412011-06-15 17:25:46 +0000365 str.printf("skia bench: alpha=0x%02X antialias=%d filter=%d",
reed@google.com3b14dc12011-04-04 14:31:36 +0000366 forceAlpha, forceAA, forceFilter);
bungeman@google.coma5d48412011-06-15 17:25:46 +0000367 str.appendf(" rotate=%d scale=%d clip=%d",
368 doRotate, doScale, doClip);
369
370 const char * ditherName;
371 switch (forceDither) {
372 case SkTriState::kDefault: ditherName = "default"; break;
373 case SkTriState::kTrue: ditherName = "true"; break;
374 case SkTriState::kFalse: ditherName = "false"; break;
375 default: ditherName = "<invalid>"; break;
376 }
377 str.appendf(" dither=%s", ditherName);
378
379 if (hasStrokeWidth) {
380 str.appendf(" strokeWidth=%f", strokeWidth);
381 } else {
382 str.append(" strokeWidth=none");
383 }
384
385#if defined(SK_SCALAR_IS_FLOAT)
386 str.append(" scalar=float");
387#elif defined(SK_SCALAR_IS_FIXED)
388 str.append(" scalar=fixed");
389#endif
390
391#if defined(SK_BUILD_FOR_WIN32)
392 str.append(" system=WIN32");
393#elif defined(SK_BUILD_FOR_MAC)
394 str.append(" system=MAC");
395#elif defined(SK_BUILD_FOR_ANDROID)
396 str.append(" system=ANDROID");
397#elif defined(SK_BUILD_FOR_UNIX)
398 str.append(" system=UNIX");
399#else
400 str.append(" system=other");
401#endif
402
403#if defined(SK_DEBUG)
404 str.append(" DEBUG");
405#endif
406 str.append("\n");
reed@google.com3b14dc12011-04-04 14:31:36 +0000407 log_progress(str);
408 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000409
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000410 GrContext* context = NULL;
bungeman@google.coma5d48412011-06-15 17:25:46 +0000411 //Don't do GL when fixed.
412#if !defined(SK_SCALAR_IS_FIXED)
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000413 SkEGLContext eglContext;
414 if (eglContext.init(1024, 1024)) {
415 context = GrContext::CreateGLShaderContext();
416 }
bungeman@google.coma5d48412011-06-15 17:25:46 +0000417#endif
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000418
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000419 BenchTimer timer = BenchTimer();
420
reed@android.come9d00602009-09-02 21:12:42 +0000421 Iter iter(&defineDict);
reed@android.combd700c32009-01-05 03:34:50 +0000422 SkBenchmark* bench;
423 while ((bench = iter.next()) != NULL) {
reed@android.comb398fe82009-01-07 11:47:57 +0000424 SkIPoint dim = bench->getSize();
425 if (dim.fX <= 0 || dim.fY <= 0) {
426 continue;
427 }
reed@android.comb398fe82009-01-07 11:47:57 +0000428
reed@android.com4bc19832009-01-19 20:08:35 +0000429 bench->setForceAlpha(forceAlpha);
430 bench->setForceAA(forceAA);
reed@android.com29348cb2009-08-04 18:17:15 +0000431 bench->setForceFilter(forceFilter);
reed@android.com4e635f92009-10-19 17:39:46 +0000432 bench->setDither(forceDither);
agl@chromium.org652807b2010-04-27 15:47:34 +0000433 if (hasStrokeWidth) {
434 bench->setStrokeWidth(strokeWidth);
435 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000436
reed@android.com387359e2009-08-04 01:51:09 +0000437 // only run benchmarks if their name contains matchStr
438 if (matchStr && strstr(bench->getName(), matchStr) == NULL) {
439 continue;
440 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000441
reed@android.com29348cb2009-08-04 18:17:15 +0000442 {
443 SkString str;
reed@google.comd34658a2011-04-11 13:12:51 +0000444 str.printf("running bench [%d %d] %28s", dim.fX, dim.fY,
reed@android.com0c9da392010-02-22 19:50:13 +0000445 bench->getName());
reed@android.com29348cb2009-08-04 18:17:15 +0000446 log_progress(str);
447 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000448
reed@android.com4bc19832009-01-19 20:08:35 +0000449 for (int configIndex = 0; configIndex < configCount; configIndex++) {
450 if (configCount > 1) {
451 outConfig = gConfigs[configIndex].fConfig;
452 configName = gConfigs[configIndex].fName;
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000453 backend = gConfigs[configIndex].fBackend;
reed@android.com4bc19832009-01-19 20:08:35 +0000454 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000455
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000456 if (kGPU_Backend == backend && NULL == context) {
457 continue;
458 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000459
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000460 SkDevice* device = make_device(outConfig, dim, backend, context);
461 SkCanvas canvas(device);
462 device->unref();
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000463
reed@android.com4c7d3d62009-01-21 03:15:13 +0000464 if (doClip) {
465 performClip(&canvas, dim.fX, dim.fY);
466 }
reed@android.com387359e2009-08-04 01:51:09 +0000467 if (doScale) {
468 performScale(&canvas, dim.fX, dim.fY);
469 }
reed@android.com4c7d3d62009-01-21 03:15:13 +0000470 if (doRotate) {
471 performRotate(&canvas, dim.fX, dim.fY);
472 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000473
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000474 bool gpu = kGPU_Backend == backend && context;
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000475 //warm up caches if needed
reed@android.comeca48362010-12-20 18:34:17 +0000476 if (repeatDraw > 1) {
477 SkAutoCanvasRestore acr(&canvas, true);
478 bench->draw(&canvas);
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000479 if (gpu) {
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000480 context->flush();
481 glFinish();
482 }
reed@android.comeca48362010-12-20 18:34:17 +0000483 }
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000484
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000485 timer.start();
reed@android.com4bc19832009-01-19 20:08:35 +0000486 for (int i = 0; i < repeatDraw; i++) {
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000487 SkAutoCanvasRestore acr(&canvas, true);
488 bench->draw(&canvas);
reed@google.com25df8882011-07-14 19:03:58 +0000489 if (gpu) {
490 context->flush();
491 }
492 }
493 if (gpu) {
494 glFinish();
reed@android.com4bc19832009-01-19 20:08:35 +0000495 }
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000496 timer.end();
bungeman@google.comd1a416a2011-05-18 18:37:07 +0000497
reed@android.com4bc19832009-01-19 20:08:35 +0000498 if (repeatDraw > 1) {
reed@android.com29348cb2009-08-04 18:17:15 +0000499 SkString str;
bungeman@google.combe9ad4e2011-06-07 19:16:02 +0000500 str.printf(" %4s:", configName);
501 if (timerWall) {
502 str.appendf(" msecs = %6.2f", timer.fWall / repeatDraw);
503 }
504 if (timerCpu) {
505 str.appendf(" cmsecs = %6.2f", timer.fCpu / repeatDraw);
506 }
507 if (timerGpu && gpu && timer.fGpu > 0) {
508 str.appendf(" gmsecs = %6.2f", timer.fGpu / repeatDraw);
509 }
reed@android.com29348cb2009-08-04 18:17:15 +0000510 log_progress(str);
reed@android.com4bc19832009-01-19 20:08:35 +0000511 }
reed@android.com4c7d3d62009-01-21 03:15:13 +0000512 if (outDir.size() > 0) {
mike@reedtribe.orga9015f82011-05-17 02:25:05 +0000513 saveFile(bench->getName(), configName, outDir.c_str(),
514 device->accessBitmap(false));
reed@android.com4c7d3d62009-01-21 03:15:13 +0000515 }
reed@android.com4bc19832009-01-19 20:08:35 +0000516 }
reed@android.com29348cb2009-08-04 18:17:15 +0000517 log_progress("\n");
reed@android.combd700c32009-01-05 03:34:50 +0000518 }
519
520 return 0;
521}