blob: e7ae0362d7ec60ee4d5e81fe28e10ae9cf385fb2 [file] [log] [blame]
junov@chromium.org777442d2012-06-12 14:56:36 +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
scroggo@google.com4a26d9d2012-11-07 18:01:46 +00008#include "CopyTilesRenderer.h"
junov@chromium.org777442d2012-06-12 14:56:36 +00009#include "SkBitmap.h"
10#include "SkCanvas.h"
keyar@chromium.org472b3792012-07-20 22:34:27 +000011#include "SkDevice.h"
borenet@google.com10ef79e2012-09-10 17:19:06 +000012#include "SkGraphics.h"
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000013#include "SkImageDecoder.h"
edisonn@google.com84f548c2012-12-18 22:24:03 +000014#include "SkImageEncoder.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000015#include "SkMath.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000016#include "SkOSFile.h"
17#include "SkPicture.h"
18#include "SkStream.h"
19#include "SkString.h"
senorblanco@chromium.org3cbbb542012-07-13 18:55:53 +000020#include "SkTArray.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000021#include "PictureRenderer.h"
twiz@google.coma31b8bb2012-06-22 18:24:56 +000022#include "picture_utils.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000023
junov@chromium.org777442d2012-06-12 14:56:36 +000024static void usage(const char* argv0) {
25 SkDebugf("SkPicture rendering tool\n");
26 SkDebugf("\n"
27"Usage: \n"
borenet@google.com070d3542012-10-26 13:26:55 +000028" %s <input>... \n"
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000029" [-w <outputDir>]\n"
30" [--mode pow2tile minWidth height | copyTile width height | simple\n"
31" | tile width height]\n"
scroggo@google.comb6e806b2012-10-03 17:32:33 +000032" [--pipe]\n"
edisonn@google.com84f548c2012-12-18 22:24:03 +000033" [--bbh bbhType]\n"
scroggo@google.comb6e806b2012-10-03 17:32:33 +000034" [--multi count]\n"
edisonn@google.com84f548c2012-12-18 22:24:03 +000035" [--validate]\n"
36" [--writeWholeImage]\n"
37" [--clone n]\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +000038" [--viewport width height][--scale sf]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000039" [--device bitmap"
40#if SK_SUPPORT_GPU
41" | gpu"
42#endif
43"]"
junov@chromium.org777442d2012-06-12 14:56:36 +000044, argv0);
keyar@chromium.org472b3792012-07-20 22:34:27 +000045 SkDebugf("\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000046 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000047" input: A list of directories and files to use as input. Files are\n"
48" expected to have the .skp extension.\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000049 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000050" outputDir: directory to write the rendered images.\n\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000051 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000052" --mode pow2tile minWidth height | copyTile width height | simple\n"
53" | tile width height | rerecord: Run in the corresponding mode.\n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000054" Default is simple.\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000055 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000056" pow2tile minWidth height, Creates tiles with widths\n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000057" that are all a power of two\n"
58" such that they minimize the\n"
59" amount of wasted tile space.\n"
60" minWidth is the minimum width\n"
61" of these tiles and must be a\n"
62" power of two. A simple render\n"
63" is done with these tiles.\n");
64 SkDebugf(
scroggo@google.coma9e3a362012-11-07 17:52:48 +000065" simple, Render using the default rendering method.\n"
66" rerecord, Record the picture as a new skp, with the bitmaps PNG encoded.\n"
67 );
keyar@chromium.org795cd472012-08-02 18:57:53 +000068 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000069" tile width height, Do a simple render using tiles\n"
70" with the given dimensions.\n"
71" copyTile width height, Draw the picture, then copy it into tiles.\n"
72" Does not support percentages.\n"
73" If the picture is large enough, breaks it into\n"
74" larger tiles (and draws the picture once per\n"
75" larger tile) to avoid creating a large canvas.\n"
76" Add --tiles x y to specify the number of tiles\n"
77" per larger tile in the x and y direction.\n"
78 );
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000079 SkDebugf("\n");
80 SkDebugf(
scroggo@google.comb6e806b2012-10-03 17:32:33 +000081" --multi count : Set the number of threads for multi threaded drawing. Must be greater\n"
82" than 1. Only works with tiled rendering.\n"
scroggo@google.comc0d5e542012-12-13 21:40:48 +000083" --viewport width height : Set the viewport.\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +000084" --scale sf : Scale drawing by sf.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +000085" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.comb6e806b2012-10-03 17:32:33 +000086 SkDebugf(
edisonn@google.com84f548c2012-12-18 22:24:03 +000087" --validate: Verify that the rendered image contains the same pixels as "
88"the picture rendered in simple mode.\n"
89" --writeWholeImage: In tile mode, write the entire rendered image to a "
90"file, instead of an image for each tile.\n");
91 SkDebugf(
92" --clone n: Clone the picture n times before rendering.\n");
93 SkDebugf(
94" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
95" be used. Accepted values are: none, rtree, grid. Default\n"
96" value is none. Not compatible with --pipe. With value\n"
97" 'grid', width and height must be specified. 'grid' can\n"
98" only be used with modes tile, record, and\n"
99" playbackCreation.");
100 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000101" --device bitmap"
102#if SK_SUPPORT_GPU
103" | gpu"
104#endif
105": Use the corresponding device. Default is bitmap.\n");
106 SkDebugf(
107" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000108#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000109 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000110" gpu, Render to the GPU.\n");
111#endif
junov@chromium.org777442d2012-06-12 14:56:36 +0000112}
113
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000114static void make_output_filepath(SkString* path, const SkString& dir,
junov@chromium.org777442d2012-06-12 14:56:36 +0000115 const SkString& name) {
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000116 sk_tools::make_filepath(path, dir, name);
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000117 // Remove ".skp"
118 path->remove(path->size() - 4, 4);
junov@chromium.org777442d2012-06-12 14:56:36 +0000119}
120
borenet@google.com070d3542012-10-26 13:26:55 +0000121static bool render_picture(const SkString& inputPath, const SkString* outputDir,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000122 sk_tools::PictureRenderer& renderer,
123 SkBitmap** out,
124 int clones) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000125 SkString inputFilename;
126 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000127
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000128 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000129 inputStream.setPath(inputPath.c_str());
130 if (!inputStream.isValid()) {
131 SkDebugf("Could not open file %s\n", inputPath.c_str());
borenet@google.com66bcbd12012-09-17 18:26:06 +0000132 return false;
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000133 }
134
borenet@google.com66bcbd12012-09-17 18:26:06 +0000135 bool success = false;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000136 SkPicture* picture = SkNEW_ARGS(SkPicture,
137 (&inputStream, &success, &SkImageDecoder::DecodeStream));
borenet@google.com66bcbd12012-09-17 18:26:06 +0000138 if (!success) {
139 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
140 return false;
141 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000142
edisonn@google.com84f548c2012-12-18 22:24:03 +0000143 for (int i = 0; i < clones; ++i) {
144 SkPicture* clone = picture->clone();
145 SkDELETE(picture);
146 picture = clone;
147 }
148
149 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000150 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000151
edisonn@google.com84f548c2012-12-18 22:24:03 +0000152 renderer.init(picture);
scroggo@google.comb4773b42012-10-01 20:06:09 +0000153 renderer.setup();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000154
borenet@google.com070d3542012-10-26 13:26:55 +0000155 SkString* outputPath = NULL;
156 if (NULL != outputDir) {
157 outputPath = SkNEW(SkString);
158 make_output_filepath(outputPath, *outputDir, inputFilename);
159 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000160
161 success = renderer.render(outputPath, out);
borenet@google.com070d3542012-10-26 13:26:55 +0000162 if (outputPath) {
163 if (!success) {
164 SkDebugf("Could not write to file %s\n", outputPath->c_str());
165 }
166 SkDELETE(outputPath);
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000167 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000168
169 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000170
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000171 renderer.end();
edisonn@google.com84f548c2012-12-18 22:24:03 +0000172
173 SkDELETE(picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000174 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000175}
176
edisonn@google.com84f548c2012-12-18 22:24:03 +0000177static bool render_picture(const SkString& inputPath, const SkString* outputDir,
178 sk_tools::PictureRenderer& renderer,
179 bool validate,
180 bool writeWholeImage,
181 int clones) {
182 SkBitmap* bitmap = NULL;
183 bool success = render_picture(inputPath,
184 writeWholeImage ? NULL : outputDir,
185 renderer,
186 validate || writeWholeImage ? &bitmap : NULL, clones);
187
188 if (!success || ((validate || writeWholeImage) && bitmap == NULL)) {
189 SkDebugf("Failed to draw the picture.\n");
190 SkDELETE(bitmap);
191 return false;
192 }
193
194 if (validate) {
195 SkBitmap* referenceBitmap = NULL;
196 sk_tools::SimplePictureRenderer referenceRenderer;
197 success = render_picture(inputPath, NULL, referenceRenderer,
198 &referenceBitmap, 0);
199
200 if (!success || !referenceBitmap) {
201 SkDebugf("Failed to draw the reference picture.\n");
202 SkDELETE(bitmap);
203 SkDELETE(referenceBitmap);
204 return false;
205 }
206
207 if (success && (bitmap->width() != referenceBitmap->width())) {
208 SkDebugf("Expected image width: %i, actual image width %i.\n",
209 referenceBitmap->width(), bitmap->width());
210 SkDELETE(bitmap);
211 SkDELETE(referenceBitmap);
212 return false;
213 }
214 if (success && (bitmap->height() != referenceBitmap->height())) {
215 SkDebugf("Expected image height: %i, actual image height %i",
216 referenceBitmap->height(), bitmap->height());
217 SkDELETE(bitmap);
218 SkDELETE(referenceBitmap);
219 return false;
220 }
skia.committer@gmail.coma7d8e3e2012-12-19 02:01:38 +0000221
edisonn@google.com84f548c2012-12-18 22:24:03 +0000222 for (int y = 0; success && y < bitmap->height(); y++) {
223 for (int x = 0; success && x < bitmap->width(); x++) {
224 if (*referenceBitmap->getAddr32(x, y) != *bitmap->getAddr32(x, y)) {
225 SkDebugf("Expected pixel at (%i %i): 0x%x, actual 0x%x\n",
226 x, y,
227 referenceBitmap->getAddr32(x, y),
228 *bitmap->getAddr32(x, y));
229 SkDELETE(bitmap);
230 SkDELETE(referenceBitmap);
231 return false;
232 }
233 }
234 }
235 SkDELETE(referenceBitmap);
236 }
237
238 if (writeWholeImage) {
239 sk_tools::force_all_opaque(*bitmap);
240 if (NULL != outputDir && writeWholeImage) {
241 SkString inputFilename;
242 sk_tools::get_basename(&inputFilename, inputPath);
243 SkString outputPath;
244 make_output_filepath(&outputPath, *outputDir, inputFilename);
245 outputPath.append(".png");
246 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap,
247 SkImageEncoder::kPNG_Type, 100)) {
248 SkDebugf("Failed to draw the picture.\n");
249 success = false;
250 }
251 }
252 }
253 SkDELETE(bitmap);
254
255 return success;
256}
257
258
borenet@google.com070d3542012-10-26 13:26:55 +0000259static int process_input(const SkString& input, const SkString* outputDir,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000260 sk_tools::PictureRenderer& renderer,
261 bool validate, bool writeWholeImage, int clones) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000262 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000263 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000264 int failures = 0;
borenet@google.com070d3542012-10-26 13:26:55 +0000265 SkDebugf("process_input, %s\n", input.c_str());
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000266 if (iter.next(&inputFilename)) {
267 do {
268 SkString inputPath;
269 sk_tools::make_filepath(&inputPath, input, inputFilename);
edisonn@google.com84f548c2012-12-18 22:24:03 +0000270 if (!render_picture(inputPath, outputDir, renderer,
271 validate, writeWholeImage, clones)) {
borenet@google.com57837bf2012-09-19 17:28:29 +0000272 ++failures;
273 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000274 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000275 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000276 SkString inputPath(input);
edisonn@google.com84f548c2012-12-18 22:24:03 +0000277 if (!render_picture(inputPath, outputDir, renderer,
278 validate, writeWholeImage, clones)) {
borenet@google.com57837bf2012-09-19 17:28:29 +0000279 ++failures;
280 }
281 } else {
282 SkString warning;
283 warning.printf("Warning: skipping %s\n", input.c_str());
284 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000285 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000286 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000287}
288
289static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000290 sk_tools::PictureRenderer*& renderer, SkString*& outputDir,
291 bool* validate, bool* writeWholeImage,
292 int* clones){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000293 const char* argv0 = argv[0];
294 char* const* stop = argv + argc;
295
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000296 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
297 sk_tools::PictureRenderer::kBitmap_DeviceType;
298
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000299 bool usePipe = false;
300 int numThreads = 1;
301 bool useTiles = false;
302 const char* widthString = NULL;
303 const char* heightString = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000304 int gridWidth = 0;
305 int gridHeight = 0;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000306 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000307 bool isCopyMode = false;
308 const char* xTilesString = NULL;
309 const char* yTilesString = NULL;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000310 const char* mode = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000311 bool gridSupported = false;
312 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
313 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
314 *validate = false;
315 *writeWholeImage = false;
316 *clones = 0;
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000317 SkISize viewport;
318 viewport.setEmpty();
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000319 SkScalar scaleFactor = SK_Scalar1;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000320
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000321 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000322 if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000323 if (renderer != NULL) {
324 renderer->unref();
325 SkDebugf("Cannot combine modes.\n");
326 usage(argv0);
327 exit(-1);
328 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000329
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000330 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000331 if (argv >= stop) {
332 SkDebugf("Missing mode for --mode\n");
333 usage(argv0);
334 exit(-1);
335 }
336
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000337 if (0 == strcmp(*argv, "simple")) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000338 renderer = SkNEW(sk_tools::SimplePictureRenderer);
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000339 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
340 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000341 useTiles = true;
342 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000343
344 if (0 == strcmp(*argv, "pow2tile")) {
345 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000346 } else if (0 == strcmp(*argv, "copyTile")) {
347 isCopyMode = true;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000348 } else {
349 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000350 }
351
keyar@chromium.org795cd472012-08-02 18:57:53 +0000352 ++argv;
353 if (argv >= stop) {
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000354 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000355 usage(argv0);
356 exit(-1);
357 }
358
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000359 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000360 ++argv;
361 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000362 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000363 usage(argv0);
364 exit(-1);
365 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000366 heightString = *argv;
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000367 } else if (0 == strcmp(*argv, "rerecord")) {
368 renderer = SkNEW(sk_tools::RecordPictureRenderer);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000369 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000370 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000371 usage(argv0);
372 exit(-1);
373 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000374 } else if (0 == strcmp(*argv, "--bbh")) {
375 ++argv;
376 if (argv >= stop) {
377 SkDebugf("Missing value for --bbh\n");
378 usage(argv0);
379 exit(-1);
380 }
381 if (0 == strcmp(*argv, "none")) {
382 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
383 } else if (0 == strcmp(*argv, "rtree")) {
384 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
385 } else if (0 == strcmp(*argv, "grid")) {
386 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
387 ++argv;
388 if (argv >= stop) {
389 SkDebugf("Missing width for --bbh grid\n");
390 usage(argv0);
391 exit(-1);
392 }
393 gridWidth = atoi(*argv);
394 ++argv;
395 if (argv >= stop) {
396 SkDebugf("Missing height for --bbh grid\n");
397 usage(argv0);
398 exit(-1);
399 }
400 gridHeight = atoi(*argv);
401 } else {
402 SkDebugf("%s is not a valid value for --bbhType\n", *argv);
403 usage(argv0);
404 exit(-1);;
405 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000406 } else if (0 == strcmp(*argv, "--viewport")) {
407 ++argv;
408 if (argv >= stop) {
409 SkDebugf("Missing width for --viewport\n");
410 usage(argv0);
411 exit(-1);
412 }
413 viewport.fWidth = atoi(*argv);
414 ++argv;
415 if (argv >= stop) {
416 SkDebugf("Missing height for --viewport\n");
417 usage(argv0);
418 exit(-1);
419 }
420 viewport.fHeight = atoi(*argv);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000421 } else if (0 == strcmp(*argv, "--scale")) {
422 ++argv;
423 if (argv >= stop) {
424 SkDebugf("Missing scaleFactor for --scale\n");
425 usage(argv0);
426 exit(-1);
427 }
428 scaleFactor = atof(*argv);
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000429 } else if (0 == strcmp(*argv, "--tiles")) {
430 ++argv;
431 if (argv >= stop) {
432 SkDebugf("Missing x for --tiles\n");
433 usage(argv0);
434 exit(-1);
435 }
436 xTilesString = *argv;
437 ++argv;
438 if (argv >= stop) {
439 SkDebugf("Missing y for --tiles\n");
440 usage(argv0);
441 exit(-1);
442 }
443 yTilesString = *argv;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000444 } else if (0 == strcmp(*argv, "--pipe")) {
445 usePipe = true;
446 } else if (0 == strcmp(*argv, "--multi")) {
447 ++argv;
448 if (argv >= stop) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000449 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000450 SkDebugf("Missing arg for --multi\n");
451 usage(argv0);
452 exit(-1);
453 }
454 numThreads = atoi(*argv);
455 if (numThreads < 2) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000456 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000457 SkDebugf("Number of threads must be at least 2.\n");
458 usage(argv0);
459 exit(-1);
460 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000461 } else if (0 == strcmp(*argv, "--clone")) {
462 ++argv;
463 if (argv >= stop) {
464 SkSafeUnref(renderer);
465 SkDebugf("Missing arg for --clone\n");
466 usage(argv0);
467 exit(-1);
468 }
469 *clones = atoi(*argv);
470 if (*clones < 0) {
471 SkSafeUnref(renderer);
472 SkDebugf("Number of clones must be at least 0.\n");
473 usage(argv0);
474 exit(-1);
475 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000476 } else if (0 == strcmp(*argv, "--device")) {
477 ++argv;
478 if (argv >= stop) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000479 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000480 SkDebugf("Missing mode for --device\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000481 usage(argv0);
482 exit(-1);
483 }
484
485 if (0 == strcmp(*argv, "bitmap")) {
486 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
487 }
488#if SK_SUPPORT_GPU
489 else if (0 == strcmp(*argv, "gpu")) {
490 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
491 }
492#endif
493 else {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000494 SkSafeUnref(renderer);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000495 SkDebugf("%s is not a valid mode for --device\n", *argv);
496 usage(argv0);
497 exit(-1);
498 }
499
keyar@chromium.org472b3792012-07-20 22:34:27 +0000500 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000501 SkSafeUnref(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000502 usage(argv0);
503 exit(-1);
borenet@google.com070d3542012-10-26 13:26:55 +0000504 } else if (0 == strcmp(*argv, "-w")) {
505 ++argv;
506 if (argv >= stop) {
507 SkDebugf("Missing output directory for -w\n");
508 usage(argv0);
509 exit(-1);
510 }
511 outputDir = SkNEW_ARGS(SkString, (*argv));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000512 } else if (0 == strcmp(*argv, "--validate")) {
513 *validate = true;
514 } else if (0 == strcmp(*argv, "--writeWholeImage")) {
515 *writeWholeImage = true;
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000516 } else {
517 inputs->push_back(SkString(*argv));
518 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000519 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000520
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000521 if (numThreads > 1 && !useTiles) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000522 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000523 SkDebugf("Multithreaded drawing requires tiled rendering.\n");
524 usage(argv0);
525 exit(-1);
526 }
527
edisonn@google.com84f548c2012-12-18 22:24:03 +0000528 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
529 SkDebugf("--pipe and --bbh cannot be used together\n");
530 usage(argv0);
531 exit(-1);
532 }
533
534 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
535 !gridSupported) {
536 SkDebugf("'--bbh grid' is not compatible with specified --mode.\n");
537 usage(argv0);
538 exit(-1);
539 }
540
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000541 if (useTiles) {
542 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000543 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000544 if (isCopyMode) {
545 int x, y;
546 if (xTilesString != NULL) {
547 SkASSERT(yTilesString != NULL);
548 x = atoi(xTilesString);
549 y = atoi(yTilesString);
550 if (x <= 0 || y <= 0) {
551 SkDebugf("--tiles must be given values > 0\n");
552 usage(argv0);
553 exit(-1);
554 }
555 } else {
556 x = y = 4;
557 }
558 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
559 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000560 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
561 } else {
562 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
563 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000564 if (isPowerOf2Mode) {
565 int minWidth = atoi(widthString);
566 if (!SkIsPow2(minWidth) || minWidth < 0) {
567 tiledRenderer->unref();
568 SkString err;
569 err.printf("-mode %s must be given a width"
570 " value that is a power of two\n", mode);
571 SkDebugf(err.c_str());
572 usage(argv0);
573 exit(-1);
574 }
575 tiledRenderer->setTileMinPowerOf2Width(minWidth);
576 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000577 if (isCopyMode) {
578 tiledRenderer->unref();
579 SkString err;
580 err.printf("--mode %s does not support percentages.\n", mode);
581 SkDebugf(err.c_str());
582 usage(argv0);
583 exit(-1);
584 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000585 tiledRenderer->setTileWidthPercentage(atof(widthString));
586 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
587 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000588 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000589 usage(argv0);
590 exit(-1);
591 }
592 } else {
593 tiledRenderer->setTileWidth(atoi(widthString));
594 if (!(tiledRenderer->getTileWidth() > 0)) {
595 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000596 SkDebugf("--mode %s must be given a width > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000597 usage(argv0);
598 exit(-1);
599 }
600 }
601
602 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000603 if (isCopyMode) {
604 tiledRenderer->unref();
605 SkString err;
606 err.printf("--mode %s does not support percentages.\n", mode);
607 SkDebugf(err.c_str());
608 usage(argv0);
609 exit(-1);
610 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000611 tiledRenderer->setTileHeightPercentage(atof(heightString));
612 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
613 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000614 SkDebugf("--mode %s must be given a height percentage > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000615 usage(argv0);
616 exit(-1);
617 }
618 } else {
619 tiledRenderer->setTileHeight(atoi(heightString));
620 if (!(tiledRenderer->getTileHeight() > 0)) {
621 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000622 SkDebugf("--mode %s must be given a height > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000623 usage(argv0);
624 exit(-1);
625 }
626 }
627 if (numThreads > 1) {
628#if SK_SUPPORT_GPU
629 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
630 tiledRenderer->unref();
631 SkDebugf("GPU not compatible with multithreaded tiling.\n");
632 usage(argv0);
633 exit(-1);
634 }
635#endif
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000636 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000637 renderer = tiledRenderer;
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000638 if (usePipe) {
639 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
640 "Turning off pipe.\n");
641 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000642 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000643 if (renderer != NULL) {
644 renderer->unref();
645 SkDebugf("Pipe is incompatible with other modes.\n");
646 usage(argv0);
647 exit(-1);
648 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000649 renderer = SkNEW(sk_tools::PipePictureRenderer);
650 }
651
borenet@google.com070d3542012-10-26 13:26:55 +0000652 if (inputs->empty()) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000653 SkSafeUnref(renderer);
borenet@google.com070d3542012-10-26 13:26:55 +0000654 if (NULL != outputDir) {
655 SkDELETE(outputDir);
656 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000657 usage(argv0);
658 exit(-1);
659 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000660
661 if (NULL == renderer) {
662 renderer = SkNEW(sk_tools::SimplePictureRenderer);
663 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000664
edisonn@google.com84f548c2012-12-18 22:24:03 +0000665 renderer->setBBoxHierarchyType(bbhType);
666 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000667 renderer->setViewport(viewport);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000668 renderer->setScaleFactor(scaleFactor);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000669 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000670}
671
caryclark@google.com5987f582012-10-02 18:33:14 +0000672int tool_main(int argc, char** argv);
673int tool_main(int argc, char** argv) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000674 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000675 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000676 sk_tools::PictureRenderer* renderer = NULL;
borenet@google.com070d3542012-10-26 13:26:55 +0000677 SkString* outputDir = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000678 bool validate = false;
679 bool writeWholeImage = false;
680 int clones = 0;
681 parse_commandline(argc, argv, &inputs, renderer, outputDir,
682 &validate, &writeWholeImage, &clones);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000683 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000684
borenet@google.com66bcbd12012-09-17 18:26:06 +0000685 int failures = 0;
borenet@google.com070d3542012-10-26 13:26:55 +0000686 for (int i = 0; i < inputs.count(); i ++) {
edisonn@google.com84f548c2012-12-18 22:24:03 +0000687 failures += process_input(inputs[i], outputDir, *renderer,
688 validate, writeWholeImage, clones);
junov@chromium.org777442d2012-06-12 14:56:36 +0000689 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000690 if (failures != 0) {
691 SkDebugf("Failed to render %i pictures.\n", failures);
692 return 1;
693 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000694#if SK_SUPPORT_GPU
695#if GR_CACHE_STATS
696 if (renderer->isUsingGpuDevice()) {
697 GrContext* ctx = renderer->getGrContext();
698
699 ctx->printCacheStats();
700 }
701#endif
702#endif
borenet@google.com070d3542012-10-26 13:26:55 +0000703 if (NULL != outputDir) {
704 SkDELETE(outputDir);
705 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000706 SkDELETE(renderer);
caryclark@google.com868e1f62012-10-02 20:00:03 +0000707 return 0;
junov@chromium.org777442d2012-06-12 14:56:36 +0000708}
caryclark@google.com5987f582012-10-02 18:33:14 +0000709
710#if !defined SK_BUILD_FOR_IOS
711int main(int argc, char * const argv[]) {
712 return tool_main(argc, (char**) argv);
713}
714#endif