blob: 0bfbb2841c036c06dd08efcf9f366a0d8ee6d918 [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"
scroggo@google.comcbcef702012-12-13 22:09:28 +0000123" [--repeat][--timeIndividualTiles] \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");
scroggo@google.comcbcef702012-12-13 22:09:28 +0000147 SkDebugf(" --timeIndividualTiles : Report times for drawing individual tiles, rather than\n"
148" times for drawing the whole page.\n"
149" Requires --mode tile\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000150 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000151" --mode pow2tile minWidth height | copyTile width height | record | simple\n"
152" | tile width height | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000153" Run in the corresponding mode.\n"
154" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000155 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000156" pow2tile minWidth height, Creates tiles with widths\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000157" that are all a power of two\n"
158" such that they minimize the\n"
159" amount of wasted tile space.\n"
160" minWidth is the minimum width\n"
161" of these tiles and must be a\n"
162" power of two. Simple\n"
163" rendering using these tiles\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000164" is benchmarked.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000165 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000166" record, Benchmark picture to picture recording.\n");
167 SkDebugf(
168" simple, Benchmark a simple rendering.\n");
169 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000170" tile width height, Benchmark simple rendering using\n"
171" tiles with the given dimensions.\n"
172" copyTile width height, Draw the picture, then copy it into tiles.\n"
173" Does not support percentages.\n"
174" If the picture is large enough, breaks it into\n"
175" larger tiles (and draws the picture once per\n"
176" larger tile) to avoid creating a large canvas.\n"
177" Add --tiles x y to specify the number of tiles\n"
178" per larger tile in the x and y direction.\n"
179 );
keyar@chromium.org795cd472012-08-02 18:57:53 +0000180 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +0000181" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000182 SkDebugf("\n");
183 SkDebugf(
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000184" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
185" than 1. Only works with tiled rendering.\n"
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000186" --viewport width height : Set the viewport.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000187" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000188 SkDebugf(
junov@chromium.org7b537062012-11-06 18:58:43 +0000189" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
190" be used. Accepted values are: none, rtree, grid. Default\n"
191" value is none. Not compatible with --pipe. With value\n"
192" 'grid', width and height must be specified. 'grid' can\n"
193" only be used with modes tile, record, and\n"
194" playbackCreation.");
junov@chromium.org9313ca42012-11-02 18:11:49 +0000195 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000196" --device bitmap"
197#if SK_SUPPORT_GPU
198" | gpu"
199#endif
200": Use the corresponding device. Default is bitmap.\n");
201 SkDebugf(
202" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000203#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000204 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000205" gpu, Render to the GPU.\n");
206#endif
207 SkDebugf("\n");
208 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000209" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +0000210"Set the number of times to repeat each test."
211" Default is %i.\n", DEFAULT_REPEATS);
caryclark@google.coma3622372012-11-06 21:26:13 +0000212 SkDebugf(
caryclark@google.come3e940c2012-11-07 16:42:17 +0000213" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
214" use no blur or low quality blur, or use no hinting or\n"
215" slight hinting. For all flags except AAClip, specify the\n"
216" type of primitive to effect, or choose all. for AAClip\n"
217" alone, the filter affects all clips independent of type.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000218}
219
scroggo@google.com9a412522012-09-07 15:21:18 +0000220SkBenchLogger gLogger;
221
borenet@google.com66bcbd12012-09-17 18:26:06 +0000222static bool run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +0000223 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000224 SkFILEStream inputStream;
225
reed@google.com006db0f2012-06-27 19:33:29 +0000226 inputStream.setPath(inputPath.c_str());
227 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000228 SkString err;
229 err.printf("Could not open file %s\n", inputPath.c_str());
230 gLogger.logError(err);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000231 return false;
reed@google.com006db0f2012-06-27 19:33:29 +0000232 }
233
borenet@google.com66bcbd12012-09-17 18:26:06 +0000234 bool success = false;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000235 SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000236 if (!success) {
237 SkString err;
238 err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
239 gLogger.logError(err);
240 return false;
241 }
reed@google.com006db0f2012-06-27 19:33:29 +0000242
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000243 SkString filename;
244 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000245
246 SkString result;
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000247 result.printf("running bench [%i %i] %s ", picture.width(),
248 picture.height(), filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000249 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000250
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000251 benchmark.run(&picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000252 return true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000253}
254
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000255#define PRINT_USAGE_AND_EXIT \
256 do { \
257 usage(argv0); \
258 exit(-1); \
259 } while (0)
260
keyar@chromium.org163b5672012-08-01 17:53:29 +0000261static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
scroggo@google.com5239c322012-09-11 19:15:32 +0000262 sk_tools::PictureBenchmark* benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000263 const char* argv0 = argv[0];
264 char* const* stop = argv + argc;
265
keyar@chromium.org163b5672012-08-01 17:53:29 +0000266 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000267 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
268 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000269
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000270 SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
scroggo@google.com5239c322012-09-11 19:15:32 +0000271
scroggo@google.com9a412522012-09-07 15:21:18 +0000272 // Create a string to show our current settings.
273 // TODO: Make it prettier. Currently it just repeats the command line.
274 SkString commandLine("bench_pictures:");
275 for (int i = 1; i < argc; i++) {
276 commandLine.appendf(" %s", *(argv+i));
277 }
278 commandLine.append("\n");
279
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000280 bool usePipe = false;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000281 int numThreads = 1;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000282 bool useTiles = false;
283 const char* widthString = NULL;
284 const char* heightString = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000285 int gridWidth = 0;
286 int gridHeight = 0;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000287 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000288 bool isCopyMode = false;
289 const char* xTilesString = NULL;
290 const char* yTilesString = NULL;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000291 const char* mode = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000292 bool gridSupported = false;
skia.committer@gmail.com1aa90cf2012-11-06 13:18:25 +0000293 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
junov@chromium.org9313ca42012-11-02 18:11:49 +0000294 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
caryclark@google.coma3622372012-11-06 21:26:13 +0000295 sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
296 sk_bzero(drawFilters, sizeof(drawFilters));
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000297 SkISize viewport;
298 viewport.setEmpty();
reed@google.com006db0f2012-06-27 19:33:29 +0000299 for (++argv; argv < stop; ++argv) {
300 if (0 == strcmp(*argv, "--repeat")) {
301 ++argv;
302 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000303 repeats = atoi(*argv);
304 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000305 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000306 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000307 }
308 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000309 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000310 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000311 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000312 } else if (0 == strcmp(*argv, "--pipe")) {
313 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000314 } else if (0 == strcmp(*argv, "--logFile")) {
315 argv++;
316 if (argv < stop) {
317 if (!gLogger.SetLogFile(*argv)) {
318 SkString str;
319 str.printf("Could not open %s for writing.", *argv);
320 gLogger.logError(str);
321 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000322 // TODO(borenet): We're disabling this for now, due to
323 // write-protected Android devices. The very short-term
324 // solution is to ignore the fact that we have no log file.
325 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000326 }
327 } else {
328 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000329 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000330 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000331 } else if (0 == strcmp(*argv, "--multi")) {
332 ++argv;
333 if (argv >= stop) {
334 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000335 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000336 }
337 numThreads = atoi(*argv);
338 if (numThreads < 2) {
339 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000340 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000341 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000342 } else if (0 == strcmp(*argv, "--bbh")) {
343 ++argv;
344 if (argv >= stop) {
345 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000346 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000347 }
348 if (0 == strcmp(*argv, "none")) {
349 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
350 } else if (0 == strcmp(*argv, "rtree")) {
351 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000352 } else if (0 == strcmp(*argv, "grid")) {
353 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
354 ++argv;
355 if (argv >= stop) {
356 gLogger.logError("Missing width for --bbh grid\n");
357 PRINT_USAGE_AND_EXIT;
358 }
359 gridWidth = atoi(*argv);
360 ++argv;
361 if (argv >= stop) {
362 gLogger.logError("Missing height for --bbh grid\n");
363 PRINT_USAGE_AND_EXIT;
364 }
365 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000366 } else {
367 SkString err;
368 err.printf("%s is not a valid value for --bbhType\n", *argv);
369 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000370 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000371 }
372
keyar@chromium.org795cd472012-08-02 18:57:53 +0000373 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000374 if (renderer.get() != NULL) {
375 SkDebugf("Cannot combine modes.\n");
376 PRINT_USAGE_AND_EXIT;
377 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000378
reed@google.com006db0f2012-06-27 19:33:29 +0000379 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000380 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000381 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000382 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000383 }
384
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000385 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000386 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000387 gridSupported = true;
reed@google.com5a34fd32012-12-10 16:05:09 +0000388 } else if (0 == strcmp(*argv, "clone")) {
389 renderer.reset(sk_tools::CreatePictureCloneRenderer());
keyar@chromium.org795cd472012-08-02 18:57:53 +0000390 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000391 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000392 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
393 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000394 useTiles = true;
395 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000396
397 if (0 == strcmp(*argv, "pow2tile")) {
398 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000399 } else if (0 == strcmp(*argv, "copyTile")) {
400 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000401 } else {
402 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000403 }
404
keyar@chromium.org795cd472012-08-02 18:57:53 +0000405 ++argv;
406 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000407 SkString err;
408 err.printf("Missing width 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 }
412
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000413 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000414 ++argv;
415 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000416 SkString err;
417 err.appendf("Missing height for --mode %s\n", mode);
418 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000419 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000420 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000421 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000422 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000423 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000424 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000425 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
426 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000427 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000428 SkString err;
429 err.printf("%s is not a valid mode for --mode\n", *argv);
430 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000431 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000432 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000433 } else if (0 == strcmp(*argv, "--viewport")) {
434 ++argv;
435 if (argv >= stop) {
436 gLogger.logError("Missing width for --viewport\n");
437 PRINT_USAGE_AND_EXIT;
438 }
439 viewport.fWidth = atoi(*argv);
440 ++argv;
441 if (argv >= stop) {
442 gLogger.logError("Missing height for --viewport\n");
443 PRINT_USAGE_AND_EXIT;
444 }
445 viewport.fHeight = atoi(*argv);
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000446 } else if (0 == strcmp(*argv, "--tiles")) {
447 ++argv;
448 if (argv >= stop) {
449 gLogger.logError("Missing x for --tiles\n");
450 PRINT_USAGE_AND_EXIT;
451 }
452 xTilesString = *argv;
453 ++argv;
454 if (argv >= stop) {
455 gLogger.logError("Missing y for --tiles\n");
456 PRINT_USAGE_AND_EXIT;
457 }
458 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000459 } else if (0 == strcmp(*argv, "--device")) {
460 ++argv;
461 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000462 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000463 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000464 }
465
466 if (0 == strcmp(*argv, "bitmap")) {
467 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
468 }
469#if SK_SUPPORT_GPU
470 else if (0 == strcmp(*argv, "gpu")) {
471 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
472 }
473#endif
474 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000475 SkString err;
476 err.printf("%s is not a valid mode for --device\n", *argv);
477 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000478 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000479 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000480 } else if (0 == strcmp(*argv, "--timers")) {
481 ++argv;
482 if (argv < stop) {
483 bool timerWall = false;
484 bool truncatedTimerWall = false;
485 bool timerCpu = false;
486 bool truncatedTimerCpu = false;
487 bool timerGpu = false;
488 for (char* t = *argv; *t; ++t) {
489 switch (*t) {
490 case 'w':
491 timerWall = true;
492 break;
493 case 'c':
494 timerCpu = true;
495 break;
496 case 'W':
497 truncatedTimerWall = true;
498 break;
499 case 'C':
500 truncatedTimerCpu = true;
501 break;
502 case 'g':
503 timerGpu = true;
504 break;
505 default: {
506 break;
507 }
508 }
509 }
510 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
511 truncatedTimerCpu, timerGpu);
512 } else {
513 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000514 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000515 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000516 } else if (0 == strcmp(*argv, "--timeIndividualTiles")) {
517 benchmark->setTimeIndividualTiles(true);
scroggo@google.com5239c322012-09-11 19:15:32 +0000518 } else if (0 == strcmp(*argv, "--min")) {
519 benchmark->setPrintMin(true);
520 } else if (0 == strcmp(*argv, "--logPerIter")) {
521 ++argv;
522 if (argv < stop) {
523 bool log = atoi(*argv) != 0;
524 benchmark->setLogPerIter(log);
525 } else {
526 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000527 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000528 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000529 } else if (0 == strcmp(*argv, "--filter")) {
530 ++argv;
531 if (argv < stop) {
532 const char* colon = strchr(*argv, ':');
533 if (colon) {
534 int type = -1;
535 size_t typeLen = colon - *argv;
536 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
537 if (typeLen == strlen(gFilterTypes[tIndex])
538 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
539 type = tIndex;
540 break;
541 }
542 }
543 if (type < 0) {
544 SkString err;
545 err.printf("Unknown type for --filter %s\n", *argv);
546 gLogger.logError(err);
547 PRINT_USAGE_AND_EXIT;
548 }
549 int flag = -1;
550 size_t flagLen = strlen(*argv) - typeLen - 1;
551 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
552 if (flagLen == strlen(gFilterFlags[fIndex])
553 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
554 flag = 1 << fIndex;
555 break;
556 }
557 }
558 if (flag < 0) {
559 SkString err;
560 err.printf("Unknown flag for --filter %s\n", *argv);
561 gLogger.logError(err);
562 PRINT_USAGE_AND_EXIT;
563 }
564 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
565 if (type != SkDrawFilter::kTypeCount && index != type) {
566 continue;
567 }
568 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
569 (drawFilters[index] | flag);
570 }
571 } else {
572 SkString err;
573 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
574 gLogger.logError(err);
575 PRINT_USAGE_AND_EXIT;
576 }
577 } else {
578 gLogger.logError("Missing arg for --filter\n");
579 PRINT_USAGE_AND_EXIT;
580 }
reed@google.com006db0f2012-06-27 19:33:29 +0000581 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000582 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000583 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000584 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000585 }
586 }
587
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000588 if (numThreads > 1 && !useTiles) {
589 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000590 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000591 }
592
junov@chromium.org9313ca42012-11-02 18:11:49 +0000593 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
594 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000595 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000596 }
597
junov@chromium.org7b537062012-11-06 18:58:43 +0000598 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
599 !gridSupported) {
600 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
601 PRINT_USAGE_AND_EXIT;
602 }
603
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000604 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000605 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000606 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000607 if (isCopyMode) {
608 int x, y;
609 if (xTilesString != NULL) {
610 SkASSERT(yTilesString != NULL);
611 x = atoi(xTilesString);
612 y = atoi(yTilesString);
613 if (x <= 0 || y <= 0) {
614 gLogger.logError("--tiles must be given values > 0\n");
615 PRINT_USAGE_AND_EXIT;
616 }
617 } else {
618 x = y = 4;
619 }
620 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
scroggo@google.comcbcef702012-12-13 22:09:28 +0000621 if (benchmark->timeIndividualTiles()) {
622 gLogger.logError("timeIndividualTiles is not compatible with copyTile\n");
623 PRINT_USAGE_AND_EXIT;
624 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000625 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000626 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
627 } else {
628 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
629 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000630 if (isPowerOf2Mode) {
631 int minWidth = atoi(widthString);
632 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000633 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000634 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000635 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000636 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000637 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 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000640 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000641 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000642 if (isCopyMode) {
643 tiledRenderer->unref();
644 SkString err;
645 err.printf("--mode %s does not support percentages.\n", mode);
646 gLogger.logError(err.c_str());
647 PRINT_USAGE_AND_EXIT;
648 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000649 tiledRenderer->setTileWidthPercentage(atof(widthString));
650 if (!(tiledRenderer->getTileWidthPercentage() > 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 percentage > 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 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000658 tiledRenderer->setTileWidth(atoi(widthString));
659 if (!(tiledRenderer->getTileWidth() > 0)) {
660 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000661 SkString err;
662 err.appendf("--mode %s must be given a width > 0\n", mode);
663 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000664 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000665 }
666 }
667
668 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000669 if (isCopyMode) {
670 tiledRenderer->unref();
671 SkString err;
672 err.printf("--mode %s does not support percentages.\n", mode);
673 gLogger.logError(err.c_str());
674 PRINT_USAGE_AND_EXIT;
675 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000676 tiledRenderer->setTileHeightPercentage(atof(heightString));
677 if (!(tiledRenderer->getTileHeightPercentage() > 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 percentage > 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 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000685 tiledRenderer->setTileHeight(atoi(heightString));
686 if (!(tiledRenderer->getTileHeight() > 0)) {
687 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000688 SkString err;
689 err.appendf("--mode %s must be given a height > 0\n", mode);
690 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000691 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000692 }
693 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000694 if (numThreads > 1) {
695#if SK_SUPPORT_GPU
696 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
697 tiledRenderer->unref();
698 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000699 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000700 }
701#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000702 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000703 renderer.reset(tiledRenderer);
704 if (usePipe) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000705 gLogger.logError("Pipe rendering is currently not compatible with tiling.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000706 "Turning off pipe.\n");
707 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000708 } else {
709 if (benchmark->timeIndividualTiles()) {
710 gLogger.logError("timeIndividualTiles requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000711 PRINT_USAGE_AND_EXIT;
712 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000713 if (usePipe) {
714 if (renderer.get() != NULL) {
715 gLogger.logError("Pipe is incompatible with other modes.\n");
716 PRINT_USAGE_AND_EXIT;
717 }
718 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
719 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000720 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000721 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000722 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000723 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000724
scroggo@google.com5239c322012-09-11 19:15:32 +0000725 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000726 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000727 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000728
729 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000730 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000731 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000732 renderer->setViewport(viewport);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000733 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000734 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000735 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000736 benchmark->setLogger(&gLogger);
737 // Report current settings:
738 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000739}
reed@google.com006db0f2012-06-27 19:33:29 +0000740
borenet@google.com66bcbd12012-09-17 18:26:06 +0000741static int process_input(const SkString& input,
742 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000743 SkOSFile::Iter iter(input.c_str(), "skp");
744 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000745 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000746 if (iter.next(&inputFilename)) {
747 do {
748 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000749 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000750 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000751 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000752 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000753 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000754 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
755 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000756 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000757 }
758 } else {
759 SkString warning;
760 warning.printf("Warning: skipping %s\n", input.c_str());
761 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000762 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000763 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000764}
765
caryclark@google.com5987f582012-10-02 18:33:14 +0000766int tool_main(int argc, char** argv);
767int tool_main(int argc, char** argv) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000768#ifdef SK_ENABLE_INST_COUNT
769 gPrintInstCount = true;
770#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000771 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000772
scroggo@google.com5239c322012-09-11 19:15:32 +0000773 SkTArray<SkString> inputs;
774 sk_tools::PictureBenchmark benchmark;
775
776 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000777
borenet@google.com66bcbd12012-09-17 18:26:06 +0000778 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000779 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000780 failures += process_input(inputs[i], benchmark);
781 }
782
783 if (failures != 0) {
784 SkString err;
785 err.printf("Failed to run %i benchmarks.\n", failures);
786 gLogger.logError(err);
787 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000788 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000789 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000790}
caryclark@google.com5987f582012-10-02 18:33:14 +0000791
792#if !defined SK_BUILD_FOR_IOS
793int main(int argc, char * const argv[]) {
794 return tool_main(argc, (char**) argv);
795}
796#endif