blob: 409439e7684d466c36dc142bb28d8f2136a75728 [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.com006db0f2012-06-27 19:33:29 +0000416 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000417 SkString err;
418 err.printf("%s is not a valid mode for --mode\n", *argv);
419 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000420 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000421 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000422 } else if (0 == strcmp(*argv, "--tiles")) {
423 ++argv;
424 if (argv >= stop) {
425 gLogger.logError("Missing x for --tiles\n");
426 PRINT_USAGE_AND_EXIT;
427 }
428 xTilesString = *argv;
429 ++argv;
430 if (argv >= stop) {
431 gLogger.logError("Missing y for --tiles\n");
432 PRINT_USAGE_AND_EXIT;
433 }
434 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000435 } else if (0 == strcmp(*argv, "--device")) {
436 ++argv;
437 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000438 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000439 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000440 }
441
442 if (0 == strcmp(*argv, "bitmap")) {
443 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
444 }
445#if SK_SUPPORT_GPU
446 else if (0 == strcmp(*argv, "gpu")) {
447 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
448 }
449#endif
450 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000451 SkString err;
452 err.printf("%s is not a valid mode for --device\n", *argv);
453 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000454 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000455 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000456 } else if (0 == strcmp(*argv, "--timers")) {
457 ++argv;
458 if (argv < stop) {
459 bool timerWall = false;
460 bool truncatedTimerWall = false;
461 bool timerCpu = false;
462 bool truncatedTimerCpu = false;
463 bool timerGpu = false;
464 for (char* t = *argv; *t; ++t) {
465 switch (*t) {
466 case 'w':
467 timerWall = true;
468 break;
469 case 'c':
470 timerCpu = true;
471 break;
472 case 'W':
473 truncatedTimerWall = true;
474 break;
475 case 'C':
476 truncatedTimerCpu = true;
477 break;
478 case 'g':
479 timerGpu = true;
480 break;
481 default: {
482 break;
483 }
484 }
485 }
486 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
487 truncatedTimerCpu, timerGpu);
488 } else {
489 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000490 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000491 }
492 } else if (0 == strcmp(*argv, "--min")) {
493 benchmark->setPrintMin(true);
494 } else if (0 == strcmp(*argv, "--logPerIter")) {
495 ++argv;
496 if (argv < stop) {
497 bool log = atoi(*argv) != 0;
498 benchmark->setLogPerIter(log);
499 } else {
500 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000501 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000502 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000503 } else if (0 == strcmp(*argv, "--filter")) {
504 ++argv;
505 if (argv < stop) {
506 const char* colon = strchr(*argv, ':');
507 if (colon) {
508 int type = -1;
509 size_t typeLen = colon - *argv;
510 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
511 if (typeLen == strlen(gFilterTypes[tIndex])
512 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
513 type = tIndex;
514 break;
515 }
516 }
517 if (type < 0) {
518 SkString err;
519 err.printf("Unknown type for --filter %s\n", *argv);
520 gLogger.logError(err);
521 PRINT_USAGE_AND_EXIT;
522 }
523 int flag = -1;
524 size_t flagLen = strlen(*argv) - typeLen - 1;
525 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
526 if (flagLen == strlen(gFilterFlags[fIndex])
527 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
528 flag = 1 << fIndex;
529 break;
530 }
531 }
532 if (flag < 0) {
533 SkString err;
534 err.printf("Unknown flag for --filter %s\n", *argv);
535 gLogger.logError(err);
536 PRINT_USAGE_AND_EXIT;
537 }
538 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
539 if (type != SkDrawFilter::kTypeCount && index != type) {
540 continue;
541 }
542 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
543 (drawFilters[index] | flag);
544 }
545 } else {
546 SkString err;
547 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
548 gLogger.logError(err);
549 PRINT_USAGE_AND_EXIT;
550 }
551 } else {
552 gLogger.logError("Missing arg for --filter\n");
553 PRINT_USAGE_AND_EXIT;
554 }
reed@google.com006db0f2012-06-27 19:33:29 +0000555 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000556 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000557 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000558 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000559 }
560 }
561
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000562 if (numThreads > 1 && !useTiles) {
563 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000564 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000565 }
566
junov@chromium.org9313ca42012-11-02 18:11:49 +0000567 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
568 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000569 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000570 }
571
junov@chromium.org7b537062012-11-06 18:58:43 +0000572 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
573 !gridSupported) {
574 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
575 PRINT_USAGE_AND_EXIT;
576 }
577
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000578 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000579 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000580 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000581 if (isCopyMode) {
582 int x, y;
583 if (xTilesString != NULL) {
584 SkASSERT(yTilesString != NULL);
585 x = atoi(xTilesString);
586 y = atoi(yTilesString);
587 if (x <= 0 || y <= 0) {
588 gLogger.logError("--tiles must be given values > 0\n");
589 PRINT_USAGE_AND_EXIT;
590 }
591 } else {
592 x = y = 4;
593 }
594 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
595 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000596 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
597 } else {
598 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
599 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000600 if (isPowerOf2Mode) {
601 int minWidth = atoi(widthString);
602 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000603 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000604 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000605 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000606 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000607 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000608 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000609 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000610 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000611 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000612 if (isCopyMode) {
613 tiledRenderer->unref();
614 SkString err;
615 err.printf("--mode %s does not support percentages.\n", mode);
616 gLogger.logError(err.c_str());
617 PRINT_USAGE_AND_EXIT;
618 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000619 tiledRenderer->setTileWidthPercentage(atof(widthString));
620 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
621 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000622 SkString err;
623 err.appendf("--mode %s must be given a width percentage > 0\n", mode);
624 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000625 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000626 }
627 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000628 tiledRenderer->setTileWidth(atoi(widthString));
629 if (!(tiledRenderer->getTileWidth() > 0)) {
630 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000631 SkString err;
632 err.appendf("--mode %s must be given a width > 0\n", mode);
633 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000634 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000635 }
636 }
637
638 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000639 if (isCopyMode) {
640 tiledRenderer->unref();
641 SkString err;
642 err.printf("--mode %s does not support percentages.\n", mode);
643 gLogger.logError(err.c_str());
644 PRINT_USAGE_AND_EXIT;
645 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000646 tiledRenderer->setTileHeightPercentage(atof(heightString));
647 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
648 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000649 SkString err;
650 err.appendf("--mode %s must be given a height percentage > 0\n", mode);
651 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000652 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000653 }
654 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000655 tiledRenderer->setTileHeight(atoi(heightString));
656 if (!(tiledRenderer->getTileHeight() > 0)) {
657 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000658 SkString err;
659 err.appendf("--mode %s must be given a height > 0\n", mode);
660 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000661 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000662 }
663 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000664 if (numThreads > 1) {
665#if SK_SUPPORT_GPU
666 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
667 tiledRenderer->unref();
668 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000669 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000670 }
671#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000672 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000673 renderer.reset(tiledRenderer);
674 if (usePipe) {
675 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
676 "Turning off pipe.\n");
677 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000678 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000679 if (renderer.get() != NULL) {
680 SkDebugf("Pipe is incompatible with other modes.\n");
681 PRINT_USAGE_AND_EXIT;
682 }
683 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000684 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000685 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000686 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000687 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000688
scroggo@google.com5239c322012-09-11 19:15:32 +0000689 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000690 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000691 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000692
693 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000694 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000695 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000696 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000697 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000698 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000699 benchmark->setLogger(&gLogger);
700 // Report current settings:
701 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000702}
reed@google.com006db0f2012-06-27 19:33:29 +0000703
borenet@google.com66bcbd12012-09-17 18:26:06 +0000704static int process_input(const SkString& input,
705 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000706 SkOSFile::Iter iter(input.c_str(), "skp");
707 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000708 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000709 if (iter.next(&inputFilename)) {
710 do {
711 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000712 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000713 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000714 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000715 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000716 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000717 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
718 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000719 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000720 }
721 } else {
722 SkString warning;
723 warning.printf("Warning: skipping %s\n", input.c_str());
724 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000725 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000726 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000727}
728
caryclark@google.com5987f582012-10-02 18:33:14 +0000729int tool_main(int argc, char** argv);
730int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000731#ifdef SK_ENABLE_INST_COUNT
732 gPrintInstCount = true;
733#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000734 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000735
scroggo@google.com5239c322012-09-11 19:15:32 +0000736 SkTArray<SkString> inputs;
737 sk_tools::PictureBenchmark benchmark;
738
739 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000740
borenet@google.com66bcbd12012-09-17 18:26:06 +0000741 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000742 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000743 failures += process_input(inputs[i], benchmark);
744 }
745
746 if (failures != 0) {
747 SkString err;
748 err.printf("Failed to run %i benchmarks.\n", failures);
749 gLogger.logError(err);
750 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000751 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000752 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000753}
caryclark@google.com5987f582012-10-02 18:33:14 +0000754
755#if !defined SK_BUILD_FOR_IOS
756int main(int argc, char * const argv[]) {
757 return tool_main(argc, (char**) argv);
758}
759#endif