blob: 582cf43d430df47d59d8918a364c86b0daa972a3 [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",
53 "hinting",
54 "slightHinting",
caryclark@google.come3e940c2012-11-07 16:42:17 +000055 "AAClip",
caryclark@google.coma3622372012-11-06 21:26:13 +000056};
57
58static const size_t kFilterFlagsCount = sizeof(gFilterFlags) / sizeof(gFilterFlags[0]);
59
60static SkString filtersName(sk_tools::PictureRenderer::DrawFilterFlags* drawFilters) {
61 int all = drawFilters[0];
62 size_t tIndex;
63 for (tIndex = 1; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
64 all &= drawFilters[tIndex];
65 }
66 SkString result;
67 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
68 SkString types;
69 if (all & (1 << fIndex)) {
70 types = gFilterTypes[SkDrawFilter::kTypeCount];
71 } else {
72 for (tIndex = 0; tIndex < SkDrawFilter::kTypeCount; ++tIndex) {
73 if (drawFilters[tIndex] & (1 << fIndex)) {
74 types += gFilterTypes[tIndex];
75 }
76 }
77 }
78 if (!types.size()) {
79 continue;
80 }
81 result += "_";
82 result += types;
83 result += ".";
84 result += gFilterFlags[fIndex];
85 }
86 return result;
87}
88
89static SkString filterTypesUsage() {
90 SkString result;
91 for (size_t index = 0; index < kFilterTypesCount; ++index) {
92 result += gFilterTypes[index];
93 if (index < kFilterTypesCount - 1) {
94 result += " | ";
95 }
96 }
97 return result;
98}
99
100static SkString filterFlagsUsage() {
101 SkString result;
102 size_t len = 0;
103 for (size_t index = 0; index < kFilterFlagsCount; ++index) {
104 result += gFilterFlags[index];
105 if (result.size() - len >= 72) {
106 result += "\n ";
107 len = result.size();
108 }
109 if (index < kFilterFlagsCount - 1) {
110 result += " | ";
111 }
112 }
113 return result;
114}
115
reed@google.com006db0f2012-06-27 19:33:29 +0000116static void usage(const char* argv0) {
117 SkDebugf("SkPicture benchmarking tool\n");
118 SkDebugf("\n"
119"Usage: \n"
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000120" %s <inputDir>...\n"
scroggo@google.com5239c322012-09-11 19:15:32 +0000121" [--logFile filename][--timers [wcgWC]*][--logPerIter 1|0][--min]\n"
scroggo@google.comcbcef702012-12-13 22:09:28 +0000122" [--repeat][--timeIndividualTiles] \n"
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000123" [--mode pow2tile minWidth height | record | simple\n"
124" | tile width height | playbackCreation]\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000125" [--pipe]\n"
junov@chromium.org9313ca42012-11-02 18:11:49 +0000126" [--bbh bbhType]\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000127" [--multi numThreads]\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000128" [--viewport width height][--scale sf]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000129" [--device bitmap"
130#if SK_SUPPORT_GPU
131" | gpu"
132#endif
caryclark@google.coma3622372012-11-06 21:26:13 +0000133"]\n"
134" [--filter [%s]:\n [%s]]\n"
135, argv0, filterTypesUsage().c_str(), filterFlagsUsage().c_str());
136 SkDebugf("\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000137 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000138" inputDir: A list of directories and files to use as input. Files are\n"
scroggo@google.com9a412522012-09-07 15:21:18 +0000139" expected to have the .skp extension.\n\n"
140" --logFile filename : destination for writing log output, in addition to stdout.\n");
scroggo@google.com5239c322012-09-11 19:15:32 +0000141 SkDebugf(" --logPerIter 1|0 : "
142 "Log each repeat timer instead of mean, default is disabled.\n");
143 SkDebugf(" --min : Print the minimum times (instead of average).\n");
144 SkDebugf(" --timers [wcgWC]* : "
145 "Display wall, cpu, gpu, truncated wall or truncated cpu time for each picture.\n");
scroggo@google.comcbcef702012-12-13 22:09:28 +0000146 SkDebugf(" --timeIndividualTiles : Report times for drawing individual tiles, rather than\n"
147" times for drawing the whole page.\n"
148" Requires --mode tile\n");
reed@google.com006db0f2012-06-27 19:33:29 +0000149 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000150" --mode pow2tile minWidth height | copyTile width height | record | simple\n"
151" | tile width height | playbackCreation:\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000152" Run in the corresponding mode.\n"
153" Default is simple.\n");
keyar@chromium.orgcf6c44c2012-07-09 19:37:40 +0000154 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000155" pow2tile minWidth height, Creates tiles with widths\n"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000156" that are all a power of two\n"
157" such that they minimize the\n"
158" amount of wasted tile space.\n"
159" minWidth is the minimum width\n"
160" of these tiles and must be a\n"
161" power of two. Simple\n"
162" rendering using these tiles\n"
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000163" is benchmarked.\n");
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000164 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +0000165" record, Benchmark picture to picture recording.\n");
166 SkDebugf(
167" simple, Benchmark a simple rendering.\n");
168 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000169" tile width height, Benchmark simple rendering using\n"
170" tiles with the given dimensions.\n"
171" copyTile width height, Draw the picture, then copy it into tiles.\n"
172" Does not support percentages.\n"
173" If the picture is large enough, breaks it into\n"
174" larger tiles (and draws the picture once per\n"
175" larger tile) to avoid creating a large canvas.\n"
176" Add --tiles x y to specify the number of tiles\n"
177" per larger tile in the x and y direction.\n"
178 );
keyar@chromium.org795cd472012-08-02 18:57:53 +0000179 SkDebugf(
scroggo@google.com9a412522012-09-07 15:21:18 +0000180" playbackCreation, Benchmark creation of the SkPicturePlayback.\n");
keyar@chromium.org795cd472012-08-02 18:57:53 +0000181 SkDebugf("\n");
182 SkDebugf(
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000183" --multi numThreads : Set the number of threads for multi threaded drawing. Must be greater\n"
184" than 1. Only works with tiled rendering.\n"
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000185" --viewport width height : Set the viewport.\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000186" --scale sf : Scale drawing by sf.\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();
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000299 SkScalar scaleFactor = SK_Scalar1;
reed@google.com006db0f2012-06-27 19:33:29 +0000300 for (++argv; argv < stop; ++argv) {
301 if (0 == strcmp(*argv, "--repeat")) {
302 ++argv;
303 if (argv < stop) {
keyar@chromium.org163b5672012-08-01 17:53:29 +0000304 repeats = atoi(*argv);
305 if (repeats < 1) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000306 gLogger.logError("--repeat must be given a value > 0\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000307 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000308 }
309 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000310 gLogger.logError("Missing arg for --repeat\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000311 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000312 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000313 } else if (0 == strcmp(*argv, "--pipe")) {
314 usePipe = true;
scroggo@google.com9a412522012-09-07 15:21:18 +0000315 } else if (0 == strcmp(*argv, "--logFile")) {
316 argv++;
317 if (argv < stop) {
318 if (!gLogger.SetLogFile(*argv)) {
319 SkString str;
320 str.printf("Could not open %s for writing.", *argv);
321 gLogger.logError(str);
322 usage(argv0);
borenet@google.coma49bffd2012-09-13 18:54:48 +0000323 // TODO(borenet): We're disabling this for now, due to
324 // write-protected Android devices. The very short-term
325 // solution is to ignore the fact that we have no log file.
326 //exit(-1);
scroggo@google.com9a412522012-09-07 15:21:18 +0000327 }
328 } else {
329 gLogger.logError("Missing arg for --logFile\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000330 PRINT_USAGE_AND_EXIT;
scroggo@google.com9a412522012-09-07 15:21:18 +0000331 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000332 } else if (0 == strcmp(*argv, "--multi")) {
333 ++argv;
334 if (argv >= stop) {
335 gLogger.logError("Missing arg for --multi\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000336 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000337 }
338 numThreads = atoi(*argv);
339 if (numThreads < 2) {
340 gLogger.logError("Number of threads must be at least 2.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000341 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000342 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000343 } else if (0 == strcmp(*argv, "--bbh")) {
344 ++argv;
345 if (argv >= stop) {
346 gLogger.logError("Missing value for --bbh\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000347 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000348 }
349 if (0 == strcmp(*argv, "none")) {
350 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
351 } else if (0 == strcmp(*argv, "rtree")) {
352 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
junov@chromium.org7b537062012-11-06 18:58:43 +0000353 } else if (0 == strcmp(*argv, "grid")) {
354 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
355 ++argv;
356 if (argv >= stop) {
357 gLogger.logError("Missing width for --bbh grid\n");
358 PRINT_USAGE_AND_EXIT;
359 }
360 gridWidth = atoi(*argv);
361 ++argv;
362 if (argv >= stop) {
363 gLogger.logError("Missing height for --bbh grid\n");
364 PRINT_USAGE_AND_EXIT;
365 }
366 gridHeight = atoi(*argv);
junov@chromium.org9313ca42012-11-02 18:11:49 +0000367 } else {
368 SkString err;
369 err.printf("%s is not a valid value for --bbhType\n", *argv);
370 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000371 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000372 }
373
keyar@chromium.org795cd472012-08-02 18:57:53 +0000374 } else if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000375 if (renderer.get() != NULL) {
376 SkDebugf("Cannot combine modes.\n");
377 PRINT_USAGE_AND_EXIT;
378 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000379
reed@google.com006db0f2012-06-27 19:33:29 +0000380 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000381 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000382 gLogger.logError("Missing mode for --mode\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000383 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000384 }
385
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000386 if (0 == strcmp(*argv, "record")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000387 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000388 gridSupported = true;
reed@google.com5a34fd32012-12-10 16:05:09 +0000389 } else if (0 == strcmp(*argv, "clone")) {
390 renderer.reset(sk_tools::CreatePictureCloneRenderer());
keyar@chromium.org795cd472012-08-02 18:57:53 +0000391 } else if (0 == strcmp(*argv, "simple")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000392 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000393 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
394 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000395 useTiles = true;
396 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000397
398 if (0 == strcmp(*argv, "pow2tile")) {
399 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000400 } else if (0 == strcmp(*argv, "copyTile")) {
401 isCopyMode = true;
junov@chromium.org7b537062012-11-06 18:58:43 +0000402 } else {
403 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000404 }
405
keyar@chromium.org795cd472012-08-02 18:57:53 +0000406 ++argv;
407 if (argv >= stop) {
scroggo@google.com9a412522012-09-07 15:21:18 +0000408 SkString err;
409 err.printf("Missing width for --mode %s\n", mode);
410 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000411 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000412 }
413
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000414 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000415 ++argv;
416 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000417 SkString err;
418 err.appendf("Missing height for --mode %s\n", mode);
419 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000420 PRINT_USAGE_AND_EXIT;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000421 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000422 heightString = *argv;
scroggo@google.com9a412522012-09-07 15:21:18 +0000423 } else if (0 == strcmp(*argv, "playbackCreation")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000424 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
junov@chromium.org7b537062012-11-06 18:58:43 +0000425 gridSupported = true;
reed@google.comfe7b1ed2012-11-29 21:00:39 +0000426 } else if (0 == strcmp(*argv, "gatherPixelRefs")) {
427 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
reed@google.com006db0f2012-06-27 19:33:29 +0000428 } else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000429 SkString err;
430 err.printf("%s is not a valid mode for --mode\n", *argv);
431 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000432 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000433 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000434 } else if (0 == strcmp(*argv, "--viewport")) {
435 ++argv;
436 if (argv >= stop) {
437 gLogger.logError("Missing width for --viewport\n");
438 PRINT_USAGE_AND_EXIT;
439 }
440 viewport.fWidth = atoi(*argv);
441 ++argv;
442 if (argv >= stop) {
443 gLogger.logError("Missing height for --viewport\n");
444 PRINT_USAGE_AND_EXIT;
445 }
446 viewport.fHeight = atoi(*argv);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000447 } else if (0 == strcmp(*argv, "--scale")) {
448 ++argv;
449 if (argv >= stop) {
450 gLogger.logError("Missing scaleFactor for --scale\n");
451 PRINT_USAGE_AND_EXIT;
452 }
reed@google.com89d15a22013-01-07 22:26:05 +0000453 scaleFactor = SkDoubleToScalar(atof(*argv));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000454 } else if (0 == strcmp(*argv, "--tiles")) {
455 ++argv;
456 if (argv >= stop) {
457 gLogger.logError("Missing x for --tiles\n");
458 PRINT_USAGE_AND_EXIT;
459 }
460 xTilesString = *argv;
461 ++argv;
462 if (argv >= stop) {
463 gLogger.logError("Missing y for --tiles\n");
464 PRINT_USAGE_AND_EXIT;
465 }
466 yTilesString = *argv;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000467 } else if (0 == strcmp(*argv, "--device")) {
468 ++argv;
469 if (argv >= stop) {
borenet@google.coma49bffd2012-09-13 18:54:48 +0000470 gLogger.logError("Missing mode for --device\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000471 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000472 }
473
474 if (0 == strcmp(*argv, "bitmap")) {
475 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
476 }
477#if SK_SUPPORT_GPU
478 else if (0 == strcmp(*argv, "gpu")) {
479 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
480 }
481#endif
482 else {
scroggo@google.com9a412522012-09-07 15:21:18 +0000483 SkString err;
484 err.printf("%s is not a valid mode for --device\n", *argv);
485 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000486 PRINT_USAGE_AND_EXIT;
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000487 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000488 } else if (0 == strcmp(*argv, "--timers")) {
489 ++argv;
490 if (argv < stop) {
491 bool timerWall = false;
492 bool truncatedTimerWall = false;
493 bool timerCpu = false;
494 bool truncatedTimerCpu = false;
495 bool timerGpu = false;
496 for (char* t = *argv; *t; ++t) {
497 switch (*t) {
498 case 'w':
499 timerWall = true;
500 break;
501 case 'c':
502 timerCpu = true;
503 break;
504 case 'W':
505 truncatedTimerWall = true;
506 break;
507 case 'C':
508 truncatedTimerCpu = true;
509 break;
510 case 'g':
511 timerGpu = true;
512 break;
513 default: {
514 break;
515 }
516 }
517 }
518 benchmark->setTimersToShow(timerWall, truncatedTimerWall, timerCpu,
519 truncatedTimerCpu, timerGpu);
520 } else {
521 gLogger.logError("Missing arg for --timers\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000522 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000523 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000524 } else if (0 == strcmp(*argv, "--timeIndividualTiles")) {
525 benchmark->setTimeIndividualTiles(true);
scroggo@google.com5239c322012-09-11 19:15:32 +0000526 } else if (0 == strcmp(*argv, "--min")) {
527 benchmark->setPrintMin(true);
528 } else if (0 == strcmp(*argv, "--logPerIter")) {
529 ++argv;
530 if (argv < stop) {
531 bool log = atoi(*argv) != 0;
532 benchmark->setLogPerIter(log);
533 } else {
534 gLogger.logError("Missing arg for --logPerIter\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000535 PRINT_USAGE_AND_EXIT;
scroggo@google.com5239c322012-09-11 19:15:32 +0000536 }
caryclark@google.coma3622372012-11-06 21:26:13 +0000537 } else if (0 == strcmp(*argv, "--filter")) {
538 ++argv;
539 if (argv < stop) {
540 const char* colon = strchr(*argv, ':');
541 if (colon) {
542 int type = -1;
543 size_t typeLen = colon - *argv;
544 for (size_t tIndex = 0; tIndex < kFilterTypesCount; ++tIndex) {
545 if (typeLen == strlen(gFilterTypes[tIndex])
546 && !strncmp(*argv, gFilterTypes[tIndex], typeLen)) {
547 type = tIndex;
548 break;
549 }
550 }
551 if (type < 0) {
552 SkString err;
553 err.printf("Unknown type for --filter %s\n", *argv);
554 gLogger.logError(err);
555 PRINT_USAGE_AND_EXIT;
556 }
557 int flag = -1;
558 size_t flagLen = strlen(*argv) - typeLen - 1;
559 for (size_t fIndex = 0; fIndex < kFilterFlagsCount; ++fIndex) {
560 if (flagLen == strlen(gFilterFlags[fIndex])
561 && !strncmp(colon + 1, gFilterFlags[fIndex], flagLen)) {
562 flag = 1 << fIndex;
563 break;
564 }
565 }
566 if (flag < 0) {
567 SkString err;
568 err.printf("Unknown flag for --filter %s\n", *argv);
569 gLogger.logError(err);
570 PRINT_USAGE_AND_EXIT;
571 }
572 for (int index = 0; index < SkDrawFilter::kTypeCount; ++index) {
573 if (type != SkDrawFilter::kTypeCount && index != type) {
574 continue;
575 }
576 drawFilters[index] = (sk_tools::PictureRenderer::DrawFilterFlags)
577 (drawFilters[index] | flag);
578 }
579 } else {
580 SkString err;
581 err.printf("Unknown arg for --filter %s : missing colon\n", *argv);
582 gLogger.logError(err);
583 PRINT_USAGE_AND_EXIT;
584 }
585 } else {
586 gLogger.logError("Missing arg for --filter\n");
587 PRINT_USAGE_AND_EXIT;
588 }
reed@google.com006db0f2012-06-27 19:33:29 +0000589 } else if (0 == strcmp(*argv, "--help") || 0 == strcmp(*argv, "-h")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000590 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000591 } else {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000592 inputs->push_back(SkString(*argv));
reed@google.com006db0f2012-06-27 19:33:29 +0000593 }
594 }
595
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000596 if (numThreads > 1 && !useTiles) {
597 gLogger.logError("Multithreaded drawing requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000598 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000599 }
600
junov@chromium.org9313ca42012-11-02 18:11:49 +0000601 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
602 gLogger.logError("--pipe and --bbh cannot be used together\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000603 PRINT_USAGE_AND_EXIT;
junov@chromium.org9313ca42012-11-02 18:11:49 +0000604 }
605
junov@chromium.org7b537062012-11-06 18:58:43 +0000606 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
607 !gridSupported) {
608 gLogger.logError("'--bbh grid' is not compatible with specified --mode.\n");
609 PRINT_USAGE_AND_EXIT;
610 }
611
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000612 if (useTiles) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000613 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000614 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000615 if (isCopyMode) {
616 int x, y;
617 if (xTilesString != NULL) {
618 SkASSERT(yTilesString != NULL);
619 x = atoi(xTilesString);
620 y = atoi(yTilesString);
621 if (x <= 0 || y <= 0) {
622 gLogger.logError("--tiles must be given values > 0\n");
623 PRINT_USAGE_AND_EXIT;
624 }
625 } else {
626 x = y = 4;
627 }
628 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
scroggo@google.comcbcef702012-12-13 22:09:28 +0000629 if (benchmark->timeIndividualTiles()) {
630 gLogger.logError("timeIndividualTiles is not compatible with copyTile\n");
631 PRINT_USAGE_AND_EXIT;
632 }
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000633 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000634 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
635 } else {
636 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
637 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000638 if (isPowerOf2Mode) {
639 int minWidth = atoi(widthString);
640 if (!SkIsPow2(minWidth) || minWidth < 0) {
scroggo@google.com5239c322012-09-11 19:15:32 +0000641 tiledRenderer->unref();
scroggo@google.com9a412522012-09-07 15:21:18 +0000642 SkString err;
scroggo@google.com5239c322012-09-11 19:15:32 +0000643 err.printf("-mode %s must be given a width"
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000644 " value that is a power of two\n", mode);
scroggo@google.com9a412522012-09-07 15:21:18 +0000645 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 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000648 tiledRenderer->setTileMinPowerOf2Width(minWidth);
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000649 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000650 if (isCopyMode) {
651 tiledRenderer->unref();
652 SkString err;
653 err.printf("--mode %s does not support percentages.\n", mode);
654 gLogger.logError(err.c_str());
655 PRINT_USAGE_AND_EXIT;
656 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000657 tiledRenderer->setTileWidthPercentage(atof(widthString));
658 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
659 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000660 SkString err;
661 err.appendf("--mode %s must be given a width percentage > 0\n", mode);
662 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000663 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000664 }
665 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000666 tiledRenderer->setTileWidth(atoi(widthString));
667 if (!(tiledRenderer->getTileWidth() > 0)) {
668 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000669 SkString err;
670 err.appendf("--mode %s must be given a width > 0\n", mode);
671 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000672 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000673 }
674 }
675
676 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000677 if (isCopyMode) {
678 tiledRenderer->unref();
679 SkString err;
680 err.printf("--mode %s does not support percentages.\n", mode);
681 gLogger.logError(err.c_str());
682 PRINT_USAGE_AND_EXIT;
683 }
scroggo@google.com5239c322012-09-11 19:15:32 +0000684 tiledRenderer->setTileHeightPercentage(atof(heightString));
685 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
686 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000687 SkString err;
688 err.appendf("--mode %s must be given a height percentage > 0\n", mode);
689 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000690 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000691 }
692 } else {
scroggo@google.com5239c322012-09-11 19:15:32 +0000693 tiledRenderer->setTileHeight(atoi(heightString));
694 if (!(tiledRenderer->getTileHeight() > 0)) {
695 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000696 SkString err;
697 err.appendf("--mode %s must be given a height > 0\n", mode);
698 gLogger.logError(err);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000699 PRINT_USAGE_AND_EXIT;
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000700 }
701 }
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000702 if (numThreads > 1) {
703#if SK_SUPPORT_GPU
704 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
705 tiledRenderer->unref();
706 gLogger.logError("GPU not compatible with multithreaded tiling.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000707 PRINT_USAGE_AND_EXIT;
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000708 }
709#endif
scroggo@google.combcdf2ec2012-09-20 14:42:33 +0000710 }
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000711 renderer.reset(tiledRenderer);
712 if (usePipe) {
scroggo@google.comcbcef702012-12-13 22:09:28 +0000713 gLogger.logError("Pipe rendering is currently not compatible with tiling.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000714 "Turning off pipe.\n");
715 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000716 } else {
717 if (benchmark->timeIndividualTiles()) {
718 gLogger.logError("timeIndividualTiles requires tiled rendering.\n");
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000719 PRINT_USAGE_AND_EXIT;
720 }
scroggo@google.comcbcef702012-12-13 22:09:28 +0000721 if (usePipe) {
722 if (renderer.get() != NULL) {
723 gLogger.logError("Pipe is incompatible with other modes.\n");
724 PRINT_USAGE_AND_EXIT;
725 }
726 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
727 }
scroggo@google.com58b4ead2012-08-31 16:15:22 +0000728 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000729 if (inputs->count() < 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000730 PRINT_USAGE_AND_EXIT;
reed@google.com006db0f2012-06-27 19:33:29 +0000731 }
keyar@chromium.org163b5672012-08-01 17:53:29 +0000732
scroggo@google.com5239c322012-09-11 19:15:32 +0000733 if (NULL == renderer) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000734 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
keyar@chromium.org163b5672012-08-01 17:53:29 +0000735 }
junov@chromium.org9313ca42012-11-02 18:11:49 +0000736
737 renderer->setBBoxHierarchyType(bbhType);
caryclark@google.coma3622372012-11-06 21:26:13 +0000738 renderer->setDrawFilters(drawFilters, filtersName(drawFilters));
junov@chromium.org7b537062012-11-06 18:58:43 +0000739 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000740 renderer->setViewport(viewport);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000741 renderer->setScaleFactor(scaleFactor);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000742 benchmark->setRenderer(renderer);
keyar@chromium.org163b5672012-08-01 17:53:29 +0000743 benchmark->setRepeats(repeats);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000744 benchmark->setDeviceType(deviceType);
scroggo@google.com9a412522012-09-07 15:21:18 +0000745 benchmark->setLogger(&gLogger);
746 // Report current settings:
747 gLogger.logProgress(commandLine);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000748}
reed@google.com006db0f2012-06-27 19:33:29 +0000749
borenet@google.com66bcbd12012-09-17 18:26:06 +0000750static int process_input(const SkString& input,
751 sk_tools::PictureBenchmark& benchmark) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000752 SkOSFile::Iter iter(input.c_str(), "skp");
753 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000754 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000755 if (iter.next(&inputFilename)) {
756 do {
757 SkString inputPath;
keyar@chromium.org163b5672012-08-01 17:53:29 +0000758 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000759 if (!run_single_benchmark(inputPath, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000760 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000761 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000762 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000763 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
764 if (!run_single_benchmark(input, benchmark)) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000765 ++failures;
borenet@google.com57837bf2012-09-19 17:28:29 +0000766 }
767 } else {
768 SkString warning;
769 warning.printf("Warning: skipping %s\n", input.c_str());
770 gLogger.logError(warning);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000771 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000772 return failures;
reed@google.com006db0f2012-06-27 19:33:29 +0000773}
774
caryclark@google.com5987f582012-10-02 18:33:14 +0000775int tool_main(int argc, char** argv);
776int tool_main(int argc, char** argv) {
bsalomon@google.com4e230682013-01-15 20:37:04 +0000777#if SK_ENABLE_INST_COUNT
scroggo@google.com5239c322012-09-11 19:15:32 +0000778 gPrintInstCount = true;
779#endif
scroggo@google.com0a36f432012-09-10 20:29:13 +0000780 SkAutoGraphics ag;
reed@google.com006db0f2012-06-27 19:33:29 +0000781
scroggo@google.com5239c322012-09-11 19:15:32 +0000782 SkTArray<SkString> inputs;
783 sk_tools::PictureBenchmark benchmark;
784
785 parse_commandline(argc, argv, &inputs, &benchmark);
reed@google.com006db0f2012-06-27 19:33:29 +0000786
borenet@google.com66bcbd12012-09-17 18:26:06 +0000787 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000788 for (int i = 0; i < inputs.count(); ++i) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000789 failures += process_input(inputs[i], benchmark);
790 }
791
792 if (failures != 0) {
793 SkString err;
794 err.printf("Failed to run %i benchmarks.\n", failures);
795 gLogger.logError(err);
796 return 1;
reed@google.com006db0f2012-06-27 19:33:29 +0000797 }
caryclark@google.com868e1f62012-10-02 20:00:03 +0000798 return 0;
reed@google.com006db0f2012-06-27 19:33:29 +0000799}
caryclark@google.com5987f582012-10-02 18:33:14 +0000800
801#if !defined SK_BUILD_FOR_IOS
802int main(int argc, char * const argv[]) {
803 return tool_main(argc, (char**) argv);
804}
805#endif