blob: acbe747c8b1ecf61d3f4a6347e528b2771153825 [file] [log] [blame]
reed@google.com006db0f2012-06-27 19:33:29 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "BenchTimer.h"
keyar@chromium.org163b5672012-08-01 17:53:29 +00009#include "PictureBenchmark.h"
scroggo@google.com9a412522012-09-07 15:21:18 +000010#include "SkBenchLogger.h"
reed@google.com006db0f2012-06-27 19:33:29 +000011#include "SkCanvas.h"
scroggo@google.com0a36f432012-09-10 20:29:13 +000012#include "SkGraphics.h"
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000013#include "SkImageDecoder.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000014#include "SkMath.h"
reed@google.com006db0f2012-06-27 19:33:29 +000015#include "SkOSFile.h"
16#include "SkPicture.h"
17#include "SkStream.h"
18#include "SkTArray.h"
19#include "picture_utils.h"
20
borenet@google.com13fd5a12012-09-17 21:10:05 +000021const int DEFAULT_REPEATS = 1;
reed@google.com006db0f2012-06-27 19:33:29 +000022
caryclark@google.coma3622372012-11-06 21:26:13 +000023static char const * const gFilterTypes[] = {
24 "paint",
25 "point",
26 "line",
27 "bitmap",
28 "rect",
29 "path",
30 "text",
31 "all",
32};
33
34static const size_t kFilterTypesCount = sizeof(gFilterTypes) / sizeof(gFilterTypes[0]);
35
36static char const * const gFilterFlags[] = {
37 "antiAlias",
38 "filterBitmap",
39 "dither",
40 "underlineText",
41 "strikeThruText",
42 "fakeBoldText",
43 "linearText",
44 "subpixelText",
45 "devKernText",
46 "LCDRenderText",
47 "embeddedBitmapText",
48 "autoHinting",
49 "verticalText",
50 "genA8FromLCD",
51 "blur",
caryclark@google.come3e940c2012-11-07 16:42:17 +000052 "lowBlur",
caryclark@google.coma3622372012-11-06 21:26:13 +000053 "hinting",
54 "slightHinting",
caryclark@google.come3e940c2012-11-07 16:42:17 +000055 "AAClip",
caryclark@google.coma3622372012-11-06 21:26:13 +000056};
57
58static const size_t kFilterFlagsCount = sizeof(gFilterFlags) / sizeof(gFilterFlags[0]);
59
60static SkString filtersName(sk_tools::PictureRenderer::DrawFilterFlags* drawFilters) {
61 int all = drawFilters[0];
62 size_t tIndex;
63 for (tIndex = 1; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
64 all &= drawFilters[tIndex];
65 }
66 SkString result;
67 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
68 SkString types;
69 if (all & (1 << fIndex)) {
70 types = gFilterTypes[SkDrawFilter::kTypeCount];
71 } else {
72 for (tIndex = 0; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
73 if (drawFilters[tIndex] & (1 << fIndex)) {
74 types += gFilterTypes[tIndex];
75 }
76 }
77 }
78 if (!types.size()) {
79 continue;
80 }
81 result += "_";
82 result += types;
83 result += ".";
84 result += gFilterFlags[fIndex];
85 }
86 return result;
87}
88
89static SkString filterTypesUsage() {
90 SkString result;
91 for (size_t index = 0; index < kFilterTypesCount; ++index) {
92 result += gFilterTypes[index];
93 if (index < kFilterTypesCount - 1) {
94 result += " | ";
95 }
96 }
97 return result;
98}
99
100static SkString filterFlagsUsage() {
101 SkString result;
102 size_t len = 0;
103 for (size_t index = 0; index < kFilterFlagsCount; ++index) {
104 result += gFilterFlags[index];
105 if (result.size() - len >= 72) {
106 result += "\n ";
107 len = result.size();
108 }
109 if (index < kFilterFlagsCount - 1) {
110 result += " | ";
111 }
112 }
113 return result;
114}
115
reed@google.com006db0f2012-06-27 19:33:29 +0000116static void usage(const char* argv0) {
117 SkDebugf("SkPicture benchmarking tool\n");
118 SkDebugf("\n"
119"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000120" %s <inputDir>...\n"
scroggo@google.com5239c322012-09-11 19:15:32 +0000121" [--logFile filename][--timers [wcgWC]*][--logPerIter 1|0][--min]\n"
keyar@chromium.org795cd472012-08-02 18:57:53 +0000122" [--repeat] \n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000123" [--mode pow2tile minWidth height[] | record | simple\n"
124" | tile width[] height[] | playbackCreation]\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000125" [--pipe]\n"
junov@chromium.org9313ca42012-11-02 18:11:49 +0000126" [--bbh bbhType]\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000127" [--multi numThreads]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000128" [--device bitmap"
129#if SK_SUPPORT_GPU
130" | gpu"
131#endif
caryclark@google.coma3622372012-11-06 21:26:13 +0000132"]\n"
133" [--filter [%s]:\n [%s]]\n"
134, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
135 SkDebugf("\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000136 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000137" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +0000138" expected to have the .skp extension.\n\n"
139" --logFile filename : destination for writing log output, in addition to stdout.\n");
scroggo@google.com5239c322012-09-11 19:15:32 +0000140 SkDebugf(" --logPerIter 1|0 : "
141 "Log each repeat timer instead of mean, default is disabled.\n");
142 SkDebugf(" --min : Print the minimum times (instead of average).\n");
143 SkDebugf(" --timers [wcgWC]* : "
144 "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000145 SkDebugf(
caryclark@google.coma3622372012-11-06 21:26:13 +0000146" --mode pow2tile minWidth height[] | record | simple\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000147" | tile width[] height[] | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000148" Run in the corresponding mode.\n"
149" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000150 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000151" pow2tile minWidth height[], Creates tiles with widths\n"
152" that are all a power of two\n"
153" such that they minimize the\n"
154" amount of wasted tile space.\n"
155" minWidth is the minimum width\n"
156" of these tiles and must be a\n"
157" power of two. Simple\n"
158" rendering using these tiles\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000159" is benchmarked.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000160 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000161" record, Benchmark picture to picture recording.\n");
162 SkDebugf(
163" simple, Benchmark a simple rendering.\n");
164 SkDebugf(
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000165" tile width[] height[], Benchmark simple rendering using\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000166" tiles with the given dimensions.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000167 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +0000168" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000169 SkDebugf("\n");
170 SkDebugf(
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000171" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
172" than 1. Only works with tiled rendering.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000173" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000174 SkDebugf(
junov@chromium.org7b537062012-11-06 18:58:43 +0000175" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
176" be used. Accepted values are: none, rtree, grid. Default\n"
177" value is none. Not compatible with --pipe. With value\n"
178" 'grid', width and height must be specified. 'grid' can\n"
179" only be used with modes tile, record, and\n"
180" playbackCreation.");
junov@chromium.org9313ca42012-11-02 18:11:49 +0000181 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000182" --device bitmap"
183#if SK_SUPPORT_GPU
184" | gpu"
185#endif
186": Use the corresponding device. Default is bitmap.\n");
187 SkDebugf(
188" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000189#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000190 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000191" gpu, Render to the GPU.\n");
192#endif
193 SkDebugf("\n");
194 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000195" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +0000196"Set the number of times to repeat each test."
197" Default is %i.\n", DEFAULT_REPEATS);
caryclark@google.coma3622372012-11-06 21:26:13 +0000198 SkDebugf(
caryclark@google.come3e940c2012-11-07 16:42:17 +0000199" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
200" use no blur or low quality blur, or use no hinting or\n"
201" slight hinting. For all flags except AAClip, specify the\n"
202" type of primitive to effect, or choose all. for AAClip\n"
203" alone, the filter affects all clips independent of type.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000204}
205
scroggo@google.com9a412522012-09-07 15:21:18 +0000206SkBenchLogger gLogger;
207
borenet@google.com66bcbd12012-09-17 18:26:06 +0000208static bool run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +0000209 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000210 SkFILEStream inputStream;
211
reed@google.com006db0f2012-06-27 19:33:29 +0000212 inputStream.setPath(inputPath.c_str());
213 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000214 SkString err;
215 err.printf("Could not open file %s\n", inputPath.c_str());
216 gLogger.logError(err);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000217 return false;
reed@google.com006db0f2012-06-27 19:33:29 +0000218 }
219
borenet@google.com66bcbd12012-09-17 18:26:06 +0000220 bool success = false;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000221 SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000222 if (!success) {
223 SkString err;
224 err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
225 gLogger.logError(err);
226 return false;
227 }
reed@google.com006db0f2012-06-27 19:33:29 +0000228
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000229 SkString filename;
230 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000231
232 SkString result;
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000233 result.printf("running bench [%i %i] %s ", picture.width(),
234 picture.height(), filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000235 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000236
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000237 benchmark.run(&picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000238 return true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000239}
240
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000241#define PRINT_USAGE_AND_EXIT \
242 do { \
243 usage(argv0); \
244 exit(-1); \
245 } while (0)
246
keyar@chromium.org163b5672012-08-01 17:53:29 +0000247static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
scroggo@google.com5239c322012-09-11 19:15:32 +0000248 sk_tools::PictureBenchmark* benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000249 const char* argv0 = argv[0];
250 char* const* stop = argv + argc;
251
keyar@chromium.org163b5672012-08-01 17:53:29 +0000252 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000253 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
254 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000255
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000256 SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
scroggo@google.com5239c322012-09-11 19:15:32 +0000257
scroggo@google.com9a412522012-09-07 15:21:18 +0000258 // Create a string to show our current settings.
259 // TODO: Make it prettier. Currently it just repeats the command line.
260 SkString commandLine("bench_pictures:");
261 for (int i = 1; i < argc; i++) {
262 commandLine.appendf(" %s", *(argv+i));
263 }
264 commandLine.append("\n");
265
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000266 bool usePipe = false;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000267 int numThreads = 1;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000268 bool useTiles = false;
269 const char* widthString = NULL;
270 const char* heightString = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000271 int gridWidth = 0;
272 int gridHeight = 0;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000273 bool isPowerOf2Mode = false;
274 const char* mode = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000275 bool gridSupported = false;
skia.committer@gmail.com1aa90cf2012-11-06 13:18:25 +0000276 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
junov@chromium.org9313ca42012-11-02 18:11:49 +0000277 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
caryclark@google.coma3622372012-11-06 21:26:13 +0000278 sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
279 sk_bzero(drawFilters, sizeof(drawFilters));
reed@google.com006db0f2012-06-27 19:33:29 +0000280 for (++argv; argv < stop; ++argv) {
281 if (0 == strcmp(*argv, "--repeat")) {
282 ++argv;
283 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000284 repeats = atoi(*argv);
285 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000286 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000287 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000288 }
289 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000290 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000291 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000292 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000293 } else if (0 == strcmp(*argv, "--pipe")) {
294 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000295 } else if (0 == strcmp(*argv, "--logFile")) {
296 argv++;
297 if (argv < stop) {
298 if (!gLogger.SetLogFile(*argv)) {
299 SkString str;
300 str.printf("Could not open %s for writing.", *argv);
301 gLogger.logError(str);
302 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000303 // TODO(borenet): We're disabling this for now, due to
304 // write-protected Android devices. The very short-term
305 // solution is to ignore the fact that we have no log file.
306 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000307 }
308 } else {
309 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000310 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000311 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000312 } else if (0 == strcmp(*argv, "--multi")) {
313 ++argv;
314 if (argv >= stop) {
315 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000316 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000317 }
318 numThreads = atoi(*argv);
319 if (numThreads < 2) {
320 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000321 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000322 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000323 } else if (0 == strcmp(*argv, "--bbh")) {
324 ++argv;
325 if (argv >= stop) {
326 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000327 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000328 }
329 if (0 == strcmp(*argv, "none")) {
330 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
331 } else if (0 == strcmp(*argv, "rtree")) {
332 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000333 } else if (0 == strcmp(*argv, "grid")) {
334 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
335 ++argv;
336 if (argv >= stop) {
337 gLogger.logError("Missing width for --bbh grid\n");
338 PRINT_USAGE_AND_EXIT;
339 }
340 gridWidth = atoi(*argv);
341 ++argv;
342 if (argv >= stop) {
343 gLogger.logError("Missing height for --bbh grid\n");
344 PRINT_USAGE_AND_EXIT;
345 }
346 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000347 } else {
348 SkString err;
349 err.printf("%s is not a valid value for --bbhType\n", *argv);
350 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000351 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000352 }
353
keyar@chromium.org795cd472012-08-02 18:57:53 +0000354 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000355 if (renderer.get() != NULL) {
356 SkDebugf("Cannot combine modes.\n");
357 PRINT_USAGE_AND_EXIT;
358 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000359
reed@google.com006db0f2012-06-27 19:33:29 +0000360 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000361 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000362 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000363 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000364 }
365
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000366 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000367 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000368 gridSupported = true;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000369 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000370 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000371 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000372 useTiles = true;
373 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000374
375 if (0 == strcmp(*argv, "pow2tile")) {
376 isPowerOf2Mode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000377 } else {
378 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000379 }
380
keyar@chromium.org795cd472012-08-02 18:57:53 +0000381 ++argv;
382 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000383 SkString err;
384 err.printf("Missing width for --mode %s\n", mode);
385 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000386 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000387 }
388
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000389 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000390 ++argv;
391 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000392 gLogger.logError("Missing height for --mode tile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000393 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000394 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000395 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000396 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000397 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000398 gridSupported = true;
reed@google.com006db0f2012-06-27 19:33:29 +0000399 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000400 SkString err;
401 err.printf("%s is not a valid mode for --mode\n", *argv);
402 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000403 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000404 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000405 } else if (0 == strcmp(*argv, "--device")) {
406 ++argv;
407 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000408 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000409 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000410 }
411
412 if (0 == strcmp(*argv, "bitmap")) {
413 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
414 }
415#if SK_SUPPORT_GPU
416 else if (0 == strcmp(*argv, "gpu")) {
417 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
418 }
419#endif
420 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000421 SkString err;
422 err.printf("%s is not a valid mode for --device\n", *argv);
423 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000424 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000425 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000426 } else if (0 == strcmp(*argv, "--timers")) {
427 ++argv;
428 if (argv < stop) {
429 bool timerWall = false;
430 bool truncatedTimerWall = false;
431 bool timerCpu = false;
432 bool truncatedTimerCpu = false;
433 bool timerGpu = false;
434 for (char* t = *argv; *t; ++t) {
435 switch (*t) {
436 case 'w':
437 timerWall = true;
438 break;
439 case 'c':
440 timerCpu = true;
441 break;
442 case 'W':
443 truncatedTimerWall = true;
444 break;
445 case 'C':
446 truncatedTimerCpu = true;
447 break;
448 case 'g':
449 timerGpu = true;
450 break;
451 default: {
452 break;
453 }
454 }
455 }
456 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
457 truncatedTimerCpu, timerGpu);
458 } else {
459 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000460 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000461 }
462 } else if (0 == strcmp(*argv, "--min")) {
463 benchmark->setPrintMin(true);
464 } else if (0 == strcmp(*argv, "--logPerIter")) {
465 ++argv;
466 if (argv < stop) {
467 bool log = atoi(*argv) != 0;
468 benchmark->setLogPerIter(log);
469 } else {
470 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000471 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000472 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000473 } else if (0 == strcmp(*argv, "--filter")) {
474 ++argv;
475 if (argv < stop) {
476 const char* colon = strchr(*argv, ':');
477 if (colon) {
478 int type = -1;
479 size_t typeLen = colon - *argv;
480 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
481 if (typeLen == strlen(gFilterTypes[tIndex])
482 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
483 type = tIndex;
484 break;
485 }
486 }
487 if (type < 0) {
488 SkString err;
489 err.printf("Unknown type for --filter %s\n", *argv);
490 gLogger.logError(err);
491 PRINT_USAGE_AND_EXIT;
492 }
493 int flag = -1;
494 size_t flagLen = strlen(*argv) - typeLen - 1;
495 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
496 if (flagLen == strlen(gFilterFlags[fIndex])
497 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
498 flag = 1 << fIndex;
499 break;
500 }
501 }
502 if (flag < 0) {
503 SkString err;
504 err.printf("Unknown flag for --filter %s\n", *argv);
505 gLogger.logError(err);
506 PRINT_USAGE_AND_EXIT;
507 }
508 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
509 if (type != SkDrawFilter::kTypeCount && index != type) {
510 continue;
511 }
512 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
513 (drawFilters[index] | flag);
514 }
515 } else {
516 SkString err;
517 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
518 gLogger.logError(err);
519 PRINT_USAGE_AND_EXIT;
520 }
521 } else {
522 gLogger.logError("Missing arg for --filter\n");
523 PRINT_USAGE_AND_EXIT;
524 }
reed@google.com006db0f2012-06-27 19:33:29 +0000525 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000526 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000527 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000528 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000529 }
530 }
531
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000532 if (numThreads > 1 && !useTiles) {
533 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000534 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000535 }
536
junov@chromium.org9313ca42012-11-02 18:11:49 +0000537 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
538 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000539 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000540 }
541
junov@chromium.org7b537062012-11-06 18:58:43 +0000542 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
543 !gridSupported) {
544 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
545 PRINT_USAGE_AND_EXIT;
546 }
547
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000548 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000549 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000550 sk_tools::TiledPictureRenderer* tiledRenderer;
551 if (numThreads > 1) {
552 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
553 } else {
554 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
555 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000556 if (isPowerOf2Mode) {
557 int minWidth = atoi(widthString);
558 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000559 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000560 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000561 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000562 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000563 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000564 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000565 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000566 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000567 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000568 tiledRenderer->setTileWidthPercentage(atof(widthString));
569 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
570 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000571 gLogger.logError("--mode tile must be given a width percentage > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000572 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000573 }
574 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000575 tiledRenderer->setTileWidth(atoi(widthString));
576 if (!(tiledRenderer->getTileWidth() > 0)) {
577 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000578 gLogger.logError("--mode tile must be given a width > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000579 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000580 }
581 }
582
583 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000584 tiledRenderer->setTileHeightPercentage(atof(heightString));
585 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
586 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000587 gLogger.logError("--mode tile must be given a height percentage > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000588 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000589 }
590 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000591 tiledRenderer->setTileHeight(atoi(heightString));
592 if (!(tiledRenderer->getTileHeight() > 0)) {
593 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000594 gLogger.logError("--mode tile must be given a height > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000595 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000596 }
597 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000598 if (numThreads > 1) {
599#if SK_SUPPORT_GPU
600 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
601 tiledRenderer->unref();
602 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000603 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000604 }
605#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000606 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000607 renderer.reset(tiledRenderer);
608 if (usePipe) {
609 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
610 "Turning off pipe.\n");
611 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000612 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000613 if (renderer.get() != NULL) {
614 SkDebugf("Pipe is incompatible with other modes.\n");
615 PRINT_USAGE_AND_EXIT;
616 }
617 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000618 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000619 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000620 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000621 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000622
scroggo@google.com5239c322012-09-11 19:15:32 +0000623 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000624 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000625 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000626
627 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000628 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000629 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000630 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000631 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000632 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000633 benchmark->setLogger(&gLogger);
634 // Report current settings:
635 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000636}
reed@google.com006db0f2012-06-27 19:33:29 +0000637
borenet@google.com66bcbd12012-09-17 18:26:06 +0000638static int process_input(const SkString& input,
639 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000640 SkOSFile::Iter iter(input.c_str(), "skp");
641 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000642 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000643 if (iter.next(&inputFilename)) {
644 do {
645 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000646 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000647 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000648 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000649 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000650 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000651 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
652 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000653 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000654 }
655 } else {
656 SkString warning;
657 warning.printf("Warning: skipping %s\n", input.c_str());
658 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000659 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000660 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000661}
662
caryclark@google.com5987f582012-10-02 18:33:14 +0000663int tool_main(int argc, char** argv);
664int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000665#ifdef SK_ENABLE_INST_COUNT
666 gPrintInstCount = true;
667#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000668 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000669
scroggo@google.com5239c322012-09-11 19:15:32 +0000670 SkTArray<SkString> inputs;
671 sk_tools::PictureBenchmark benchmark;
672
673 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000674
borenet@google.com66bcbd12012-09-17 18:26:06 +0000675 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000676 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000677 failures += process_input(inputs[i], benchmark);
678 }
679
680 if (failures != 0) {
681 SkString err;
682 err.printf("Failed to run %i benchmarks.\n", failures);
683 gLogger.logError(err);
684 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000685 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000686 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000687}
caryclark@google.com5987f582012-10-02 18:33:14 +0000688
689#if !defined SK_BUILD_FOR_IOS
690int main(int argc, char * const argv[]) {
691 return tool_main(argc, (char**) argv);
692}
693#endif