blob: b485aff21bd5f14d630f1e8c017d5e9d86f15cb2 [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",
jvanverth@google.comd3c208c2013-01-22 13:54:52 +000030 "oval",
caryclark@google.coma3622372012-11-06 21:26:13 +000031 "path",
32 "text",
33 "all",
34};
35
36static const size_t kFilterTypesCount = sizeof(gFilterTypes) / sizeof(gFilterTypes[0]);
37
38static char const * const gFilterFlags[] = {
39 "antiAlias",
40 "filterBitmap",
41 "dither",
42 "underlineText",
43 "strikeThruText",
44 "fakeBoldText",
45 "linearText",
46 "subpixelText",
47 "devKernText",
48 "LCDRenderText",
49 "embeddedBitmapText",
50 "autoHinting",
51 "verticalText",
52 "genA8FromLCD",
53 "blur",
54 "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.com82ec0b02012-12-17 19:25:54 +0000129" [--viewport width height][--scale sf]\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.com82ec0b02012-12-17 19:25:54 +0000187" --scale sf : Scale drawing by sf.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000188" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000189 SkDebugf(
junov@chromium.org7b537062012-11-06 18:58:43 +0000190" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
191" be used. Accepted values are: none, rtree, grid. Default\n"
192" value is none. Not compatible with --pipe. With value\n"
193" 'grid', width and height must be specified. 'grid' can\n"
194" only be used with modes tile, record, and\n"
195" playbackCreation.");
junov@chromium.org9313ca42012-11-02 18:11:49 +0000196 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000197" --device bitmap"
198#if SK_SUPPORT_GPU
199" | gpu"
200#endif
201": Use the corresponding device. Default is bitmap.\n");
202 SkDebugf(
203" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000204#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000205 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000206" gpu, Render to the GPU.\n");
207#endif
208 SkDebugf("\n");
209 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000210" --repeat: "
reed@google.com006db0f2012-06-27 19:33:29 +0000211"Set the number of times to repeat each test."
212" Default is %i.\n", DEFAULT_REPEATS);
caryclark@google.coma3622372012-11-06 21:26:13 +0000213 SkDebugf(
caryclark@google.come3e940c2012-11-07 16:42:17 +0000214" --filter type:flag : Enable canvas filtering to disable a paint flag,\n"
215" use no blur or low quality blur, or use no hinting or\n"
216" slight hinting. For all flags except AAClip, specify the\n"
217" type of primitive to effect, or choose all. for AAClip\n"
218" alone, the filter affects all clips independent of type.\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000219}
220
scroggo@google.com9a412522012-09-07 15:21:18 +0000221SkBenchLogger gLogger;
222
borenet@google.com66bcbd12012-09-17 18:26:06 +0000223static bool run_single_benchmark(const SkString& inputPath,
keyar@chromium.org163b5672012-08-01 17:53:29 +0000224 sk_tools::PictureBenchmark& benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000225 SkFILEStream inputStream;
226
reed@google.com006db0f2012-06-27 19:33:29 +0000227 inputStream.setPath(inputPath.c_str());
228 if (!inputStream.isValid()) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000229 SkString err;
230 err.printf("Could not open file %s\n", inputPath.c_str());
231 gLogger.logError(err);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000232 return false;
reed@google.com006db0f2012-06-27 19:33:29 +0000233 }
234
borenet@google.com66bcbd12012-09-17 18:26:06 +0000235 bool success = false;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000236 SkPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000237 if (!success) {
238 SkString err;
239 err.printf("Could not read an SkPicture from %s\n", inputPath.c_str());
240 gLogger.logError(err);
241 return false;
242 }
reed@google.com006db0f2012-06-27 19:33:29 +0000243
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000244 SkString filename;
245 sk_tools::get_basename(&filename, inputPath);
keyar@chromium.orgdb9a5fb2012-08-21 17:57:59 +0000246
247 SkString result;
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000248 result.printf("running bench [%i %i] %s ", picture.width(),
249 picture.height(), filename.c_str());
scroggo@google.com9a412522012-09-07 15:21:18 +0000250 gLogger.logProgress(result);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000251
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000252 benchmark.run(&picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000253 return true;
keyar@chromium.org0665f252012-07-10 18:30:18 +0000254}
255
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000256#define PRINT_USAGE_AND_EXIT \
257 do { \
258 usage(argv0); \
259 exit(-1); \
260 } while (0)
261
keyar@chromium.org163b5672012-08-01 17:53:29 +0000262static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
scroggo@google.com5239c322012-09-11 19:15:32 +0000263 sk_tools::PictureBenchmark* benchmark) {
reed@google.com006db0f2012-06-27 19:33:29 +0000264 const char* argv0 = argv[0];
265 char* const* stop = argv + argc;
266
keyar@chromium.org163b5672012-08-01 17:53:29 +0000267 int repeats = DEFAULT_REPEATS;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000268 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
269 sk_tools::PictureRenderer::kBitmap_DeviceType;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000270
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000271 SkAutoTUnref<sk_tools::PictureRenderer> renderer(NULL);
scroggo@google.com5239c322012-09-11 19:15:32 +0000272
scroggo@google.com9a412522012-09-07 15:21:18 +0000273 // Create a string to show our current settings.
274 // TODO: Make it prettier. Currently it just repeats the command line.
275 SkString commandLine("bench_pictures:");
276 for (int i = 1; i < argc; i++) {
277 commandLine.appendf(" %s", *(argv+i));
278 }
279 commandLine.append("\n");
280
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000281 bool usePipe = false;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000282 int numThreads = 1;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000283 bool useTiles = false;
284 const char* widthString = NULL;
285 const char* heightString = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000286 int gridWidth = 0;
287 int gridHeight = 0;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000288 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000289 bool isCopyMode = false;
290 const char* xTilesString = NULL;
291 const char* yTilesString = NULL;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000292 const char* mode = NULL;
junov@chromium.org7b537062012-11-06 18:58:43 +0000293 bool gridSupported = false;
skia.committer@gmail.com1aa90cf2012-11-06 13:18:25 +0000294 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
junov@chromium.org9313ca42012-11-02 18:11:49 +0000295 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
caryclark@google.coma3622372012-11-06 21:26:13 +0000296 sk_tools::PictureRenderer::DrawFilterFlags drawFilters[SkDrawFilter::kTypeCount];
297 sk_bzero(drawFilters, sizeof(drawFilters));
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000298 SkISize viewport;
299 viewport.setEmpty();
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000300 SkScalar scaleFactor = SK_Scalar1;
reed@google.com006db0f2012-06-27 19:33:29 +0000301 for (++argv; argv < stop; ++argv) {
302 if (0 == strcmp(*argv, "--repeat")) {
303 ++argv;
304 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000305 repeats = atoi(*argv);
306 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000307 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000308 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000309 }
310 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000311 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000312 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000313 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000314 } else if (0 == strcmp(*argv, "--pipe")) {
315 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000316 } else if (0 == strcmp(*argv, "--logFile")) {
317 argv++;
318 if (argv < stop) {
319 if (!gLogger.SetLogFile(*argv)) {
320 SkString str;
321 str.printf("Could not open %s for writing.", *argv);
322 gLogger.logError(str);
323 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000324 // TODO(borenet): We're disabling this for now, due to
325 // write-protected Android devices. The very short-term
326 // solution is to ignore the fact that we have no log file.
327 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000328 }
329 } else {
330 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000331 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000332 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000333 } else if (0 == strcmp(*argv, "--multi")) {
334 ++argv;
335 if (argv >= stop) {
336 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000337 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000338 }
339 numThreads = atoi(*argv);
340 if (numThreads < 2) {
341 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000342 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000343 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000344 } else if (0 == strcmp(*argv, "--bbh")) {
345 ++argv;
346 if (argv >= stop) {
347 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000348 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000349 }
350 if (0 == strcmp(*argv, "none")) {
351 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
352 } else if (0 == strcmp(*argv, "rtree")) {
353 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000354 } else if (0 == strcmp(*argv, "grid")) {
355 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
356 ++argv;
357 if (argv >= stop) {
358 gLogger.logError("Missing width for --bbh grid\n");
359 PRINT_USAGE_AND_EXIT;
360 }
361 gridWidth = atoi(*argv);
362 ++argv;
363 if (argv >= stop) {
364 gLogger.logError("Missing height for --bbh grid\n");
365 PRINT_USAGE_AND_EXIT;
366 }
367 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000368 } else {
369 SkString err;
370 err.printf("%s is not a valid value for --bbhType\n", *argv);
371 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000372 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000373 }
374
keyar@chromium.org795cd472012-08-02 18:57:53 +0000375 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000376 if (renderer.get() != NULL) {
377 SkDebugf("Cannot combine modes.\n");
378 PRINT_USAGE_AND_EXIT;
379 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000380
reed@google.com006db0f2012-06-27 19:33:29 +0000381 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000382 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000383 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000384 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000385 }
386
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000387 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000388 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000389 gridSupported = true;
reed@google.com5a34fd32012-12-10 16:05:09 +0000390 } else if (0 == strcmp(*argv, "clone")) {
391 renderer.reset(sk_tools::CreatePictureCloneRenderer());
keyar@chromium.org795cd472012-08-02 18:57:53 +0000392 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000393 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000394 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
395 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000396 useTiles = true;
397 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000398
399 if (0 == strcmp(*argv, "pow2tile")) {
400 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000401 } else if (0 == strcmp(*argv, "copyTile")) {
402 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000403 } else {
404 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000405 }
406
keyar@chromium.org795cd472012-08-02 18:57:53 +0000407 ++argv;
408 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000409 SkString err;
410 err.printf("Missing width 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 }
414
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000415 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000416 ++argv;
417 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000418 SkString err;
419 err.appendf("Missing height for --mode %s\n", mode);
420 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000421 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000422 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000423 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000424 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000425 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000426 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000427 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
428 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000429 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000430 SkString err;
431 err.printf("%s is not a valid mode for --mode\n", *argv);
432 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000433 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000434 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000435 } else if (0 == strcmp(*argv, "--viewport")) {
436 ++argv;
437 if (argv >= stop) {
438 gLogger.logError("Missing width for --viewport\n");
439 PRINT_USAGE_AND_EXIT;
440 }
441 viewport.fWidth = atoi(*argv);
442 ++argv;
443 if (argv >= stop) {
444 gLogger.logError("Missing height for --viewport\n");
445 PRINT_USAGE_AND_EXIT;
446 }
447 viewport.fHeight = atoi(*argv);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000448 } else if (0 == strcmp(*argv, "--scale")) {
449 ++argv;
450 if (argv >= stop) {
451 gLogger.logError("Missing scaleFactor for --scale\n");
452 PRINT_USAGE_AND_EXIT;
453 }
reed@google.com89d15a22013-01-07 22:26:05 +0000454 scaleFactor = SkDoubleToScalar(atof(*argv));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000455 } else if (0 == strcmp(*argv, "--tiles")) {
456 ++argv;
457 if (argv >= stop) {
458 gLogger.logError("Missing x for --tiles\n");
459 PRINT_USAGE_AND_EXIT;
460 }
461 xTilesString = *argv;
462 ++argv;
463 if (argv >= stop) {
464 gLogger.logError("Missing y for --tiles\n");
465 PRINT_USAGE_AND_EXIT;
466 }
467 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000468 } else if (0 == strcmp(*argv, "--device")) {
469 ++argv;
470 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000471 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000472 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000473 }
474
475 if (0 == strcmp(*argv, "bitmap")) {
476 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
477 }
478#if SK_SUPPORT_GPU
479 else if (0 == strcmp(*argv, "gpu")) {
480 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
481 }
482#endif
483 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000484 SkString err;
485 err.printf("%s is not a valid mode for --device\n", *argv);
486 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000487 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000488 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000489 } else if (0 == strcmp(*argv, "--timers")) {
490 ++argv;
491 if (argv < stop) {
492 bool timerWall = false;
493 bool truncatedTimerWall = false;
494 bool timerCpu = false;
495 bool truncatedTimerCpu = false;
496 bool timerGpu = false;
497 for (char* t = *argv; *t; ++t) {
498 switch (*t) {
499 case 'w':
500 timerWall = true;
501 break;
502 case 'c':
503 timerCpu = true;
504 break;
505 case 'W':
506 truncatedTimerWall = true;
507 break;
508 case 'C':
509 truncatedTimerCpu = true;
510 break;
511 case 'g':
512 timerGpu = true;
513 break;
514 default: {
515 break;
516 }
517 }
518 }
519 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
520 truncatedTimerCpu, timerGpu);
521 } else {
522 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000523 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000524 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000525 } else if (0 == strcmp(*argv, "--timeIndividualTiles")) {
526 benchmark->setTimeIndividualTiles(true);
scroggo@google.com5239c322012-09-11 19:15:32 +0000527 } else if (0 == strcmp(*argv, "--min")) {
528 benchmark->setPrintMin(true);
529 } else if (0 == strcmp(*argv, "--logPerIter")) {
530 ++argv;
531 if (argv < stop) {
532 bool log = atoi(*argv) != 0;
533 benchmark->setLogPerIter(log);
534 } else {
535 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000536 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000537 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000538 } else if (0 == strcmp(*argv, "--filter")) {
539 ++argv;
540 if (argv < stop) {
541 const char* colon = strchr(*argv, ':');
542 if (colon) {
543 int type = -1;
544 size_t typeLen = colon - *argv;
545 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
546 if (typeLen == strlen(gFilterTypes[tIndex])
547 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
548 type = tIndex;
549 break;
550 }
551 }
552 if (type < 0) {
553 SkString err;
554 err.printf("Unknown type for --filter %s\n", *argv);
555 gLogger.logError(err);
556 PRINT_USAGE_AND_EXIT;
557 }
558 int flag = -1;
559 size_t flagLen = strlen(*argv) - typeLen - 1;
560 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
561 if (flagLen == strlen(gFilterFlags[fIndex])
562 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
563 flag = 1 << fIndex;
564 break;
565 }
566 }
567 if (flag < 0) {
568 SkString err;
569 err.printf("Unknown flag for --filter %s\n", *argv);
570 gLogger.logError(err);
571 PRINT_USAGE_AND_EXIT;
572 }
573 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
574 if (type != SkDrawFilter::kTypeCount && index != type) {
575 continue;
576 }
577 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
578 (drawFilters[index] | flag);
579 }
580 } else {
581 SkString err;
582 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
583 gLogger.logError(err);
584 PRINT_USAGE_AND_EXIT;
585 }
586 } else {
587 gLogger.logError("Missing arg for --filter\n");
588 PRINT_USAGE_AND_EXIT;
589 }
reed@google.com006db0f2012-06-27 19:33:29 +0000590 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000591 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000592 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000593 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000594 }
595 }
596
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000597 if (numThreads > 1 && !useTiles) {
598 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000599 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000600 }
601
junov@chromium.org9313ca42012-11-02 18:11:49 +0000602 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
603 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000604 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000605 }
606
junov@chromium.org7b537062012-11-06 18:58:43 +0000607 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
608 !gridSupported) {
609 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
610 PRINT_USAGE_AND_EXIT;
611 }
612
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000613 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000614 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000615 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000616 if (isCopyMode) {
617 int x, y;
618 if (xTilesString != NULL) {
619 SkASSERT(yTilesString != NULL);
620 x = atoi(xTilesString);
621 y = atoi(yTilesString);
622 if (x <= 0 || y <= 0) {
623 gLogger.logError("--tiles must be given values > 0\n");
624 PRINT_USAGE_AND_EXIT;
625 }
626 } else {
627 x = y = 4;
628 }
629 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
scroggo@google.comcbcef702012-12-13 22:09:28 +0000630 if (benchmark->timeIndividualTiles()) {
631 gLogger.logError("timeIndividualTiles is not compatible with copyTile\n");
632 PRINT_USAGE_AND_EXIT;
633 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000634 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000635 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
636 } else {
637 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
638 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000639 if (isPowerOf2Mode) {
640 int minWidth = atoi(widthString);
641 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000642 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000643 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000644 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000645 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000646 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000647 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000648 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000649 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000650 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000651 if (isCopyMode) {
652 tiledRenderer->unref();
653 SkString err;
654 err.printf("--mode %s does not support percentages.\n", mode);
655 gLogger.logError(err.c_str());
656 PRINT_USAGE_AND_EXIT;
657 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000658 tiledRenderer->setTileWidthPercentage(atof(widthString));
659 if (!(tiledRenderer->getTileWidthPercentage() > 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 percentage > 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 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000667 tiledRenderer->setTileWidth(atoi(widthString));
668 if (!(tiledRenderer->getTileWidth() > 0)) {
669 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000670 SkString err;
671 err.appendf("--mode %s must be given a width > 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 }
676
677 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000678 if (isCopyMode) {
679 tiledRenderer->unref();
680 SkString err;
681 err.printf("--mode %s does not support percentages.\n", mode);
682 gLogger.logError(err.c_str());
683 PRINT_USAGE_AND_EXIT;
684 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000685 tiledRenderer->setTileHeightPercentage(atof(heightString));
686 if (!(tiledRenderer->getTileHeightPercentage() > 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 percentage > 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 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000694 tiledRenderer->setTileHeight(atoi(heightString));
695 if (!(tiledRenderer->getTileHeight() > 0)) {
696 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000697 SkString err;
698 err.appendf("--mode %s must be given a height > 0\n", mode);
699 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000700 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000701 }
702 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000703 if (numThreads > 1) {
704#if SK_SUPPORT_GPU
705 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
706 tiledRenderer->unref();
707 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000708 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000709 }
710#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000711 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000712 renderer.reset(tiledRenderer);
713 if (usePipe) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000714 gLogger.logError("Pipe rendering is currently not compatible with tiling.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000715 "Turning off pipe.\n");
716 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000717 } else {
718 if (benchmark->timeIndividualTiles()) {
719 gLogger.logError("timeIndividualTiles requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000720 PRINT_USAGE_AND_EXIT;
721 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000722 if (usePipe) {
723 if (renderer.get() != NULL) {
724 gLogger.logError("Pipe is incompatible with other modes.\n");
725 PRINT_USAGE_AND_EXIT;
726 }
727 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
728 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000729 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000730 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000731 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000732 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000733
scroggo@google.com5239c322012-09-11 19:15:32 +0000734 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000735 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000736 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000737
738 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000739 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000740 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000741 renderer->setViewport(viewport);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000742 renderer->setScaleFactor(scaleFactor);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000743 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000744 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000745 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000746 benchmark->setLogger(&gLogger);
747 // Report current settings:
748 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000749}
reed@google.com006db0f2012-06-27 19:33:29 +0000750
borenet@google.com66bcbd12012-09-17 18:26:06 +0000751static int process_input(const SkString& input,
752 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000753 SkOSFile::Iter iter(input.c_str(), "skp");
754 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000755 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000756 if (iter.next(&inputFilename)) {
757 do {
758 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000759 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000760 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000761 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000762 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000763 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000764 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
765 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000766 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000767 }
768 } else {
769 SkString warning;
770 warning.printf("Warning: skipping %s\n", input.c_str());
771 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000772 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000773 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000774}
775
caryclark@google.com5987f582012-10-02 18:33:14 +0000776int tool_main(int argc, char** argv);
777int tool_main(int argc, char** argv) {
bsalomon@google.com4e230682013-01-15 20:37:04 +0000778#if SK_ENABLE_INST_COUNT
scroggo@google.com5239c322012-09-11 19:15:32 +0000779 gPrintInstCount = true;
780#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000781 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000782
scroggo@google.com5239c322012-09-11 19:15:32 +0000783 SkTArray<SkString> inputs;
784 sk_tools::PictureBenchmark benchmark;
785
786 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000787
borenet@google.com66bcbd12012-09-17 18:26:06 +0000788 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000789 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000790 failures += process_input(inputs[i], benchmark);
791 }
792
793 if (failures != 0) {
794 SkString err;
795 err.printf("Failed to run %i benchmarks.\n", failures);
796 gLogger.logError(err);
797 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000798 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000799 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000800}
caryclark@google.com5987f582012-10-02 18:33:14 +0000801
802#if !defined SK_BUILD_FOR_IOS
803int main(int argc, char * const argv[]) {
804 return tool_main(argc, (char**) argv);
805}
806#endif