blob: 178d9ba432881c143c72edbb10b244ff19e173ae [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
junov@chromium.org777442d2012-06-12 14:56:36 +00008#include "SkBitmap.h"
9#include "SkCanvas.h"
keyar@chromium.org472b3792012-07-20 22:34:27 +000010#include "SkDevice.h"
borenet@google.com10ef79e2012-09-10 17:19:06 +000011#include "SkGraphics.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000012#include "SkMath.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000013#include "SkOSFile.h"
14#include "SkPicture.h"
15#include "SkStream.h"
16#include "SkString.h"
senorblanco@chromium.org3cbbb542012-07-13 18:55:53 +000017#include "SkTArray.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000018#include "PictureRenderer.h"
twiz@google.coma31b8bb2012-06-22 18:24:56 +000019#include "picture_utils.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000020
junov@chromium.org777442d2012-06-12 14:56:36 +000021static void usage(const char* argv0) {
22 SkDebugf("SkPicture rendering tool\n");
23 SkDebugf("\n"
24"Usage: \n"
keyar@chromium.org472b3792012-07-20 22:34:27 +000025" %s <input>... <outputDir> \n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000026" [--mode pipe | pow2tile minWidth height[%] | simple\n"
27" | tile width[%] height[%]]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000028" [--device bitmap"
29#if SK_SUPPORT_GPU
30" | gpu"
31#endif
32"]"
junov@chromium.org777442d2012-06-12 14:56:36 +000033, argv0);
keyar@chromium.org472b3792012-07-20 22:34:27 +000034 SkDebugf("\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000035 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000036" input: A list of directories and files to use as input. Files are\n"
37" expected to have the .skp extension.\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000038 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000039" outputDir: directory to write the rendered images.\n\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000040 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000041" --mode pipe | pow2tile minWidth height[%] | simple\n"
42" | tile width[%] height[%]: Run in the corresponding mode.\n"
43" Default is simple.\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000044 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000045" pipe, Render using a SkGPipe.\n");
46 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000047" pow2tile minWidth height[%], Creates tiles with widths\n"
48" that are all a power of two\n"
49" such that they minimize the\n"
50" amount of wasted tile space.\n"
51" minWidth is the minimum width\n"
52" of these tiles and must be a\n"
53" power of two. A simple render\n"
54" is done with these tiles.\n");
55 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000056" simple, Render using the default rendering method.\n");
57 SkDebugf(
58" tile width[%] height[%], Do a simple render using tiles\n"
59" with the given dimensions.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000060 SkDebugf("\n");
61 SkDebugf(
62" --device bitmap"
63#if SK_SUPPORT_GPU
64" | gpu"
65#endif
66": Use the corresponding device. Default is bitmap.\n");
67 SkDebugf(
68" bitmap, Render to a bitmap.\n");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000069#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +000070 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000071" gpu, Render to the GPU.\n");
72#endif
junov@chromium.org777442d2012-06-12 14:56:36 +000073}
74
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000075static void make_output_filepath(SkString* path, const SkString& dir,
junov@chromium.org777442d2012-06-12 14:56:36 +000076 const SkString& name) {
twiz@google.coma31b8bb2012-06-22 18:24:56 +000077 sk_tools::make_filepath(path, dir, name);
junov@chromium.org777442d2012-06-12 14:56:36 +000078 path->remove(path->size() - 3, 3);
79 path->append("png");
80}
81
borenet@google.com66bcbd12012-09-17 18:26:06 +000082static bool write_output(const SkString& outputDir, const SkString& inputFilename,
keyar@chromium.org9299ede2012-08-21 19:05:08 +000083 const sk_tools::PictureRenderer& renderer) {
junov@chromium.org777442d2012-06-12 14:56:36 +000084 SkString outputPath;
85 make_output_filepath(&outputPath, outputDir, inputFilename);
keyar@chromium.org9299ede2012-08-21 19:05:08 +000086 bool isWritten = renderer.write(outputPath);
junov@chromium.org777442d2012-06-12 14:56:36 +000087 if (!isWritten) {
88 SkDebugf("Could not write to file %s\n", outputPath.c_str());
89 }
borenet@google.com66bcbd12012-09-17 18:26:06 +000090 return isWritten;
junov@chromium.org777442d2012-06-12 14:56:36 +000091}
92
borenet@google.com66bcbd12012-09-17 18:26:06 +000093static bool render_picture(const SkString& inputPath, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000094 sk_tools::PictureRenderer& renderer) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000095 SkString inputFilename;
96 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +000097
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000098 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +000099 inputStream.setPath(inputPath.c_str());
100 if (!inputStream.isValid()) {
101 SkDebugf("Could not open file %s\n", inputPath.c_str());
borenet@google.com66bcbd12012-09-17 18:26:06 +0000102 return false;
twiz@google.coma31b8bb2012-06-22 18:24:56 +0000103 }
104
borenet@google.com66bcbd12012-09-17 18:26:06 +0000105 bool success = false;
106 SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream, &success));
borenet@google.come21795e2012-09-14 14:34:28 +0000107 SkAutoTUnref<SkPicture> aur(picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000108 if (!success) {
109 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
110 return false;
111 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000112
borenet@google.come21795e2012-09-14 14:34:28 +0000113 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000114 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000115
borenet@google.come21795e2012-09-14 14:34:28 +0000116 // rescale to avoid memory issues allocating a very large offscreen
117 sk_tools::resize_if_needed(&aur);
reed@google.come04e92b2012-09-13 17:44:32 +0000118
borenet@google.come21795e2012-09-14 14:34:28 +0000119 renderer.init(aur);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000120
scroggo@google.com9a412522012-09-07 15:21:18 +0000121 renderer.render(true);
122
123 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000124
borenet@google.com66bcbd12012-09-17 18:26:06 +0000125 success = write_output(outputDir, inputFilename, renderer);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000126
127 renderer.end();
borenet@google.com66bcbd12012-09-17 18:26:06 +0000128 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000129}
130
borenet@google.com66bcbd12012-09-17 18:26:06 +0000131static int process_input(const SkString& input, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000132 sk_tools::PictureRenderer& renderer) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000133 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000134 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000135 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000136 if (iter.next(&inputFilename)) {
137 do {
138 SkString inputPath;
139 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000140 if (!render_picture(inputPath, outputDir, renderer)) {
141 ++failures;
142 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000143 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000144 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000145 SkString inputPath(input);
borenet@google.com57837bf2012-09-19 17:28:29 +0000146 if (!render_picture(inputPath, outputDir, renderer)) {
147 ++failures;
148 }
149 } else {
150 SkString warning;
151 warning.printf("Warning: skipping %s\n", input.c_str());
152 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000153 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000154 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000155}
156
157static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000158 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000159 const char* argv0 = argv[0];
160 char* const* stop = argv + argc;
161
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000162 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
163 sk_tools::PictureRenderer::kBitmap_DeviceType;
164
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000165 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000166 if (0 == strcmp(*argv, "--mode")) {
167 SkDELETE(renderer);
168
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000169 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000170 if (argv >= stop) {
171 SkDebugf("Missing mode for --mode\n");
172 usage(argv0);
173 exit(-1);
174 }
175
176 if (0 == strcmp(*argv, "pipe")) {
177 renderer = SkNEW(sk_tools::PipePictureRenderer);
178 } else if (0 == strcmp(*argv, "simple")) {
179 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000180 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
181 char* mode = *argv;
182 bool isPowerOf2Mode = false;
183
184 if (0 == strcmp(*argv, "pow2tile")) {
185 isPowerOf2Mode = true;
186 }
187
keyar@chromium.org795cd472012-08-02 18:57:53 +0000188 sk_tools::TiledPictureRenderer* tileRenderer =
189 SkNEW(sk_tools::TiledPictureRenderer);
190 ++argv;
191 if (argv >= stop) {
192 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000193 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000194 usage(argv0);
195 exit(-1);
196 }
197
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000198 if (isPowerOf2Mode) {
199 int minWidth = atoi(*argv);
200
201 if (!SkIsPow2(minWidth) || minWidth <= 0) {
202 SkDELETE(tileRenderer);
203 SkDebugf("--mode %s must be given a width"
204 " value that is a power of two\n", mode);
205 exit(-1);
206 }
207
208 tileRenderer->setTileMinPowerOf2Width(minWidth);
209 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000210 tileRenderer->setTileWidthPercentage(atof(*argv));
211 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
212 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000213 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000214 exit(-1);
215 }
216 } else {
217 tileRenderer->setTileWidth(atoi(*argv));
218 if (!(tileRenderer->getTileWidth() > 0)) {
219 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000220 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000221 exit(-1);
222 }
223 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000224
225 ++argv;
226 if (argv >= stop) {
227 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000228 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000229 usage(argv0);
230 exit(-1);
231 }
232
keyar@chromium.org163b5672012-08-01 17:53:29 +0000233 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000234 tileRenderer->setTileHeightPercentage(atof(*argv));
235 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
236 SkDELETE(tileRenderer);
237 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000238 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000239 exit(-1);
240 }
241 } else {
242 tileRenderer->setTileHeight(atoi(*argv));
243 if (!(tileRenderer->getTileHeight() > 0)) {
244 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000245 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000246 exit(-1);
247 }
248 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000249
250 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000251 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000252 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000253 usage(argv0);
254 exit(-1);
255 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000256 } else if (0 == strcmp(*argv, "--device")) {
257 ++argv;
258 if (argv >= stop) {
259 SkDebugf("Missing mode for --deivce\n");
260 usage(argv0);
261 exit(-1);
262 }
263
264 if (0 == strcmp(*argv, "bitmap")) {
265 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
266 }
267#if SK_SUPPORT_GPU
268 else if (0 == strcmp(*argv, "gpu")) {
269 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
270 }
271#endif
272 else {
273 SkDebugf("%s is not a valid mode for --device\n", *argv);
274 usage(argv0);
275 exit(-1);
276 }
277
keyar@chromium.org472b3792012-07-20 22:34:27 +0000278 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000279 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000280 usage(argv0);
281 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000282 } else {
283 inputs->push_back(SkString(*argv));
284 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000285 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000286
287 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000288 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000289 usage(argv0);
290 exit(-1);
291 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000292
293 if (NULL == renderer) {
294 renderer = SkNEW(sk_tools::SimplePictureRenderer);
295 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000296
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000297 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000298}
299
300int main(int argc, char* const argv[]) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000301 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000302 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000303 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000304
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000305 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000306 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000307 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000308
borenet@google.com66bcbd12012-09-17 18:26:06 +0000309 int failures = 0;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000310 for (int i = 0; i < inputs.count() - 1; i ++) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000311 failures += process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000312 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000313 if (failures != 0) {
314 SkDebugf("Failed to render %i pictures.\n", failures);
315 return 1;
316 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000317#if SK_SUPPORT_GPU
318#if GR_CACHE_STATS
319 if (renderer->isUsingGpuDevice()) {
320 GrContext* ctx = renderer->getGrContext();
321
322 ctx->printCacheStats();
323 }
324#endif
325#endif
326
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000327 SkDELETE(renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000328}