blob: ca638071693bca80f850954c85bc84e9d385c1d3 [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"
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000129" [--viewport width height]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000130" [--device bitmap"
131#if SK_SUPPORT_GPU
132" | gpu"
133#endif
caryclark@google.coma3622372012-11-06 21:26:13 +0000134"]\n"
135" [--filter [%s]:\n [%s]]\n"
136, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
137 SkDebugf("\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000138 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000139" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +0000140" expected to have the .skp extension.\n\n"
141" --logFile filename : destination for writing log output, in addition to stdout.\n");
scroggo@google.com5239c322012-09-11 19:15:32 +0000142 SkDebugf(" --logPerIter 1|0 : "
143 "Log each repeat timer instead of mean, default is disabled.\n");
144 SkDebugf(" --min : Print the minimum times (instead of average).\n");
145 SkDebugf(" --timers [wcgWC]* : "
146 "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000147 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000148" --mode pow2tile minWidth height | copyTile width height | record | simple\n"
149" | tile width height | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000150" Run in the corresponding mode.\n"
151" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000152 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000153" pow2tile minWidth height, Creates tiles with widths\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000154" that are all a power of two\n"
155" such that they minimize the\n"
156" amount of wasted tile space.\n"
157" minWidth is the minimum width\n"
158" of these tiles and must be a\n"
159" power of two. Simple\n"
160" rendering using these tiles\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000161" is benchmarked.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000162 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000163" record, Benchmark picture to picture recording.\n");
164 SkDebugf(
165" simple, Benchmark a simple rendering.\n");
166 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000167" tile width height, Benchmark simple rendering using\n"
168" tiles with the given dimensions.\n"
169" copyTile width height, Draw the picture, then copy it into tiles.\n"
170" Does not support percentages.\n"
171" If the picture is large enough, breaks it into\n"
172" larger tiles (and draws the picture once per\n"
173" larger tile) to avoid creating a large canvas.\n"
174" Add --tiles x y to specify the number of tiles\n"
175" per larger tile in the x and y direction.\n"
176 );
keyar@chromium.org795cd472012-08-02 18:57:53 +0000177 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +0000178" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000179 SkDebugf("\n");
180 SkDebugf(
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000181" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
182" than 1. Only works with tiled rendering.\n"
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000183" --viewport width height : Set the viewport.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000184" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000185 SkDebugf(
junov@chromium.org7b537062012-11-06 18:58:43 +0000186" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
187" be used. Accepted values are: none, rtree, grid. Default\n"
188" value is none. Not compatible with --pipe. With value\n"
189" 'grid', width and height must be specified. 'grid' can\n"
190" only be used with modes tile, record, and\n"
191" playbackCreation.");
junov@chromium.org9313ca42012-11-02 18:11:49 +0000192 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000193" --device bitmap"
194#if SK_SUPPORT_GPU
195" | gpu"
196#endif
197": Use the corresponding device. Default is bitmap.\n");
198 SkDebugf(
199" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000200#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000201 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000202" gpu, Render to the GPU.\n");
203#endif
204 SkDebugf("\n");
205 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000206" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +0000207"Set the number of times to repeat each test."
208" Default is %i.\n", DEFAULT_REPEATS);
caryclark@google.coma3622372012-11-06 21:26:13 +0000209 SkDebugf(
caryclark@google.come3e940c2012-11-07 16:42:17 +0000210" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
211" use no blur or low quality blur, or use no hinting or\n"
212" slight hinting. For all flags except AAClip, specify the\n"
213" type of primitive to effect, or choose all. for AAClip\n"
214" alone, the filter affects all clips independent of type.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000215}
216
scroggo@google.com9a412522012-09-07 15:21:18 +0000217SkBenchLogger gLogger;
218
borenet@google.com66bcbd12012-09-17 18:26:06 +0000219static bool run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +0000220 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000221 SkFILEStream inputStream;
222
reed@google.com006db0f2012-06-27 19:33:29 +0000223 inputStream.setPath(inputPath.c_str());
224 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000225 SkString err;
226 err.printf("Could not open file %s\n", inputPath.c_str());
227 gLogger.logError(err);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000228 return false;
reed@google.com006db0f2012-06-27 19:33:29 +0000229 }
230
borenet@google.com66bcbd12012-09-17 18:26:06 +0000231 bool success = false;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000232 SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000233 if (!success) {
234 SkString err;
235 err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
236 gLogger.logError(err);
237 return false;
238 }
reed@google.com006db0f2012-06-27 19:33:29 +0000239
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000240 SkString filename;
241 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000242
243 SkString result;
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000244 result.printf("running bench [%i %i] %s ", picture.width(),
245 picture.height(), filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000246 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000247
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000248 benchmark.run(&picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000249 return true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000250}
251
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000252#define PRINT_USAGE_AND_EXIT \
253 do { \
254 usage(argv0); \
255 exit(-1); \
256 } while (0)
257
keyar@chromium.org163b5672012-08-01 17:53:29 +0000258static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
scroggo@google.com5239c322012-09-11 19:15:32 +0000259 sk_tools::PictureBenchmark* benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000260 const char* argv0 = argv[0];
261 char* const* stop = argv + argc;
262
keyar@chromium.org163b5672012-08-01 17:53:29 +0000263 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000264 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
265 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000266
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000267 SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
scroggo@google.com5239c322012-09-11 19:15:32 +0000268
scroggo@google.com9a412522012-09-07 15:21:18 +0000269 // Create a string to show our current settings.
270 // TODO: Make it prettier. Currently it just repeats the command line.
271 SkString commandLine("bench_pictures:");
272 for (int i = 1; i < argc; i++) {
273 commandLine.appendf(" %s", *(argv+i));
274 }
275 commandLine.append("\n");
276
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000277 bool usePipe = false;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000278 int numThreads = 1;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000279 bool useTiles = false;
280 const char* widthString = NULL;
281 const char* heightString = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000282 int gridWidth = 0;
283 int gridHeight = 0;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000284 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000285 bool isCopyMode = false;
286 const char* xTilesString = NULL;
287 const char* yTilesString = NULL;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000288 const char* mode = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000289 bool gridSupported = false;
skia.committer@gmail.com1aa90cf2012-11-06 13:18:25 +0000290 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
junov@chromium.org9313ca42012-11-02 18:11:49 +0000291 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
caryclark@google.coma3622372012-11-06 21:26:13 +0000292 sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
293 sk_bzero(drawFilters, sizeof(drawFilters));
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000294 SkISize viewport;
295 viewport.setEmpty();
reed@google.com006db0f2012-06-27 19:33:29 +0000296 for (++argv; argv < stop; ++argv) {
297 if (0 == strcmp(*argv, "--repeat")) {
298 ++argv;
299 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000300 repeats = atoi(*argv);
301 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000302 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000303 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000304 }
305 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000306 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000307 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000308 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000309 } else if (0 == strcmp(*argv, "--pipe")) {
310 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000311 } else if (0 == strcmp(*argv, "--logFile")) {
312 argv++;
313 if (argv < stop) {
314 if (!gLogger.SetLogFile(*argv)) {
315 SkString str;
316 str.printf("Could not open %s for writing.", *argv);
317 gLogger.logError(str);
318 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000319 // TODO(borenet): We're disabling this for now, due to
320 // write-protected Android devices. The very short-term
321 // solution is to ignore the fact that we have no log file.
322 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000323 }
324 } else {
325 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000326 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000327 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000328 } else if (0 == strcmp(*argv, "--multi")) {
329 ++argv;
330 if (argv >= stop) {
331 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000332 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000333 }
334 numThreads = atoi(*argv);
335 if (numThreads < 2) {
336 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000337 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000338 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000339 } else if (0 == strcmp(*argv, "--bbh")) {
340 ++argv;
341 if (argv >= stop) {
342 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000343 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000344 }
345 if (0 == strcmp(*argv, "none")) {
346 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
347 } else if (0 == strcmp(*argv, "rtree")) {
348 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000349 } else if (0 == strcmp(*argv, "grid")) {
350 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
351 ++argv;
352 if (argv >= stop) {
353 gLogger.logError("Missing width for --bbh grid\n");
354 PRINT_USAGE_AND_EXIT;
355 }
356 gridWidth = atoi(*argv);
357 ++argv;
358 if (argv >= stop) {
359 gLogger.logError("Missing height for --bbh grid\n");
360 PRINT_USAGE_AND_EXIT;
361 }
362 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000363 } else {
364 SkString err;
365 err.printf("%s is not a valid value for --bbhType\n", *argv);
366 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000367 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000368 }
369
keyar@chromium.org795cd472012-08-02 18:57:53 +0000370 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000371 if (renderer.get() != NULL) {
372 SkDebugf("Cannot combine modes.\n");
373 PRINT_USAGE_AND_EXIT;
374 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000375
reed@google.com006db0f2012-06-27 19:33:29 +0000376 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000377 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000378 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000379 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000380 }
381
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000382 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000383 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000384 gridSupported = true;
reed@google.com5a34fd32012-12-10 16:05:09 +0000385 } else if (0 == strcmp(*argv, "clone")) {
386 renderer.reset(sk_tools::CreatePictureCloneRenderer());
keyar@chromium.org795cd472012-08-02 18:57:53 +0000387 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000388 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000389 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
390 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000391 useTiles = true;
392 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000393
394 if (0 == strcmp(*argv, "pow2tile")) {
395 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000396 } else if (0 == strcmp(*argv, "copyTile")) {
397 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000398 } else {
399 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000400 }
401
keyar@chromium.org795cd472012-08-02 18:57:53 +0000402 ++argv;
403 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000404 SkString err;
405 err.printf("Missing width for --mode %s\n", mode);
406 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000407 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000408 }
409
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000410 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000411 ++argv;
412 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000413 SkString err;
414 err.appendf("Missing height for --mode %s\n", mode);
415 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000416 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000417 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000418 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000419 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000420 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000421 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000422 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
423 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000424 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000425 SkString err;
426 err.printf("%s is not a valid mode for --mode\n", *argv);
427 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000428 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000429 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000430 } else if (0 == strcmp(*argv, "--viewport")) {
431 ++argv;
432 if (argv >= stop) {
433 gLogger.logError("Missing width for --viewport\n");
434 PRINT_USAGE_AND_EXIT;
435 }
436 viewport.fWidth = atoi(*argv);
437 ++argv;
438 if (argv >= stop) {
439 gLogger.logError("Missing height for --viewport\n");
440 PRINT_USAGE_AND_EXIT;
441 }
442 viewport.fHeight = atoi(*argv);
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000443 } else if (0 == strcmp(*argv, "--tiles")) {
444 ++argv;
445 if (argv >= stop) {
446 gLogger.logError("Missing x for --tiles\n");
447 PRINT_USAGE_AND_EXIT;
448 }
449 xTilesString = *argv;
450 ++argv;
451 if (argv >= stop) {
452 gLogger.logError("Missing y for --tiles\n");
453 PRINT_USAGE_AND_EXIT;
454 }
455 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000456 } else if (0 == strcmp(*argv, "--device")) {
457 ++argv;
458 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000459 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000460 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000461 }
462
463 if (0 == strcmp(*argv, "bitmap")) {
464 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
465 }
466#if SK_SUPPORT_GPU
467 else if (0 == strcmp(*argv, "gpu")) {
468 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
469 }
470#endif
471 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000472 SkString err;
473 err.printf("%s is not a valid mode for --device\n", *argv);
474 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000475 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000476 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000477 } else if (0 == strcmp(*argv, "--timers")) {
478 ++argv;
479 if (argv < stop) {
480 bool timerWall = false;
481 bool truncatedTimerWall = false;
482 bool timerCpu = false;
483 bool truncatedTimerCpu = false;
484 bool timerGpu = false;
485 for (char* t = *argv; *t; ++t) {
486 switch (*t) {
487 case 'w':
488 timerWall = true;
489 break;
490 case 'c':
491 timerCpu = true;
492 break;
493 case 'W':
494 truncatedTimerWall = true;
495 break;
496 case 'C':
497 truncatedTimerCpu = true;
498 break;
499 case 'g':
500 timerGpu = true;
501 break;
502 default: {
503 break;
504 }
505 }
506 }
507 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
508 truncatedTimerCpu, timerGpu);
509 } else {
510 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000511 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000512 }
513 } else if (0 == strcmp(*argv, "--min")) {
514 benchmark->setPrintMin(true);
515 } else if (0 == strcmp(*argv, "--logPerIter")) {
516 ++argv;
517 if (argv < stop) {
518 bool log = atoi(*argv) != 0;
519 benchmark->setLogPerIter(log);
520 } else {
521 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000522 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000523 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000524 } else if (0 == strcmp(*argv, "--filter")) {
525 ++argv;
526 if (argv < stop) {
527 const char* colon = strchr(*argv, ':');
528 if (colon) {
529 int type = -1;
530 size_t typeLen = colon - *argv;
531 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
532 if (typeLen == strlen(gFilterTypes[tIndex])
533 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
534 type = tIndex;
535 break;
536 }
537 }
538 if (type < 0) {
539 SkString err;
540 err.printf("Unknown type for --filter %s\n", *argv);
541 gLogger.logError(err);
542 PRINT_USAGE_AND_EXIT;
543 }
544 int flag = -1;
545 size_t flagLen = strlen(*argv) - typeLen - 1;
546 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
547 if (flagLen == strlen(gFilterFlags[fIndex])
548 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
549 flag = 1 << fIndex;
550 break;
551 }
552 }
553 if (flag < 0) {
554 SkString err;
555 err.printf("Unknown flag for --filter %s\n", *argv);
556 gLogger.logError(err);
557 PRINT_USAGE_AND_EXIT;
558 }
559 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
560 if (type != SkDrawFilter::kTypeCount && index != type) {
561 continue;
562 }
563 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
564 (drawFilters[index] | flag);
565 }
566 } else {
567 SkString err;
568 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
569 gLogger.logError(err);
570 PRINT_USAGE_AND_EXIT;
571 }
572 } else {
573 gLogger.logError("Missing arg for --filter\n");
574 PRINT_USAGE_AND_EXIT;
575 }
reed@google.com006db0f2012-06-27 19:33:29 +0000576 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000577 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000578 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000579 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000580 }
581 }
582
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000583 if (numThreads > 1 && !useTiles) {
584 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000585 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000586 }
587
junov@chromium.org9313ca42012-11-02 18:11:49 +0000588 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
589 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000590 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000591 }
592
junov@chromium.org7b537062012-11-06 18:58:43 +0000593 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
594 !gridSupported) {
595 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
596 PRINT_USAGE_AND_EXIT;
597 }
598
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000599 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000600 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000601 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000602 if (isCopyMode) {
603 int x, y;
604 if (xTilesString != NULL) {
605 SkASSERT(yTilesString != NULL);
606 x = atoi(xTilesString);
607 y = atoi(yTilesString);
608 if (x <= 0 || y <= 0) {
609 gLogger.logError("--tiles must be given values > 0\n");
610 PRINT_USAGE_AND_EXIT;
611 }
612 } else {
613 x = y = 4;
614 }
615 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
616 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000617 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
618 } else {
619 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
620 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000621 if (isPowerOf2Mode) {
622 int minWidth = atoi(widthString);
623 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000624 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000625 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000626 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000627 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000628 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 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000631 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000632 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000633 if (isCopyMode) {
634 tiledRenderer->unref();
635 SkString err;
636 err.printf("--mode %s does not support percentages.\n", mode);
637 gLogger.logError(err.c_str());
638 PRINT_USAGE_AND_EXIT;
639 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000640 tiledRenderer->setTileWidthPercentage(atof(widthString));
641 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
642 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000643 SkString err;
644 err.appendf("--mode %s must be given a width percentage > 0\n", mode);
645 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000646 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000647 }
648 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000649 tiledRenderer->setTileWidth(atoi(widthString));
650 if (!(tiledRenderer->getTileWidth() > 0)) {
651 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000652 SkString err;
653 err.appendf("--mode %s must be given a width > 0\n", mode);
654 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000655 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000656 }
657 }
658
659 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000660 if (isCopyMode) {
661 tiledRenderer->unref();
662 SkString err;
663 err.printf("--mode %s does not support percentages.\n", mode);
664 gLogger.logError(err.c_str());
665 PRINT_USAGE_AND_EXIT;
666 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000667 tiledRenderer->setTileHeightPercentage(atof(heightString));
668 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
669 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000670 SkString err;
671 err.appendf("--mode %s must be given a height percentage > 0\n", mode);
672 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000673 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000674 }
675 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000676 tiledRenderer->setTileHeight(atoi(heightString));
677 if (!(tiledRenderer->getTileHeight() > 0)) {
678 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000679 SkString err;
680 err.appendf("--mode %s must be given a height > 0\n", mode);
681 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000682 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000683 }
684 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000685 if (numThreads > 1) {
686#if SK_SUPPORT_GPU
687 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
688 tiledRenderer->unref();
689 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000690 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000691 }
692#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000693 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000694 renderer.reset(tiledRenderer);
695 if (usePipe) {
696 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
697 "Turning off pipe.\n");
698 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000699 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000700 if (renderer.get() != NULL) {
701 SkDebugf("Pipe is incompatible with other modes.\n");
702 PRINT_USAGE_AND_EXIT;
703 }
704 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000705 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000706 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000707 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000708 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000709
scroggo@google.com5239c322012-09-11 19:15:32 +0000710 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000711 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000712 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000713
714 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000715 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000716 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000717 renderer->setViewport(viewport);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000718 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000719 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000720 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000721 benchmark->setLogger(&gLogger);
722 // Report current settings:
723 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000724}
reed@google.com006db0f2012-06-27 19:33:29 +0000725
borenet@google.com66bcbd12012-09-17 18:26:06 +0000726static int process_input(const SkString& input,
727 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000728 SkOSFile::Iter iter(input.c_str(), "skp");
729 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000730 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000731 if (iter.next(&inputFilename)) {
732 do {
733 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000734 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000735 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000736 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000737 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000738 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000739 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
740 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000741 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000742 }
743 } else {
744 SkString warning;
745 warning.printf("Warning: skipping %s\n", input.c_str());
746 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000747 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000748 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000749}
750
caryclark@google.com5987f582012-10-02 18:33:14 +0000751int tool_main(int argc, char** argv);
752int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000753#ifdef SK_ENABLE_INST_COUNT
754 gPrintInstCount = true;
755#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000756 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000757
scroggo@google.com5239c322012-09-11 19:15:32 +0000758 SkTArray<SkString> inputs;
759 sk_tools::PictureBenchmark benchmark;
760
761 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000762
borenet@google.com66bcbd12012-09-17 18:26:06 +0000763 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000764 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000765 failures += process_input(inputs[i], benchmark);
766 }
767
768 if (failures != 0) {
769 SkString err;
770 err.printf("Failed to run %i benchmarks.\n", failures);
771 gLogger.logError(err);
772 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000773 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000774 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000775}
caryclark@google.com5987f582012-10-02 18:33:14 +0000776
777#if !defined SK_BUILD_FOR_IOS
778int main(int argc, char * const argv[]) {
779 return tool_main(argc, (char**) argv);
780}
781#endif