blob: 6066334416856019fd0cd06ba1ffd6e968beb3fb [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;
borenet@google.com2d2b9a02012-09-20 18:54:04 +000095 SkPicture picture(&inputStream, &success);
borenet@google.com66bcbd12012-09-17 18:26:06 +000096 if (!success) {
97 SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
98 return false;
99 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000100
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000101 SkDebugf("drawing... [%i %i] %s\n", picture.width(), picture.height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000102 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000103
borenet@google.com2d2b9a02012-09-20 18:54:04 +0000104 renderer.init(&picture);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000105
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000106 SkString outputPath;
107 make_output_filepath(&outputPath, outputDir, inputFilename);
108
109 success = renderer.render(&outputPath);
110 if (!success) {
111 SkDebugf("Could not write to file %s\n", outputPath.c_str());
112 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000113
114 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000115
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000116 renderer.end();
borenet@google.com66bcbd12012-09-17 18:26:06 +0000117 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000118}
119
borenet@google.com66bcbd12012-09-17 18:26:06 +0000120static int process_input(const SkString& input, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000121 sk_tools::PictureRenderer& renderer) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000122 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000123 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000124 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000125 if (iter.next(&inputFilename)) {
126 do {
127 SkString inputPath;
128 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000129 if (!render_picture(inputPath, outputDir, renderer)) {
130 ++failures;
131 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000132 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000133 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000134 SkString inputPath(input);
borenet@google.com57837bf2012-09-19 17:28:29 +0000135 if (!render_picture(inputPath, outputDir, renderer)) {
136 ++failures;
137 }
138 } else {
139 SkString warning;
140 warning.printf("Warning: skipping %s\n", input.c_str());
141 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000142 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000143 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000144}
145
146static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000147 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000148 const char* argv0 = argv[0];
149 char* const* stop = argv + argc;
150
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000151 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
152 sk_tools::PictureRenderer::kBitmap_DeviceType;
153
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000154 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000155 if (0 == strcmp(*argv, "--mode")) {
156 SkDELETE(renderer);
157
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000158 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000159 if (argv >= stop) {
160 SkDebugf("Missing mode for --mode\n");
161 usage(argv0);
162 exit(-1);
163 }
164
165 if (0 == strcmp(*argv, "pipe")) {
166 renderer = SkNEW(sk_tools::PipePictureRenderer);
167 } else if (0 == strcmp(*argv, "simple")) {
168 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000169 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
170 char* mode = *argv;
171 bool isPowerOf2Mode = false;
172
173 if (0 == strcmp(*argv, "pow2tile")) {
174 isPowerOf2Mode = true;
175 }
176
keyar@chromium.org795cd472012-08-02 18:57:53 +0000177 sk_tools::TiledPictureRenderer* tileRenderer =
178 SkNEW(sk_tools::TiledPictureRenderer);
179 ++argv;
180 if (argv >= stop) {
181 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000182 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000183 usage(argv0);
184 exit(-1);
185 }
186
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000187 if (isPowerOf2Mode) {
188 int minWidth = atoi(*argv);
189
190 if (!SkIsPow2(minWidth) || minWidth <= 0) {
191 SkDELETE(tileRenderer);
192 SkDebugf("--mode %s must be given a width"
193 " value that is a power of two\n", mode);
194 exit(-1);
195 }
196
197 tileRenderer->setTileMinPowerOf2Width(minWidth);
198 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000199 tileRenderer->setTileWidthPercentage(atof(*argv));
200 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
201 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000202 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000203 exit(-1);
204 }
205 } else {
206 tileRenderer->setTileWidth(atoi(*argv));
207 if (!(tileRenderer->getTileWidth() > 0)) {
208 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000209 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000210 exit(-1);
211 }
212 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000213
214 ++argv;
215 if (argv >= stop) {
216 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000217 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000218 usage(argv0);
219 exit(-1);
220 }
221
keyar@chromium.org163b5672012-08-01 17:53:29 +0000222 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000223 tileRenderer->setTileHeightPercentage(atof(*argv));
224 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
225 SkDELETE(tileRenderer);
226 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000227 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000228 exit(-1);
229 }
230 } else {
231 tileRenderer->setTileHeight(atoi(*argv));
232 if (!(tileRenderer->getTileHeight() > 0)) {
233 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000234 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000235 exit(-1);
236 }
237 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000238
239 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000240 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000241 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000242 usage(argv0);
243 exit(-1);
244 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000245 } else if (0 == strcmp(*argv, "--device")) {
246 ++argv;
247 if (argv >= stop) {
248 SkDebugf("Missing mode for --deivce\n");
249 usage(argv0);
250 exit(-1);
251 }
252
253 if (0 == strcmp(*argv, "bitmap")) {
254 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
255 }
256#if SK_SUPPORT_GPU
257 else if (0 == strcmp(*argv, "gpu")) {
258 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
259 }
260#endif
261 else {
262 SkDebugf("%s is not a valid mode for --device\n", *argv);
263 usage(argv0);
264 exit(-1);
265 }
266
keyar@chromium.org472b3792012-07-20 22:34:27 +0000267 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000268 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000269 usage(argv0);
270 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000271 } else {
272 inputs->push_back(SkString(*argv));
273 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000274 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000275
276 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000277 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000278 usage(argv0);
279 exit(-1);
280 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000281
282 if (NULL == renderer) {
283 renderer = SkNEW(sk_tools::SimplePictureRenderer);
284 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000285
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000286 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000287}
288
289int main(int argc, char* const argv[]) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000290 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000291 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000292 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000293
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000294 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000295 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000296 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000297
borenet@google.com66bcbd12012-09-17 18:26:06 +0000298 int failures = 0;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000299 for (int i = 0; i < inputs.count() - 1; i ++) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000300 failures += process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000301 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000302 if (failures != 0) {
303 SkDebugf("Failed to render %i pictures.\n", failures);
304 return 1;
305 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000306#if SK_SUPPORT_GPU
307#if GR_CACHE_STATS
308 if (renderer->isUsingGpuDevice()) {
309 GrContext* ctx = renderer->getGrContext();
310
311 ctx->printCacheStats();
312 }
313#endif
314#endif
315
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000316 SkDELETE(renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000317}