blob: 5ad00729dd570601b0bb2659d45ee10b1c119f4f [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.com66bcbd12012-09-17 18:26:06 +0000140 if (!render_picture(inputPath, outputDir, renderer))
141 ++failures;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000142 } while(iter.next(&inputFilename));
143 } else {
144 SkString inputPath(input);
borenet@google.com66bcbd12012-09-17 18:26:06 +0000145 if (!render_picture(inputPath, outputDir, renderer))
146 ++failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000147 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000148 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000149}
150
151static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000152 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000153 const char* argv0 = argv[0];
154 char* const* stop = argv + argc;
155
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000156 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
157 sk_tools::PictureRenderer::kBitmap_DeviceType;
158
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000159 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000160 if (0 == strcmp(*argv, "--mode")) {
161 SkDELETE(renderer);
162
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000163 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000164 if (argv >= stop) {
165 SkDebugf("Missing mode for --mode\n");
166 usage(argv0);
167 exit(-1);
168 }
169
170 if (0 == strcmp(*argv, "pipe")) {
171 renderer = SkNEW(sk_tools::PipePictureRenderer);
172 } else if (0 == strcmp(*argv, "simple")) {
173 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000174 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
175 char* mode = *argv;
176 bool isPowerOf2Mode = false;
177
178 if (0 == strcmp(*argv, "pow2tile")) {
179 isPowerOf2Mode = true;
180 }
181
keyar@chromium.org795cd472012-08-02 18:57:53 +0000182 sk_tools::TiledPictureRenderer* tileRenderer =
183 SkNEW(sk_tools::TiledPictureRenderer);
184 ++argv;
185 if (argv >= stop) {
186 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000187 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000188 usage(argv0);
189 exit(-1);
190 }
191
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000192 if (isPowerOf2Mode) {
193 int minWidth = atoi(*argv);
194
195 if (!SkIsPow2(minWidth) || minWidth <= 0) {
196 SkDELETE(tileRenderer);
197 SkDebugf("--mode %s must be given a width"
198 " value that is a power of two\n", mode);
199 exit(-1);
200 }
201
202 tileRenderer->setTileMinPowerOf2Width(minWidth);
203 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000204 tileRenderer->setTileWidthPercentage(atof(*argv));
205 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
206 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000207 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000208 exit(-1);
209 }
210 } else {
211 tileRenderer->setTileWidth(atoi(*argv));
212 if (!(tileRenderer->getTileWidth() > 0)) {
213 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000214 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000215 exit(-1);
216 }
217 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000218
219 ++argv;
220 if (argv >= stop) {
221 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000222 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000223 usage(argv0);
224 exit(-1);
225 }
226
keyar@chromium.org163b5672012-08-01 17:53:29 +0000227 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000228 tileRenderer->setTileHeightPercentage(atof(*argv));
229 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
230 SkDELETE(tileRenderer);
231 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000232 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000233 exit(-1);
234 }
235 } else {
236 tileRenderer->setTileHeight(atoi(*argv));
237 if (!(tileRenderer->getTileHeight() > 0)) {
238 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000239 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000240 exit(-1);
241 }
242 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000243
244 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000245 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000246 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000247 usage(argv0);
248 exit(-1);
249 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000250 } else if (0 == strcmp(*argv, "--device")) {
251 ++argv;
252 if (argv >= stop) {
253 SkDebugf("Missing mode for --deivce\n");
254 usage(argv0);
255 exit(-1);
256 }
257
258 if (0 == strcmp(*argv, "bitmap")) {
259 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
260 }
261#if SK_SUPPORT_GPU
262 else if (0 == strcmp(*argv, "gpu")) {
263 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
264 }
265#endif
266 else {
267 SkDebugf("%s is not a valid mode for --device\n", *argv);
268 usage(argv0);
269 exit(-1);
270 }
271
keyar@chromium.org472b3792012-07-20 22:34:27 +0000272 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000273 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000274 usage(argv0);
275 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000276 } else {
277 inputs->push_back(SkString(*argv));
278 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000279 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000280
281 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000282 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000283 usage(argv0);
284 exit(-1);
285 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000286
287 if (NULL == renderer) {
288 renderer = SkNEW(sk_tools::SimplePictureRenderer);
289 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000290
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000291 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000292}
293
294int main(int argc, char* const argv[]) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000295 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000296 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000297 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000298
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000299 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000300 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000301 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000302
borenet@google.com66bcbd12012-09-17 18:26:06 +0000303 int failures = 0;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000304 for (int i = 0; i < inputs.count() - 1; i ++) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000305 failures += process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000306 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000307 if (failures != 0) {
308 SkDebugf("Failed to render %i pictures.\n", failures);
309 return 1;
310 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000311#if SK_SUPPORT_GPU
312#if GR_CACHE_STATS
313 if (renderer->isUsingGpuDevice()) {
314 GrContext* ctx = renderer->getGrContext();
315
316 ctx->printCacheStats();
317 }
318#endif
319#endif
320
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000321 SkDELETE(renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000322}