blob: 47844f941731e2b5541a1532d669e3530703cf13 [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;
reed@google.com5a34fd32012-12-10 16:05:09 +0000381 } else if (0 == strcmp(*argv, "clone")) {
382 renderer.reset(sk_tools::CreatePictureCloneRenderer());
keyar@chromium.org795cd472012-08-02 18:57:53 +0000383 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000384 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000385 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
386 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000387 useTiles = true;
388 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000389
390 if (0 == strcmp(*argv, "pow2tile")) {
391 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000392 } else if (0 == strcmp(*argv, "copyTile")) {
393 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000394 } else {
395 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000396 }
397
keyar@chromium.org795cd472012-08-02 18:57:53 +0000398 ++argv;
399 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000400 SkString err;
401 err.printf("Missing width for --mode %s\n", mode);
402 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000403 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000404 }
405
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000406 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000407 ++argv;
408 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000409 SkString err;
410 err.appendf("Missing height for --mode %s\n", mode);
411 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000412 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000413 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000414 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000415 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000416 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000417 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000418 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
419 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000420 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000421 SkString err;
422 err.printf("%s is not a valid mode for --mode\n", *argv);
423 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000424 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000425 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000426 } else if (0 == strcmp(*argv, "--tiles")) {
427 ++argv;
428 if (argv >= stop) {
429 gLogger.logError("Missing x for --tiles\n");
430 PRINT_USAGE_AND_EXIT;
431 }
432 xTilesString = *argv;
433 ++argv;
434 if (argv >= stop) {
435 gLogger.logError("Missing y for --tiles\n");
436 PRINT_USAGE_AND_EXIT;
437 }
438 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000439 } else if (0 == strcmp(*argv, "--device")) {
440 ++argv;
441 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000442 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000443 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000444 }
445
446 if (0 == strcmp(*argv, "bitmap")) {
447 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
448 }
449#if SK_SUPPORT_GPU
450 else if (0 == strcmp(*argv, "gpu")) {
451 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
452 }
453#endif
454 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000455 SkString err;
456 err.printf("%s is not a valid mode for --device\n", *argv);
457 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000458 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000459 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000460 } else if (0 == strcmp(*argv, "--timers")) {
461 ++argv;
462 if (argv < stop) {
463 bool timerWall = false;
464 bool truncatedTimerWall = false;
465 bool timerCpu = false;
466 bool truncatedTimerCpu = false;
467 bool timerGpu = false;
468 for (char* t = *argv; *t; ++t) {
469 switch (*t) {
470 case 'w':
471 timerWall = true;
472 break;
473 case 'c':
474 timerCpu = true;
475 break;
476 case 'W':
477 truncatedTimerWall = true;
478 break;
479 case 'C':
480 truncatedTimerCpu = true;
481 break;
482 case 'g':
483 timerGpu = true;
484 break;
485 default: {
486 break;
487 }
488 }
489 }
490 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
491 truncatedTimerCpu, timerGpu);
492 } else {
493 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000494 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000495 }
496 } else if (0 == strcmp(*argv, "--min")) {
497 benchmark->setPrintMin(true);
498 } else if (0 == strcmp(*argv, "--logPerIter")) {
499 ++argv;
500 if (argv < stop) {
501 bool log = atoi(*argv) != 0;
502 benchmark->setLogPerIter(log);
503 } else {
504 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000505 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000506 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000507 } else if (0 == strcmp(*argv, "--filter")) {
508 ++argv;
509 if (argv < stop) {
510 const char* colon = strchr(*argv, ':');
511 if (colon) {
512 int type = -1;
513 size_t typeLen = colon - *argv;
514 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
515 if (typeLen == strlen(gFilterTypes[tIndex])
516 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
517 type = tIndex;
518 break;
519 }
520 }
521 if (type < 0) {
522 SkString err;
523 err.printf("Unknown type for --filter %s\n", *argv);
524 gLogger.logError(err);
525 PRINT_USAGE_AND_EXIT;
526 }
527 int flag = -1;
528 size_t flagLen = strlen(*argv) - typeLen - 1;
529 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
530 if (flagLen == strlen(gFilterFlags[fIndex])
531 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
532 flag = 1 << fIndex;
533 break;
534 }
535 }
536 if (flag < 0) {
537 SkString err;
538 err.printf("Unknown flag for --filter %s\n", *argv);
539 gLogger.logError(err);
540 PRINT_USAGE_AND_EXIT;
541 }
542 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
543 if (type != SkDrawFilter::kTypeCount && index != type) {
544 continue;
545 }
546 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
547 (drawFilters[index] | flag);
548 }
549 } else {
550 SkString err;
551 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
552 gLogger.logError(err);
553 PRINT_USAGE_AND_EXIT;
554 }
555 } else {
556 gLogger.logError("Missing arg for --filter\n");
557 PRINT_USAGE_AND_EXIT;
558 }
reed@google.com006db0f2012-06-27 19:33:29 +0000559 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000560 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000561 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000562 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000563 }
564 }
565
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000566 if (numThreads > 1 && !useTiles) {
567 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000568 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000569 }
570
junov@chromium.org9313ca42012-11-02 18:11:49 +0000571 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
572 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000573 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000574 }
575
junov@chromium.org7b537062012-11-06 18:58:43 +0000576 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
577 !gridSupported) {
578 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
579 PRINT_USAGE_AND_EXIT;
580 }
581
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000582 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000583 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000584 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000585 if (isCopyMode) {
586 int x, y;
587 if (xTilesString != NULL) {
588 SkASSERT(yTilesString != NULL);
589 x = atoi(xTilesString);
590 y = atoi(yTilesString);
591 if (x <= 0 || y <= 0) {
592 gLogger.logError("--tiles must be given values > 0\n");
593 PRINT_USAGE_AND_EXIT;
594 }
595 } else {
596 x = y = 4;
597 }
598 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
599 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000600 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
601 } else {
602 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
603 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000604 if (isPowerOf2Mode) {
605 int minWidth = atoi(widthString);
606 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000607 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000608 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000609 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000610 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000611 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000612 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000613 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000614 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000615 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000616 if (isCopyMode) {
617 tiledRenderer->unref();
618 SkString err;
619 err.printf("--mode %s does not support percentages.\n", mode);
620 gLogger.logError(err.c_str());
621 PRINT_USAGE_AND_EXIT;
622 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000623 tiledRenderer->setTileWidthPercentage(atof(widthString));
624 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
625 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000626 SkString err;
627 err.appendf("--mode %s must be given a width percentage > 0\n", mode);
628 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000629 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000630 }
631 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000632 tiledRenderer->setTileWidth(atoi(widthString));
633 if (!(tiledRenderer->getTileWidth() > 0)) {
634 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000635 SkString err;
636 err.appendf("--mode %s must be given a width > 0\n", mode);
637 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000638 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000639 }
640 }
641
642 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000643 if (isCopyMode) {
644 tiledRenderer->unref();
645 SkString err;
646 err.printf("--mode %s does not support percentages.\n", mode);
647 gLogger.logError(err.c_str());
648 PRINT_USAGE_AND_EXIT;
649 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000650 tiledRenderer->setTileHeightPercentage(atof(heightString));
651 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
652 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000653 SkString err;
654 err.appendf("--mode %s must be given a height percentage > 0\n", mode);
655 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000656 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000657 }
658 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000659 tiledRenderer->setTileHeight(atoi(heightString));
660 if (!(tiledRenderer->getTileHeight() > 0)) {
661 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000662 SkString err;
663 err.appendf("--mode %s must be given a height > 0\n", mode);
664 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000665 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000666 }
667 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000668 if (numThreads > 1) {
669#if SK_SUPPORT_GPU
670 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
671 tiledRenderer->unref();
672 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000673 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000674 }
675#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000676 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000677 renderer.reset(tiledRenderer);
678 if (usePipe) {
679 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
680 "Turning off pipe.\n");
681 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000682 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000683 if (renderer.get() != NULL) {
684 SkDebugf("Pipe is incompatible with other modes.\n");
685 PRINT_USAGE_AND_EXIT;
686 }
687 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000688 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000689 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000690 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000691 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000692
scroggo@google.com5239c322012-09-11 19:15:32 +0000693 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000694 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000695 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000696
697 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000698 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000699 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000700 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000701 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000702 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000703 benchmark->setLogger(&gLogger);
704 // Report current settings:
705 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000706}
reed@google.com006db0f2012-06-27 19:33:29 +0000707
borenet@google.com66bcbd12012-09-17 18:26:06 +0000708static int process_input(const SkString& input,
709 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000710 SkOSFile::Iter iter(input.c_str(), "skp");
711 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000712 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000713 if (iter.next(&inputFilename)) {
714 do {
715 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000716 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000717 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000718 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000719 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000720 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000721 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
722 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000723 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000724 }
725 } else {
726 SkString warning;
727 warning.printf("Warning: skipping %s\n", input.c_str());
728 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000729 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000730 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000731}
732
caryclark@google.com5987f582012-10-02 18:33:14 +0000733int tool_main(int argc, char** argv);
734int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000735#ifdef SK_ENABLE_INST_COUNT
736 gPrintInstCount = true;
737#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000738 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000739
scroggo@google.com5239c322012-09-11 19:15:32 +0000740 SkTArray<SkString> inputs;
741 sk_tools::PictureBenchmark benchmark;
742
743 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000744
borenet@google.com66bcbd12012-09-17 18:26:06 +0000745 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000746 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000747 failures += process_input(inputs[i], benchmark);
748 }
749
750 if (failures != 0) {
751 SkString err;
752 err.printf("Failed to run %i benchmarks.\n", failures);
753 gLogger.logError(err);
754 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000755 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000756 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000757}
caryclark@google.com5987f582012-10-02 18:33:14 +0000758
759#if !defined SK_BUILD_FOR_IOS
760int main(int argc, char * const argv[]) {
761 return tool_main(argc, (char**) argv);
762}
763#endif