blob: fda5350d3ac63c71b2b2a438a7a67d618c8658ff [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
edisonn@google.comddbd83a2013-01-16 15:03:24 +000024// Define this if validation failures should cause the tool to return failure
25// If not, it will still printf the messages.
26//#define VALIDATE_FAILURE_IS_A_TOOL_FAILURE
27
junov@chromium.org777442d2012-06-12 14:56:36 +000028static void usage(const char* argv0) {
29 SkDebugf("SkPicture rendering tool\n");
30 SkDebugf("\n"
31"Usage: \n"
borenet@google.com070d3542012-10-26 13:26:55 +000032" %s <input>... \n"
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000033" [-w <outputDir>]\n"
34" [--mode pow2tile minWidth height | copyTile width height | simple\n"
35" | tile width height]\n"
scroggo@google.comb6e806b2012-10-03 17:32:33 +000036" [--pipe]\n"
edisonn@google.com84f548c2012-12-18 22:24:03 +000037" [--bbh bbhType]\n"
scroggo@google.comb6e806b2012-10-03 17:32:33 +000038" [--multi count]\n"
edisonn@google.comddbd83a2013-01-16 15:03:24 +000039" [--validate]\n"
edisonn@google.com84f548c2012-12-18 22:24:03 +000040" [--writeWholeImage]\n"
41" [--clone n]\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +000042" [--viewport width height][--scale sf]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000043" [--device bitmap"
44#if SK_SUPPORT_GPU
45" | gpu"
46#endif
47"]"
junov@chromium.org777442d2012-06-12 14:56:36 +000048, argv0);
keyar@chromium.org472b3792012-07-20 22:34:27 +000049 SkDebugf("\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000050 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000051" input: A list of directories and files to use as input. Files are\n"
52" expected to have the .skp extension.\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000053 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000054" outputDir: directory to write the rendered images.\n\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000055 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000056" --mode pow2tile minWidth height | copyTile width height | simple\n"
57" | tile width height | rerecord: Run in the corresponding mode.\n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000058" Default is simple.\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000059 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000060" pow2tile minWidth height, Creates tiles with widths\n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000061" that are all a power of two\n"
62" such that they minimize the\n"
63" amount of wasted tile space.\n"
64" minWidth is the minimum width\n"
65" of these tiles and must be a\n"
66" power of two. A simple render\n"
67" is done with these tiles.\n");
68 SkDebugf(
scroggo@google.coma9e3a362012-11-07 17:52:48 +000069" simple, Render using the default rendering method.\n"
70" rerecord, Record the picture as a new skp, with the bitmaps PNG encoded.\n"
71 );
keyar@chromium.org795cd472012-08-02 18:57:53 +000072 SkDebugf(
scroggo@google.com4a26d9d2012-11-07 18:01:46 +000073" tile width height, Do a simple render using tiles\n"
74" with the given dimensions.\n"
75" copyTile width height, Draw the picture, then copy it into tiles.\n"
76" Does not support percentages.\n"
77" If the picture is large enough, breaks it into\n"
78" larger tiles (and draws the picture once per\n"
79" larger tile) to avoid creating a large canvas.\n"
80" Add --tiles x y to specify the number of tiles\n"
81" per larger tile in the x and y direction.\n"
82 );
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000083 SkDebugf("\n");
84 SkDebugf(
scroggo@google.comb6e806b2012-10-03 17:32:33 +000085" --multi count : Set the number of threads for multi threaded drawing. Must be greater\n"
86" than 1. Only works with tiled rendering.\n"
scroggo@google.comc0d5e542012-12-13 21:40:48 +000087" --viewport width height : Set the viewport.\n"
scroggo@google.com82ec0b02012-12-17 19:25:54 +000088" --scale sf : Scale drawing by sf.\n"
scroggo@google.coma62da2f2012-11-02 21:28:12 +000089" --pipe: Benchmark SkGPipe rendering. Currently incompatible with \"mode\".\n");
scroggo@google.comb6e806b2012-10-03 17:32:33 +000090 SkDebugf(
edisonn@google.com84f548c2012-12-18 22:24:03 +000091" --validate: Verify that the rendered image contains the same pixels as "
92"the picture rendered in simple mode.\n"
93" --writeWholeImage: In tile mode, write the entire rendered image to a "
94"file, instead of an image for each tile.\n");
95 SkDebugf(
96" --clone n: Clone the picture n times before rendering.\n");
97 SkDebugf(
98" --bbh bbhType [width height]: Set the bounding box hierarchy type to\n"
99" be used. Accepted values are: none, rtree, grid. Default\n"
100" value is none. Not compatible with --pipe. With value\n"
101" 'grid', width and height must be specified. 'grid' can\n"
102" only be used with modes tile, record, and\n"
103" playbackCreation.");
104 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000105" --device bitmap"
106#if SK_SUPPORT_GPU
107" | gpu"
108#endif
109": Use the corresponding device. Default is bitmap.\n");
110 SkDebugf(
111" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000112#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +0000113 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000114" gpu, Render to the GPU.\n");
115#endif
junov@chromium.org777442d2012-06-12 14:56:36 +0000116}
117
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000118static void make_output_filepath(SkString* path, const SkString& dir,
junov@chromium.org777442d2012-06-12 14:56:36 +0000119 const SkString& name) {
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000120 sk_tools::make_filepath(path, dir, name);
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000121 // Remove ".skp"
122 path->remove(path->size() - 4, 4);
junov@chromium.org777442d2012-06-12 14:56:36 +0000123}
124
borenet@google.com070d3542012-10-26 13:26:55 +0000125static bool render_picture(const SkString& inputPath, const SkString* outputDir,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000126 sk_tools::PictureRenderer& renderer,
127 SkBitmap** out,
128 int clones) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000129 SkString inputFilename;
130 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000131
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000132 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000133 inputStream.setPath(inputPath.c_str());
134 if (!inputStream.isValid()) {
135 SkDebugf("Could not open file %s\n", inputPath.c_str());
borenet@google.com66bcbd12012-09-17 18:26:06 +0000136 return false;
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000137 }
138
borenet@google.com66bcbd12012-09-17 18:26:06 +0000139 bool success = false;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000140 SkPicture* picture = SkNEW_ARGS(SkPicture,
141 (&inputStream, &success, &SkImageDecoder::DecodeStream));
borenet@google.com66bcbd12012-09-17 18:26:06 +0000142 if (!success) {
143 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
144 return false;
145 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000146
edisonn@google.com84f548c2012-12-18 22:24:03 +0000147 for (int i = 0; i < clones; ++i) {
148 SkPicture* clone = picture->clone();
149 SkDELETE(picture);
150 picture = clone;
151 }
152
153 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000154 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000155
edisonn@google.com84f548c2012-12-18 22:24:03 +0000156 renderer.init(picture);
scroggo@google.comb4773b42012-10-01 20:06:09 +0000157 renderer.setup();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000158
borenet@google.com070d3542012-10-26 13:26:55 +0000159 SkString* outputPath = NULL;
160 if (NULL != outputDir) {
161 outputPath = SkNEW(SkString);
162 make_output_filepath(outputPath, *outputDir, inputFilename);
163 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000164
165 success = renderer.render(outputPath, out);
borenet@google.com070d3542012-10-26 13:26:55 +0000166 if (outputPath) {
167 if (!success) {
168 SkDebugf("Could not write to file %s\n", outputPath->c_str());
169 }
170 SkDELETE(outputPath);
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000171 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000172
173 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000174
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000175 renderer.end();
edisonn@google.com84f548c2012-12-18 22:24:03 +0000176
177 SkDELETE(picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000178 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000179}
180
edisonn@google.com84f548c2012-12-18 22:24:03 +0000181static bool render_picture(const SkString& inputPath, const SkString* outputDir,
182 sk_tools::PictureRenderer& renderer,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000183 bool validate,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000184 bool writeWholeImage,
185 int clones) {
186 SkBitmap* bitmap = NULL;
187 bool success = render_picture(inputPath,
188 writeWholeImage ? NULL : outputDir,
189 renderer,
190 validate || writeWholeImage ? &bitmap : NULL, clones);
191
192 if (!success || ((validate || writeWholeImage) && bitmap == NULL)) {
193 SkDebugf("Failed to draw the picture.\n");
194 SkDELETE(bitmap);
195 return false;
196 }
197
198 if (validate) {
199 SkBitmap* referenceBitmap = NULL;
200 sk_tools::SimplePictureRenderer referenceRenderer;
201 success = render_picture(inputPath, NULL, referenceRenderer,
202 &referenceBitmap, 0);
203
204 if (!success || !referenceBitmap) {
205 SkDebugf("Failed to draw the reference picture.\n");
206 SkDELETE(bitmap);
207 SkDELETE(referenceBitmap);
208 return false;
209 }
210
211 if (success && (bitmap->width() != referenceBitmap->width())) {
212 SkDebugf("Expected image width: %i, actual image width %i.\n",
213 referenceBitmap->width(), bitmap->width());
214 SkDELETE(bitmap);
215 SkDELETE(referenceBitmap);
216 return false;
217 }
218 if (success && (bitmap->height() != referenceBitmap->height())) {
219 SkDebugf("Expected image height: %i, actual image height %i",
220 referenceBitmap->height(), bitmap->height());
221 SkDELETE(bitmap);
222 SkDELETE(referenceBitmap);
223 return false;
224 }
skia.committer@gmail.coma7d8e3e2012-12-19 02:01:38 +0000225
edisonn@google.com84f548c2012-12-18 22:24:03 +0000226 for (int y = 0; success && y < bitmap->height(); y++) {
227 for (int x = 0; success && x < bitmap->width(); x++) {
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000228 if (*referenceBitmap->getAddr32(x, y) != *bitmap->getAddr32(x, y)) {
229 SkDebugf("Expected pixel at (%i %i): 0x%x, actual 0x%x\n",
230 x, y,
edisonn@google.com01754bf2013-01-11 16:08:07 +0000231 *referenceBitmap->getAddr32(x, y),
edisonn@google.com84f548c2012-12-18 22:24:03 +0000232 *bitmap->getAddr32(x, y));
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000233#ifdef VALIDATE_FAILURE_IS_A_TOOL_FAILURE
edisonn@google.com84f548c2012-12-18 22:24:03 +0000234 SkDELETE(bitmap);
235 SkDELETE(referenceBitmap);
236 return false;
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000237#else
238 goto DONE;
239#endif
edisonn@google.com84f548c2012-12-18 22:24:03 +0000240 }
241 }
242 }
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000243 DONE:
edisonn@google.com84f548c2012-12-18 22:24:03 +0000244 SkDELETE(referenceBitmap);
245 }
246
247 if (writeWholeImage) {
248 sk_tools::force_all_opaque(*bitmap);
249 if (NULL != outputDir && writeWholeImage) {
250 SkString inputFilename;
251 sk_tools::get_basename(&inputFilename, inputPath);
252 SkString outputPath;
253 make_output_filepath(&outputPath, *outputDir, inputFilename);
254 outputPath.append(".png");
255 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap,
256 SkImageEncoder::kPNG_Type, 100)) {
257 SkDebugf("Failed to draw the picture.\n");
258 success = false;
259 }
260 }
261 }
262 SkDELETE(bitmap);
263
264 return success;
265}
266
267
borenet@google.com070d3542012-10-26 13:26:55 +0000268static int process_input(const SkString& input, const SkString* outputDir,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000269 sk_tools::PictureRenderer& renderer,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000270 bool validate, bool writeWholeImage, int clones) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000271 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000272 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000273 int failures = 0;
borenet@google.com070d3542012-10-26 13:26:55 +0000274 SkDebugf("process_input, %s\n", input.c_str());
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000275 if (iter.next(&inputFilename)) {
276 do {
277 SkString inputPath;
278 sk_tools::make_filepath(&inputPath, input, inputFilename);
edisonn@google.com84f548c2012-12-18 22:24:03 +0000279 if (!render_picture(inputPath, outputDir, renderer,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000280 validate, writeWholeImage, clones)) {
borenet@google.com57837bf2012-09-19 17:28:29 +0000281 ++failures;
282 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000283 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000284 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000285 SkString inputPath(input);
edisonn@google.com84f548c2012-12-18 22:24:03 +0000286 if (!render_picture(inputPath, outputDir, renderer,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000287 validate, writeWholeImage, clones)) {
borenet@google.com57837bf2012-09-19 17:28:29 +0000288 ++failures;
289 }
290 } else {
291 SkString warning;
292 warning.printf("Warning: skipping %s\n", input.c_str());
293 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000294 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000295 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000296}
297
298static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000299 sk_tools::PictureRenderer*& renderer, SkString*& outputDir,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000300 bool* validate, bool* writeWholeImage,
edisonn@google.com84f548c2012-12-18 22:24:03 +0000301 int* clones){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000302 const char* argv0 = argv[0];
303 char* const* stop = argv + argc;
304
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000305 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
306 sk_tools::PictureRenderer::kBitmap_DeviceType;
307
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000308 bool usePipe = false;
309 int numThreads = 1;
310 bool useTiles = false;
311 const char* widthString = NULL;
312 const char* heightString = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000313 int gridWidth = 0;
314 int gridHeight = 0;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000315 bool isPowerOf2Mode = false;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000316 bool isCopyMode = false;
317 const char* xTilesString = NULL;
318 const char* yTilesString = NULL;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000319 const char* mode = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000320 bool gridSupported = false;
321 sk_tools::PictureRenderer::BBoxHierarchyType bbhType =
322 sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
323 *validate = false;
324 *writeWholeImage = false;
325 *clones = 0;
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000326 SkISize viewport;
327 viewport.setEmpty();
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000328 SkScalar scaleFactor = SK_Scalar1;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000329
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000330 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000331 if (0 == strcmp(*argv, "--mode")) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000332 if (renderer != NULL) {
333 renderer->unref();
334 SkDebugf("Cannot combine modes.\n");
335 usage(argv0);
336 exit(-1);
337 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000338
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000339 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000340 if (argv >= stop) {
341 SkDebugf("Missing mode for --mode\n");
342 usage(argv0);
343 exit(-1);
344 }
345
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000346 if (0 == strcmp(*argv, "simple")) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000347 renderer = SkNEW(sk_tools::SimplePictureRenderer);
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000348 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))
349 || 0 == strcmp(*argv, "copyTile")) {
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000350 useTiles = true;
351 mode = *argv;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000352
353 if (0 == strcmp(*argv, "pow2tile")) {
354 isPowerOf2Mode = true;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000355 } else if (0 == strcmp(*argv, "copyTile")) {
356 isCopyMode = true;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000357 } else {
358 gridSupported = true;
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000359 }
360
keyar@chromium.org795cd472012-08-02 18:57:53 +0000361 ++argv;
362 if (argv >= stop) {
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000363 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000364 usage(argv0);
365 exit(-1);
366 }
367
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000368 widthString = *argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000369 ++argv;
370 if (argv >= stop) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000371 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000372 usage(argv0);
373 exit(-1);
374 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000375 heightString = *argv;
scroggo@google.coma9e3a362012-11-07 17:52:48 +0000376 } else if (0 == strcmp(*argv, "rerecord")) {
377 renderer = SkNEW(sk_tools::RecordPictureRenderer);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000378 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000379 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000380 usage(argv0);
381 exit(-1);
382 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000383 } else if (0 == strcmp(*argv, "--bbh")) {
384 ++argv;
385 if (argv >= stop) {
386 SkDebugf("Missing value for --bbh\n");
387 usage(argv0);
388 exit(-1);
389 }
390 if (0 == strcmp(*argv, "none")) {
391 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
392 } else if (0 == strcmp(*argv, "rtree")) {
393 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
394 } else if (0 == strcmp(*argv, "grid")) {
395 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
396 ++argv;
397 if (argv >= stop) {
398 SkDebugf("Missing width for --bbh grid\n");
399 usage(argv0);
400 exit(-1);
401 }
402 gridWidth = atoi(*argv);
403 ++argv;
404 if (argv >= stop) {
405 SkDebugf("Missing height for --bbh grid\n");
406 usage(argv0);
407 exit(-1);
408 }
409 gridHeight = atoi(*argv);
410 } else {
411 SkDebugf("%s is not a valid value for --bbhType\n", *argv);
412 usage(argv0);
413 exit(-1);;
414 }
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000415 } else if (0 == strcmp(*argv, "--viewport")) {
416 ++argv;
417 if (argv >= stop) {
418 SkDebugf("Missing width for --viewport\n");
419 usage(argv0);
420 exit(-1);
421 }
422 viewport.fWidth = atoi(*argv);
423 ++argv;
424 if (argv >= stop) {
425 SkDebugf("Missing height for --viewport\n");
426 usage(argv0);
427 exit(-1);
428 }
429 viewport.fHeight = atoi(*argv);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000430 } else if (0 == strcmp(*argv, "--scale")) {
431 ++argv;
432 if (argv >= stop) {
433 SkDebugf("Missing scaleFactor for --scale\n");
434 usage(argv0);
435 exit(-1);
436 }
reed@google.com89d15a22013-01-07 22:26:05 +0000437 scaleFactor = SkDoubleToScalar(atof(*argv));
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000438 } else if (0 == strcmp(*argv, "--tiles")) {
439 ++argv;
440 if (argv >= stop) {
441 SkDebugf("Missing x for --tiles\n");
442 usage(argv0);
443 exit(-1);
444 }
445 xTilesString = *argv;
446 ++argv;
447 if (argv >= stop) {
448 SkDebugf("Missing y for --tiles\n");
449 usage(argv0);
450 exit(-1);
451 }
452 yTilesString = *argv;
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000453 } else if (0 == strcmp(*argv, "--pipe")) {
454 usePipe = true;
455 } else if (0 == strcmp(*argv, "--multi")) {
456 ++argv;
457 if (argv >= stop) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000458 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000459 SkDebugf("Missing arg for --multi\n");
460 usage(argv0);
461 exit(-1);
462 }
463 numThreads = atoi(*argv);
464 if (numThreads < 2) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000465 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000466 SkDebugf("Number of threads must be at least 2.\n");
467 usage(argv0);
468 exit(-1);
469 }
edisonn@google.com84f548c2012-12-18 22:24:03 +0000470 } else if (0 == strcmp(*argv, "--clone")) {
471 ++argv;
472 if (argv >= stop) {
473 SkSafeUnref(renderer);
474 SkDebugf("Missing arg for --clone\n");
475 usage(argv0);
476 exit(-1);
477 }
478 *clones = atoi(*argv);
479 if (*clones < 0) {
480 SkSafeUnref(renderer);
481 SkDebugf("Number of clones must be at least 0.\n");
482 usage(argv0);
483 exit(-1);
484 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000485 } else if (0 == strcmp(*argv, "--device")) {
486 ++argv;
487 if (argv >= stop) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000488 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000489 SkDebugf("Missing mode for --device\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000490 usage(argv0);
491 exit(-1);
492 }
493
494 if (0 == strcmp(*argv, "bitmap")) {
495 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
496 }
497#if SK_SUPPORT_GPU
498 else if (0 == strcmp(*argv, "gpu")) {
499 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
500 }
501#endif
502 else {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000503 SkSafeUnref(renderer);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000504 SkDebugf("%s is not a valid mode for --device\n", *argv);
505 usage(argv0);
506 exit(-1);
507 }
508
keyar@chromium.org472b3792012-07-20 22:34:27 +0000509 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000510 SkSafeUnref(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000511 usage(argv0);
512 exit(-1);
borenet@google.com070d3542012-10-26 13:26:55 +0000513 } else if (0 == strcmp(*argv, "-w")) {
514 ++argv;
515 if (argv >= stop) {
516 SkDebugf("Missing output directory for -w\n");
517 usage(argv0);
518 exit(-1);
519 }
520 outputDir = SkNEW_ARGS(SkString, (*argv));
edisonn@google.com84f548c2012-12-18 22:24:03 +0000521 } else if (0 == strcmp(*argv, "--validate")) {
522 *validate = true;
523 } else if (0 == strcmp(*argv, "--writeWholeImage")) {
524 *writeWholeImage = true;
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000525 } else {
526 inputs->push_back(SkString(*argv));
527 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000528 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000529
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000530 if (numThreads > 1 && !useTiles) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000531 SkSafeUnref(renderer);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000532 SkDebugf("Multithreaded drawing requires tiled rendering.\n");
533 usage(argv0);
534 exit(-1);
535 }
536
edisonn@google.com84f548c2012-12-18 22:24:03 +0000537 if (usePipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
538 SkDebugf("--pipe and --bbh cannot be used together\n");
539 usage(argv0);
540 exit(-1);
541 }
542
543 if (sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType == bbhType &&
544 !gridSupported) {
545 SkDebugf("'--bbh grid' is not compatible with specified --mode.\n");
546 usage(argv0);
547 exit(-1);
548 }
549
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000550 if (useTiles) {
551 SkASSERT(NULL == renderer);
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000552 sk_tools::TiledPictureRenderer* tiledRenderer;
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000553 if (isCopyMode) {
554 int x, y;
555 if (xTilesString != NULL) {
556 SkASSERT(yTilesString != NULL);
557 x = atoi(xTilesString);
558 y = atoi(yTilesString);
559 if (x <= 0 || y <= 0) {
560 SkDebugf("--tiles must be given values > 0\n");
561 usage(argv0);
562 exit(-1);
563 }
564 } else {
565 x = y = 4;
566 }
567 tiledRenderer = SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y));
568 } else if (numThreads > 1) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000569 tiledRenderer = SkNEW_ARGS(sk_tools::MultiCorePictureRenderer, (numThreads));
570 } else {
571 tiledRenderer = SkNEW(sk_tools::TiledPictureRenderer);
572 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000573 if (isPowerOf2Mode) {
574 int minWidth = atoi(widthString);
575 if (!SkIsPow2(minWidth) || minWidth < 0) {
576 tiledRenderer->unref();
577 SkString err;
578 err.printf("-mode %s must be given a width"
579 " value that is a power of two\n", mode);
580 SkDebugf(err.c_str());
581 usage(argv0);
582 exit(-1);
583 }
584 tiledRenderer->setTileMinPowerOf2Width(minWidth);
585 } else if (sk_tools::is_percentage(widthString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000586 if (isCopyMode) {
587 tiledRenderer->unref();
588 SkString err;
589 err.printf("--mode %s does not support percentages.\n", mode);
590 SkDebugf(err.c_str());
591 usage(argv0);
592 exit(-1);
593 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000594 tiledRenderer->setTileWidthPercentage(atof(widthString));
595 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
596 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000597 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000598 usage(argv0);
599 exit(-1);
600 }
601 } else {
602 tiledRenderer->setTileWidth(atoi(widthString));
603 if (!(tiledRenderer->getTileWidth() > 0)) {
604 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000605 SkDebugf("--mode %s must be given a width > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000606 usage(argv0);
607 exit(-1);
608 }
609 }
610
611 if (sk_tools::is_percentage(heightString)) {
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000612 if (isCopyMode) {
613 tiledRenderer->unref();
614 SkString err;
615 err.printf("--mode %s does not support percentages.\n", mode);
616 SkDebugf(err.c_str());
617 usage(argv0);
618 exit(-1);
619 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000620 tiledRenderer->setTileHeightPercentage(atof(heightString));
621 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
622 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000623 SkDebugf("--mode %s must be given a height percentage > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000624 usage(argv0);
625 exit(-1);
626 }
627 } else {
628 tiledRenderer->setTileHeight(atoi(heightString));
629 if (!(tiledRenderer->getTileHeight() > 0)) {
630 tiledRenderer->unref();
scroggo@google.com4a26d9d2012-11-07 18:01:46 +0000631 SkDebugf("--mode %s must be given a height > 0\n", mode);
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000632 usage(argv0);
633 exit(-1);
634 }
635 }
636 if (numThreads > 1) {
637#if SK_SUPPORT_GPU
638 if (sk_tools::PictureRenderer::kGPU_DeviceType == deviceType) {
639 tiledRenderer->unref();
640 SkDebugf("GPU not compatible with multithreaded tiling.\n");
641 usage(argv0);
642 exit(-1);
643 }
644#endif
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000645 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000646 renderer = tiledRenderer;
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000647 if (usePipe) {
648 SkDebugf("Pipe rendering is currently not compatible with tiling.\n"
649 "Turning off pipe.\n");
650 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000651 } else if (usePipe) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000652 if (renderer != NULL) {
653 renderer->unref();
654 SkDebugf("Pipe is incompatible with other modes.\n");
655 usage(argv0);
656 exit(-1);
657 }
scroggo@google.comb6e806b2012-10-03 17:32:33 +0000658 renderer = SkNEW(sk_tools::PipePictureRenderer);
659 }
660
borenet@google.com070d3542012-10-26 13:26:55 +0000661 if (inputs->empty()) {
scroggo@google.coma62da2f2012-11-02 21:28:12 +0000662 SkSafeUnref(renderer);
borenet@google.com070d3542012-10-26 13:26:55 +0000663 if (NULL != outputDir) {
664 SkDELETE(outputDir);
665 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000666 usage(argv0);
667 exit(-1);
668 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000669
670 if (NULL == renderer) {
671 renderer = SkNEW(sk_tools::SimplePictureRenderer);
672 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000673
edisonn@google.com84f548c2012-12-18 22:24:03 +0000674 renderer->setBBoxHierarchyType(bbhType);
675 renderer->setGridSize(gridWidth, gridHeight);
scroggo@google.comc0d5e542012-12-13 21:40:48 +0000676 renderer->setViewport(viewport);
scroggo@google.com82ec0b02012-12-17 19:25:54 +0000677 renderer->setScaleFactor(scaleFactor);
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000678 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000679}
680
caryclark@google.com5987f582012-10-02 18:33:14 +0000681int tool_main(int argc, char** argv);
682int tool_main(int argc, char** argv) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000683 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000684 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000685 sk_tools::PictureRenderer* renderer = NULL;
borenet@google.com070d3542012-10-26 13:26:55 +0000686 SkString* outputDir = NULL;
edisonn@google.com84f548c2012-12-18 22:24:03 +0000687 bool validate = false;
688 bool writeWholeImage = false;
689 int clones = 0;
690 parse_commandline(argc, argv, &inputs, renderer, outputDir,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000691 &validate, &writeWholeImage, &clones);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000692 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000693
borenet@google.com66bcbd12012-09-17 18:26:06 +0000694 int failures = 0;
borenet@google.com070d3542012-10-26 13:26:55 +0000695 for (int i = 0; i < inputs.count(); i ++) {
edisonn@google.com84f548c2012-12-18 22:24:03 +0000696 failures += process_input(inputs[i], outputDir, *renderer,
edisonn@google.comddbd83a2013-01-16 15:03:24 +0000697 validate, writeWholeImage, clones);
junov@chromium.org777442d2012-06-12 14:56:36 +0000698 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000699 if (failures != 0) {
700 SkDebugf("Failed to render %i pictures.\n", failures);
701 return 1;
702 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000703#if SK_SUPPORT_GPU
704#if GR_CACHE_STATS
705 if (renderer->isUsingGpuDevice()) {
706 GrContext* ctx = renderer->getGrContext();
707
708 ctx->printCacheStats();
709 }
710#endif
711#endif
borenet@google.com070d3542012-10-26 13:26:55 +0000712 if (NULL != outputDir) {
713 SkDELETE(outputDir);
714 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000715 SkDELETE(renderer);
caryclark@google.com868e1f62012-10-02 20:00:03 +0000716 return 0;
junov@chromium.org777442d2012-06-12 14:56:36 +0000717}
caryclark@google.com5987f582012-10-02 18:33:14 +0000718
719#if !defined SK_BUILD_FOR_IOS
720int main(int argc, char * const argv[]) {
721 return tool_main(argc, (char**) argv);
722}
723#endif