blob: c1d0e1c0b31ec9c0a0a8e663fa6c3c4f05575495 [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"
scroggo@google.com4a26d9d2012-11-07 18:01:46 +00009#include "CopyTilesRenderer.h"
keyar@chromium.org163b5672012-08-01 17:53:29 +000010#include "PictureBenchmark.h"
scroggo@google.com9a412522012-09-07 15:21:18 +000011#include "SkBenchLogger.h"
reed@google.com006db0f2012-06-27 19:33:29 +000012#include "SkCanvas.h"
scroggo@google.com0a36f432012-09-10 20:29:13 +000013#include "SkGraphics.h"
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000014#include "SkImageDecoder.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000015#include "SkMath.h"
reed@google.com006db0f2012-06-27 19:33:29 +000016#include "SkOSFile.h"
17#include "SkPicture.h"
18#include "SkStream.h"
19#include "SkTArray.h"
20#include "picture_utils.h"
21
borenet@google.com13fd5a12012-09-17 21:10:05 +000022const int DEFAULT_REPEATS = 1;
reed@google.com006db0f2012-06-27 19:33:29 +000023
caryclark@google.coma3622372012-11-06 21:26:13 +000024static char const * const gFilterTypes[] = {
25 "paint",
26 "point",
27 "line",
28 "bitmap",
29 "rect",
30 "path",
31 "text",
32 "all",
33};
34
35static const size_t kFilterTypesCount = sizeof(gFilterTypes) / sizeof(gFilterTypes[0]);
36
37static char const * const gFilterFlags[] = {
38 "antiAlias",
39 "filterBitmap",
40 "dither",
41 "underlineText",
42 "strikeThruText",
43 "fakeBoldText",
44 "linearText",
45 "subpixelText",
46 "devKernText",
47 "LCDRenderText",
48 "embeddedBitmapText",
49 "autoHinting",
50 "verticalText",
51 "genA8FromLCD",
52 "blur",
caryclark@google.come3e940c2012-11-07 16:42:17 +000053 "lowBlur",
caryclark@google.coma3622372012-11-06 21:26:13 +000054 "hinting",
55 "slightHinting",
caryclark@google.come3e940c2012-11-07 16:42:17 +000056 "AAClip",
caryclark@google.coma3622372012-11-06 21:26:13 +000057};
58
59static const size_t kFilterFlagsCount = sizeof(gFilterFlags) / sizeof(gFilterFlags[0]);
60
61static SkString filtersName(sk_tools::PictureRenderer::DrawFilterFlags* drawFilters) {
62 int all = drawFilters[0];
63 size_t tIndex;
64 for (tIndex = 1; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
65 all &= drawFilters[tIndex];
66 }
67 SkString result;
68 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
69 SkString types;
70 if (all & (1 << fIndex)) {
71 types = gFilterTypes[SkDrawFilter::kTypeCount];
72 } else {
73 for (tIndex = 0; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
74 if (drawFilters[tIndex] & (1 << fIndex)) {
75 types += gFilterTypes[tIndex];
76 }
77 }
78 }
79 if (!types.size()) {
80 continue;
81 }
82 result += "_";
83 result += types;
84 result += ".";
85 result += gFilterFlags[fIndex];
86 }
87 return result;
88}
89
90static SkString filterTypesUsage() {
91 SkString result;
92 for (size_t index = 0; index < kFilterTypesCount; ++index) {
93 result += gFilterTypes[index];
94 if (index < kFilterTypesCount - 1) {
95 result += " | ";
96 }
97 }
98 return result;
99}
100
101static SkString filterFlagsUsage() {
102 SkString result;
103 size_t len = 0;
104 for (size_t index = 0; index < kFilterFlagsCount; ++index) {
105 result += gFilterFlags[index];
106 if (result.size() - len >= 72) {
107 result += "\n ";
108 len = result.size();
109 }
110 if (index < kFilterFlagsCount - 1) {
111 result += " | ";
112 }
113 }
114 return result;
115}
116
reed@google.com006db0f2012-06-27 19:33:29 +0000117static void usage(const char* argv0) {
118 SkDebugf("SkPicture benchmarking tool\n");
119 SkDebugf("\n"
120"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000121" %s <inputDir>...\n"
scroggo@google.com5239c322012-09-11 19:15:32 +0000122" [--logFile filename][--timers [wcgWC]*][--logPerIter 1|0][--min]\n"
keyar@chromium.org795cd472012-08-02 18:57:53 +0000123" [--repeat] \n"
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000124" [--mode pow2tile minWidth height | record | simple\n"
125" | tile width height | playbackCreation]\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000126" [--pipe]\n"
junov@chromium.org9313ca42012-11-02 18:11:49 +0000127" [--bbh bbhType]\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000128" [--multi numThreads]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000129" [--device bitmap"
130#if SK_SUPPORT_GPU
131" | gpu"
132#endif
caryclark@google.coma3622372012-11-06 21:26:13 +0000133"]\n"
134" [--filter [%s]:\n [%s]]\n"
135, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
136 SkDebugf("\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000137 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000138" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +0000139" expected to have the .skp extension.\n\n"
140" --logFile filename : destination for writing log output, in addition to stdout.\n");
scroggo@google.com5239c322012-09-11 19:15:32 +0000141 SkDebugf(" --logPerIter 1|0 : "
142 "Log each repeat timer instead of mean, default is disabled.\n");
143 SkDebugf(" --min : Print the minimum times (instead of average).\n");
144 SkDebugf(" --timers [wcgWC]* : "
145 "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000146 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000147" --mode pow2tile minWidth height | copyTile width height | record | simple\n"
148" | tile width height | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000149" Run in the corresponding mode.\n"
150" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000151 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000152" pow2tile minWidth height, Creates tiles with widths\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000153" that are all a power of two\n"
154" such that they minimize the\n"
155" amount of wasted tile space.\n"
156" minWidth is the minimum width\n"
157" of these tiles and must be a\n"
158" power of two. Simple\n"
159" rendering using these tiles\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000160" is benchmarked.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000161 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000162" record, Benchmark picture to picture recording.\n");
163 SkDebugf(
164" simple, Benchmark a simple rendering.\n");
165 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000166" tile width height, Benchmark simple rendering using\n"
167" tiles with the given dimensions.\n"
168" copyTile width height, Draw the picture, then copy it into tiles.\n"
169" Does not support percentages.\n"
170" If the picture is large enough, breaks it into\n"
171" larger tiles (and draws the picture once per\n"
172" larger tile) to avoid creating a large canvas.\n"
173" Add --tiles x y to specify the number of tiles\n"
174" per larger tile in the x and y direction.\n"
175 );
keyar@chromium.org795cd472012-08-02 18:57:53 +0000176 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +0000177" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000178 SkDebugf("\n");
179 SkDebugf(
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000180" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
181" than 1. Only works with tiled rendering.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000182" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000183 SkDebugf(
junov@chromium.org7b537062012-11-06 18:58:43 +0000184" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
185" be used. Accepted values are: none, rtree, grid. Default\n"
186" value is none. Not compatible with --pipe. With value\n"
187" 'grid', width and height must be specified. 'grid' can\n"
188" only be used with modes tile, record, and\n"
189" playbackCreation.");
junov@chromium.org9313ca42012-11-02 18:11:49 +0000190 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000191" --device bitmap"
192#if SK_SUPPORT_GPU
193" | gpu"
194#endif
195": Use the corresponding device. Default is bitmap.\n");
196 SkDebugf(
197" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000198#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000199 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000200" gpu, Render to the GPU.\n");
201#endif
202 SkDebugf("\n");
203 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000204" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +0000205"Set the number of times to repeat each test."
206" Default is %i.\n", DEFAULT_REPEATS);
caryclark@google.coma3622372012-11-06 21:26:13 +0000207 SkDebugf(
caryclark@google.come3e940c2012-11-07 16:42:17 +0000208" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
209" use no blur or low quality blur, or use no hinting or\n"
210" slight hinting. For all flags except AAClip, specify the\n"
211" type of primitive to effect, or choose all. for AAClip\n"
212" alone, the filter affects all clips independent of type.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000213}
214
scroggo@google.com9a412522012-09-07 15:21:18 +0000215SkBenchLogger gLogger;
216
borenet@google.com66bcbd12012-09-17 18:26:06 +0000217static bool run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +0000218 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000219 SkFILEStream inputStream;
220
reed@google.com006db0f2012-06-27 19:33:29 +0000221 inputStream.setPath(inputPath.c_str());
222 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000223 SkString err;
224 err.printf("Could not open file %s\n", inputPath.c_str());
225 gLogger.logError(err);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000226 return false;
reed@google.com006db0f2012-06-27 19:33:29 +0000227 }
228
borenet@google.com66bcbd12012-09-17 18:26:06 +0000229 bool success = false;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000230 SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000231 if (!success) {
232 SkString err;
233 err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
234 gLogger.logError(err);
235 return false;
236 }
reed@google.com006db0f2012-06-27 19:33:29 +0000237
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000238 SkString filename;
239 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000240
241 SkString result;
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000242 result.printf("running bench [%i %i] %s ", picture.width(),
243 picture.height(), filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000244 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000245
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000246 benchmark.run(&picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000247 return true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000248}
249
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000250#define PRINT_USAGE_AND_EXIT \
251 do { \
252 usage(argv0); \
253 exit(-1); \
254 } while (0)
255
keyar@chromium.org163b5672012-08-01 17:53:29 +0000256static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
scroggo@google.com5239c322012-09-11 19:15:32 +0000257 sk_tools::PictureBenchmark* benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000258 const char* argv0 = argv[0];
259 char* const* stop = argv + argc;
260
keyar@chromium.org163b5672012-08-01 17:53:29 +0000261 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000262 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
263 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000264
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000265 SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
scroggo@google.com5239c322012-09-11 19:15:32 +0000266
scroggo@google.com9a412522012-09-07 15:21:18 +0000267 // Create a string to show our current settings.
268 // TODO: Make it prettier. Currently it just repeats the command line.
269 SkString commandLine("bench_pictures:");
270 for (int i = 1; i < argc; i++) {
271 commandLine.appendf(" %s", *(argv+i));
272 }
273 commandLine.append("\n");
274
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000275 bool usePipe = false;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000276 int numThreads = 1;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000277 bool useTiles = false;
278 const char* widthString = NULL;
279 const char* heightString = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000280 int gridWidth = 0;
281 int gridHeight = 0;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000282 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000283 bool isCopyMode = false;
284 const char* xTilesString = NULL;
285 const char* yTilesString = NULL;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000286 const char* mode = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000287 bool gridSupported = false;
skia.committer@gmail.com1aa90cf2012-11-06 13:18:25 +0000288 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
junov@chromium.org9313ca42012-11-02 18:11:49 +0000289 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
caryclark@google.coma3622372012-11-06 21:26:13 +0000290 sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
291 sk_bzero(drawFilters, sizeof(drawFilters));
reed@google.com006db0f2012-06-27 19:33:29 +0000292 for (++argv; argv < stop; ++argv) {
293 if (0 == strcmp(*argv, "--repeat")) {
294 ++argv;
295 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000296 repeats = atoi(*argv);
297 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000298 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000299 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000300 }
301 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000302 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000303 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000304 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000305 } else if (0 == strcmp(*argv, "--pipe")) {
306 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000307 } else if (0 == strcmp(*argv, "--logFile")) {
308 argv++;
309 if (argv < stop) {
310 if (!gLogger.SetLogFile(*argv)) {
311 SkString str;
312 str.printf("Could not open %s for writing.", *argv);
313 gLogger.logError(str);
314 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000315 // TODO(borenet): We're disabling this for now, due to
316 // write-protected Android devices. The very short-term
317 // solution is to ignore the fact that we have no log file.
318 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000319 }
320 } else {
321 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000322 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000323 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000324 } else if (0 == strcmp(*argv, "--multi")) {
325 ++argv;
326 if (argv >= stop) {
327 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000328 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000329 }
330 numThreads = atoi(*argv);
331 if (numThreads < 2) {
332 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000333 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000334 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000335 } else if (0 == strcmp(*argv, "--bbh")) {
336 ++argv;
337 if (argv >= stop) {
338 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000339 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000340 }
341 if (0 == strcmp(*argv, "none")) {
342 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
343 } else if (0 == strcmp(*argv, "rtree")) {
344 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000345 } else if (0 == strcmp(*argv, "grid")) {
346 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
347 ++argv;
348 if (argv >= stop) {
349 gLogger.logError("Missing width for --bbh grid\n");
350 PRINT_USAGE_AND_EXIT;
351 }
352 gridWidth = atoi(*argv);
353 ++argv;
354 if (argv >= stop) {
355 gLogger.logError("Missing height for --bbh grid\n");
356 PRINT_USAGE_AND_EXIT;
357 }
358 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000359 } else {
360 SkString err;
361 err.printf("%s is not a valid value for --bbhType\n", *argv);
362 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000363 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000364 }
365
keyar@chromium.org795cd472012-08-02 18:57:53 +0000366 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000367 if (renderer.get() != NULL) {
368 SkDebugf("Cannot combine modes.\n");
369 PRINT_USAGE_AND_EXIT;
370 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000371
reed@google.com006db0f2012-06-27 19:33:29 +0000372 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000373 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000374 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000375 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000376 }
377
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000378 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000379 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000380 gridSupported = true;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000381 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000382 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000383 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
384 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000385 useTiles = true;
386 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000387
388 if (0 == strcmp(*argv, "pow2tile")) {
389 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000390 } else if (0 == strcmp(*argv, "copyTile")) {
391 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000392 } else {
393 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000394 }
395
keyar@chromium.org795cd472012-08-02 18:57:53 +0000396 ++argv;
397 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000398 SkString err;
399 err.printf("Missing width for --mode %s\n", mode);
400 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000401 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000402 }
403
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000404 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000405 ++argv;
406 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000407 SkString err;
408 err.appendf("Missing height for --mode %s\n", mode);
409 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000410 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000411 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000412 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000413 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000414 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000415 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000416 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
417 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000418 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000419 SkString err;
420 err.printf("%s is not a valid mode for --mode\n", *argv);
421 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000422 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000423 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000424 } else if (0 == strcmp(*argv, "--tiles")) {
425 ++argv;
426 if (argv >= stop) {
427 gLogger.logError("Missing x for --tiles\n");
428 PRINT_USAGE_AND_EXIT;
429 }
430 xTilesString = *argv;
431 ++argv;
432 if (argv >= stop) {
433 gLogger.logError("Missing y for --tiles\n");
434 PRINT_USAGE_AND_EXIT;
435 }
436 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000437 } else if (0 == strcmp(*argv, "--device")) {
438 ++argv;
439 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000440 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000441 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000442 }
443
444 if (0 == strcmp(*argv, "bitmap")) {
445 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
446 }
447#if SK_SUPPORT_GPU
448 else if (0 == strcmp(*argv, "gpu")) {
449 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
450 }
451#endif
452 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000453 SkString err;
454 err.printf("%s is not a valid mode for --device\n", *argv);
455 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000456 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000457 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000458 } else if (0 == strcmp(*argv, "--timers")) {
459 ++argv;
460 if (argv < stop) {
461 bool timerWall = false;
462 bool truncatedTimerWall = false;
463 bool timerCpu = false;
464 bool truncatedTimerCpu = false;
465 bool timerGpu = false;
466 for (char* t = *argv; *t; ++t) {
467 switch (*t) {
468 case 'w':
469 timerWall = true;
470 break;
471 case 'c':
472 timerCpu = true;
473 break;
474 case 'W':
475 truncatedTimerWall = true;
476 break;
477 case 'C':
478 truncatedTimerCpu = true;
479 break;
480 case 'g':
481 timerGpu = true;
482 break;
483 default: {
484 break;
485 }
486 }
487 }
488 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
489 truncatedTimerCpu, timerGpu);
490 } else {
491 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000492 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000493 }
494 } else if (0 == strcmp(*argv, "--min")) {
495 benchmark->setPrintMin(true);
496 } else if (0 == strcmp(*argv, "--logPerIter")) {
497 ++argv;
498 if (argv < stop) {
499 bool log = atoi(*argv) != 0;
500 benchmark->setLogPerIter(log);
501 } else {
502 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000503 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000504 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000505 } else if (0 == strcmp(*argv, "--filter")) {
506 ++argv;
507 if (argv < stop) {
508 const char* colon = strchr(*argv, ':');
509 if (colon) {
510 int type = -1;
511 size_t typeLen = colon - *argv;
512 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
513 if (typeLen == strlen(gFilterTypes[tIndex])
514 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
515 type = tIndex;
516 break;
517 }
518 }
519 if (type < 0) {
520 SkString err;
521 err.printf("Unknown type for --filter %s\n", *argv);
522 gLogger.logError(err);
523 PRINT_USAGE_AND_EXIT;
524 }
525 int flag = -1;
526 size_t flagLen = strlen(*argv) - typeLen - 1;
527 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
528 if (flagLen == strlen(gFilterFlags[fIndex])
529 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
530 flag = 1 << fIndex;
531 break;
532 }
533 }
534 if (flag < 0) {
535 SkString err;
536 err.printf("Unknown flag for --filter %s\n", *argv);
537 gLogger.logError(err);
538 PRINT_USAGE_AND_EXIT;
539 }
540 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
541 if (type != SkDrawFilter::kTypeCount && index != type) {
542 continue;
543 }
544 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
545 (drawFilters[index] | flag);
546 }
547 } else {
548 SkString err;
549 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
550 gLogger.logError(err);
551 PRINT_USAGE_AND_EXIT;
552 }
553 } else {
554 gLogger.logError("Missing arg for --filter\n");
555 PRINT_USAGE_AND_EXIT;
556 }
reed@google.com006db0f2012-06-27 19:33:29 +0000557 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000558 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000559 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000560 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000561 }
562 }
563
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000564 if (numThreads > 1 && !useTiles) {
565 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000566 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000567 }
568
junov@chromium.org9313ca42012-11-02 18:11:49 +0000569 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
570 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000571 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000572 }
573
junov@chromium.org7b537062012-11-06 18:58:43 +0000574 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
575 !gridSupported) {
576 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
577 PRINT_USAGE_AND_EXIT;
578 }
579
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000580 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000581 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000582 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000583 if (isCopyMode) {
584 int x, y;
585 if (xTilesString != NULL) {
586 SkASSERT(yTilesString != NULL);
587 x = atoi(xTilesString);
588 y = atoi(yTilesString);
589 if (x <= 0 || y <= 0) {
590 gLogger.logError("--tiles must be given values > 0\n");
591 PRINT_USAGE_AND_EXIT;
592 }
593 } else {
594 x = y = 4;
595 }
596 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
597 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000598 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
599 } else {
600 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
601 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000602 if (isPowerOf2Mode) {
603 int minWidth = atoi(widthString);
604 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000605 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000606 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000607 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000608 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000609 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000610 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000611 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000612 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000613 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000614 if (isCopyMode) {
615 tiledRenderer->unref();
616 SkString err;
617 err.printf("--mode %s does not support percentages.\n", mode);
618 gLogger.logError(err.c_str());
619 PRINT_USAGE_AND_EXIT;
620 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000621 tiledRenderer->setTileWidthPercentage(atof(widthString));
622 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
623 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000624 SkString err;
625 err.appendf("--mode %s must be given a width percentage > 0\n", mode);
626 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000627 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000628 }
629 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000630 tiledRenderer->setTileWidth(atoi(widthString));
631 if (!(tiledRenderer->getTileWidth() > 0)) {
632 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000633 SkString err;
634 err.appendf("--mode %s must be given a width > 0\n", mode);
635 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000636 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000637 }
638 }
639
640 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000641 if (isCopyMode) {
642 tiledRenderer->unref();
643 SkString err;
644 err.printf("--mode %s does not support percentages.\n", mode);
645 gLogger.logError(err.c_str());
646 PRINT_USAGE_AND_EXIT;
647 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000648 tiledRenderer->setTileHeightPercentage(atof(heightString));
649 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
650 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000651 SkString err;
652 err.appendf("--mode %s must be given a height percentage > 0\n", mode);
653 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000654 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000655 }
656 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000657 tiledRenderer->setTileHeight(atoi(heightString));
658 if (!(tiledRenderer->getTileHeight() > 0)) {
659 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000660 SkString err;
661 err.appendf("--mode %s must be given a height > 0\n", mode);
662 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000663 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000664 }
665 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000666 if (numThreads > 1) {
667#if SK_SUPPORT_GPU
668 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
669 tiledRenderer->unref();
670 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000671 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000672 }
673#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000674 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000675 renderer.reset(tiledRenderer);
676 if (usePipe) {
677 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
678 "Turning off pipe.\n");
679 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000680 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000681 if (renderer.get() != NULL) {
682 SkDebugf("Pipe is incompatible with other modes.\n");
683 PRINT_USAGE_AND_EXIT;
684 }
685 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000686 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000687 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000688 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000689 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000690
scroggo@google.com5239c322012-09-11 19:15:32 +0000691 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000692 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000693 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000694
695 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000696 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000697 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000698 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000699 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000700 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000701 benchmark->setLogger(&gLogger);
702 // Report current settings:
703 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000704}
reed@google.com006db0f2012-06-27 19:33:29 +0000705
borenet@google.com66bcbd12012-09-17 18:26:06 +0000706static int process_input(const SkString& input,
707 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000708 SkOSFile::Iter iter(input.c_str(), "skp");
709 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000710 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000711 if (iter.next(&inputFilename)) {
712 do {
713 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000714 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000715 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000716 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000717 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000718 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000719 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
720 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000721 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000722 }
723 } else {
724 SkString warning;
725 warning.printf("Warning: skipping %s\n", input.c_str());
726 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000727 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000728 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000729}
730
caryclark@google.com5987f582012-10-02 18:33:14 +0000731int tool_main(int argc, char** argv);
732int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000733#ifdef SK_ENABLE_INST_COUNT
734 gPrintInstCount = true;
735#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000736 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000737
scroggo@google.com5239c322012-09-11 19:15:32 +0000738 SkTArray<SkString> inputs;
739 sk_tools::PictureBenchmark benchmark;
740
741 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000742
borenet@google.com66bcbd12012-09-17 18:26:06 +0000743 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000744 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000745 failures += process_input(inputs[i], benchmark);
746 }
747
748 if (failures != 0) {
749 SkString err;
750 err.printf("Failed to run %i benchmarks.\n", failures);
751 gLogger.logError(err);
752 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000753 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000754 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000755}
caryclark@google.com5987f582012-10-02 18:33:14 +0000756
757#if !defined SK_BUILD_FOR_IOS
758int main(int argc, char * const argv[]) {
759 return tool_main(argc, (char**) argv);
760}
761#endif