blob: 5a7ff44e0f2bb8da442f2de5a1376b03568884ab [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);
scroggo@google.com81f9d2e2012-09-20 14:54:21 +000078 // Remove ".skp"
79 path->remove(path->size() - 4, 4);
junov@chromium.org777442d2012-06-12 14:56:36 +000080}
81
borenet@google.com66bcbd12012-09-17 18:26:06 +000082static bool render_picture(const SkString& inputPath, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000083 sk_tools::PictureRenderer& renderer) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000084 SkString inputFilename;
85 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +000086
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000087 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +000088 inputStream.setPath(inputPath.c_str());
89 if (!inputStream.isValid()) {
90 SkDebugf("Could not open file %s\n", inputPath.c_str());
borenet@google.com66bcbd12012-09-17 18:26:06 +000091 return false;
twiz@google.coma31b8bb2012-06-22 18:24:56 +000092 }
93
borenet@google.com66bcbd12012-09-17 18:26:06 +000094 bool success = false;
95 SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream, &success));
borenet@google.come21795e2012-09-14 14:34:28 +000096 SkAutoTUnref<SkPicture> aur(picture);
borenet@google.com66bcbd12012-09-17 18:26:06 +000097 if (!success) {
98 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
99 return false;
100 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000101
borenet@google.come21795e2012-09-14 14:34:28 +0000102 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000103 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000104
borenet@google.come21795e2012-09-14 14:34:28 +0000105 // rescale to avoid memory issues allocating a very large offscreen
106 sk_tools::resize_if_needed(&aur);
reed@google.come04e92b2012-09-13 17:44:32 +0000107
borenet@google.come21795e2012-09-14 14:34:28 +0000108 renderer.init(aur);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000109
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000110 SkString outputPath;
111 make_output_filepath(&outputPath, outputDir, inputFilename);
112
113 success = renderer.render(&outputPath);
114 if (!success) {
115 SkDebugf("Could not write to file %s\n", outputPath.c_str());
116 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000117
118 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000119
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000120 renderer.end();
borenet@google.com66bcbd12012-09-17 18:26:06 +0000121 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000122}
123
borenet@google.com66bcbd12012-09-17 18:26:06 +0000124static int process_input(const SkString& input, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000125 sk_tools::PictureRenderer& renderer) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000126 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000127 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000128 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000129 if (iter.next(&inputFilename)) {
130 do {
131 SkString inputPath;
132 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000133 if (!render_picture(inputPath, outputDir, renderer)) {
134 ++failures;
135 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000136 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000137 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000138 SkString inputPath(input);
borenet@google.com57837bf2012-09-19 17:28:29 +0000139 if (!render_picture(inputPath, outputDir, renderer)) {
140 ++failures;
141 }
142 } else {
143 SkString warning;
144 warning.printf("Warning: skipping %s\n", input.c_str());
145 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000146 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000147 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000148}
149
150static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000151 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000152 const char* argv0 = argv[0];
153 char* const* stop = argv + argc;
154
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000155 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
156 sk_tools::PictureRenderer::kBitmap_DeviceType;
157
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000158 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000159 if (0 == strcmp(*argv, "--mode")) {
160 SkDELETE(renderer);
161
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000162 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000163 if (argv >= stop) {
164 SkDebugf("Missing mode for --mode\n");
165 usage(argv0);
166 exit(-1);
167 }
168
169 if (0 == strcmp(*argv, "pipe")) {
170 renderer = SkNEW(sk_tools::PipePictureRenderer);
171 } else if (0 == strcmp(*argv, "simple")) {
172 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000173 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
174 char* mode = *argv;
175 bool isPowerOf2Mode = false;
176
177 if (0 == strcmp(*argv, "pow2tile")) {
178 isPowerOf2Mode = true;
179 }
180
keyar@chromium.org795cd472012-08-02 18:57:53 +0000181 sk_tools::TiledPictureRenderer* tileRenderer =
182 SkNEW(sk_tools::TiledPictureRenderer);
183 ++argv;
184 if (argv >= stop) {
185 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000186 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000187 usage(argv0);
188 exit(-1);
189 }
190
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000191 if (isPowerOf2Mode) {
192 int minWidth = atoi(*argv);
193
194 if (!SkIsPow2(minWidth) || minWidth <= 0) {
195 SkDELETE(tileRenderer);
196 SkDebugf("--mode %s must be given a width"
197 " value that is a power of two\n", mode);
198 exit(-1);
199 }
200
201 tileRenderer->setTileMinPowerOf2Width(minWidth);
202 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000203 tileRenderer->setTileWidthPercentage(atof(*argv));
204 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
205 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000206 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000207 exit(-1);
208 }
209 } else {
210 tileRenderer->setTileWidth(atoi(*argv));
211 if (!(tileRenderer->getTileWidth() > 0)) {
212 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000213 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000214 exit(-1);
215 }
216 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000217
218 ++argv;
219 if (argv >= stop) {
220 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000221 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000222 usage(argv0);
223 exit(-1);
224 }
225
keyar@chromium.org163b5672012-08-01 17:53:29 +0000226 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000227 tileRenderer->setTileHeightPercentage(atof(*argv));
228 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
229 SkDELETE(tileRenderer);
230 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000231 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000232 exit(-1);
233 }
234 } else {
235 tileRenderer->setTileHeight(atoi(*argv));
236 if (!(tileRenderer->getTileHeight() > 0)) {
237 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000238 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000239 exit(-1);
240 }
241 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000242
243 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000244 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000245 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000246 usage(argv0);
247 exit(-1);
248 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000249 } else if (0 == strcmp(*argv, "--device")) {
250 ++argv;
251 if (argv >= stop) {
252 SkDebugf("Missing mode for --deivce\n");
253 usage(argv0);
254 exit(-1);
255 }
256
257 if (0 == strcmp(*argv, "bitmap")) {
258 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
259 }
260#if SK_SUPPORT_GPU
261 else if (0 == strcmp(*argv, "gpu")) {
262 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
263 }
264#endif
265 else {
266 SkDebugf("%s is not a valid mode for --device\n", *argv);
267 usage(argv0);
268 exit(-1);
269 }
270
keyar@chromium.org472b3792012-07-20 22:34:27 +0000271 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000272 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000273 usage(argv0);
274 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000275 } else {
276 inputs->push_back(SkString(*argv));
277 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000278 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000279
280 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000281 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000282 usage(argv0);
283 exit(-1);
284 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000285
286 if (NULL == renderer) {
287 renderer = SkNEW(sk_tools::SimplePictureRenderer);
288 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000289
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000290 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000291}
292
293int main(int argc, char* const argv[]) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000294 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000295 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000296 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000297
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000298 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000299 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000300 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000301
borenet@google.com66bcbd12012-09-17 18:26:06 +0000302 int failures = 0;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000303 for (int i = 0; i < inputs.count() - 1; i ++) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000304 failures += process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000305 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000306 if (failures != 0) {
307 SkDebugf("Failed to render %i pictures.\n", failures);
308 return 1;
309 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000310#if SK_SUPPORT_GPU
311#if GR_CACHE_STATS
312 if (renderer->isUsingGpuDevice()) {
313 GrContext* ctx = renderer->getGrContext();
314
315 ctx->printCacheStats();
316 }
317#endif
318#endif
319
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000320 SkDELETE(renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000321}