blob: da0740a45b4bdc270ae9b012275b1e2ab16b1101 [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);
scroggo@google.comb4773b42012-10-01 20:06:09 +0000105 renderer.setup();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000106
scroggo@google.com81f9d2e2012-09-20 14:54:21 +0000107 SkString outputPath;
108 make_output_filepath(&outputPath, outputDir, inputFilename);
109
110 success = renderer.render(&outputPath);
111 if (!success) {
112 SkDebugf("Could not write to file %s\n", outputPath.c_str());
113 }
scroggo@google.com9a412522012-09-07 15:21:18 +0000114
115 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000116
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000117 renderer.end();
borenet@google.com66bcbd12012-09-17 18:26:06 +0000118 return success;
junov@chromium.org777442d2012-06-12 14:56:36 +0000119}
120
borenet@google.com66bcbd12012-09-17 18:26:06 +0000121static int process_input(const SkString& input, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000122 sk_tools::PictureRenderer& renderer) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000123 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000124 SkString inputFilename;
borenet@google.com66bcbd12012-09-17 18:26:06 +0000125 int failures = 0;
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000126 if (iter.next(&inputFilename)) {
127 do {
128 SkString inputPath;
129 sk_tools::make_filepath(&inputPath, input, inputFilename);
borenet@google.com57837bf2012-09-19 17:28:29 +0000130 if (!render_picture(inputPath, outputDir, renderer)) {
131 ++failures;
132 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000133 } while(iter.next(&inputFilename));
borenet@google.com57837bf2012-09-19 17:28:29 +0000134 } else if (SkStrEndsWith(input.c_str(), ".skp")) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000135 SkString inputPath(input);
borenet@google.com57837bf2012-09-19 17:28:29 +0000136 if (!render_picture(inputPath, outputDir, renderer)) {
137 ++failures;
138 }
139 } else {
140 SkString warning;
141 warning.printf("Warning: skipping %s\n", input.c_str());
142 SkDebugf(warning.c_str());
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000143 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000144 return failures;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000145}
146
147static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000148 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000149 const char* argv0 = argv[0];
150 char* const* stop = argv + argc;
151
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000152 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
153 sk_tools::PictureRenderer::kBitmap_DeviceType;
154
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000155 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000156 if (0 == strcmp(*argv, "--mode")) {
157 SkDELETE(renderer);
158
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000159 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000160 if (argv >= stop) {
161 SkDebugf("Missing mode for --mode\n");
162 usage(argv0);
163 exit(-1);
164 }
165
166 if (0 == strcmp(*argv, "pipe")) {
167 renderer = SkNEW(sk_tools::PipePictureRenderer);
168 } else if (0 == strcmp(*argv, "simple")) {
169 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000170 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
171 char* mode = *argv;
172 bool isPowerOf2Mode = false;
173
174 if (0 == strcmp(*argv, "pow2tile")) {
175 isPowerOf2Mode = true;
176 }
177
keyar@chromium.org795cd472012-08-02 18:57:53 +0000178 sk_tools::TiledPictureRenderer* tileRenderer =
179 SkNEW(sk_tools::TiledPictureRenderer);
180 ++argv;
181 if (argv >= stop) {
182 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000183 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000184 usage(argv0);
185 exit(-1);
186 }
187
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000188 if (isPowerOf2Mode) {
189 int minWidth = atoi(*argv);
190
191 if (!SkIsPow2(minWidth) || minWidth <= 0) {
192 SkDELETE(tileRenderer);
193 SkDebugf("--mode %s must be given a width"
194 " value that is a power of two\n", mode);
195 exit(-1);
196 }
197
198 tileRenderer->setTileMinPowerOf2Width(minWidth);
199 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000200 tileRenderer->setTileWidthPercentage(atof(*argv));
201 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
202 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000203 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000204 exit(-1);
205 }
206 } else {
207 tileRenderer->setTileWidth(atoi(*argv));
208 if (!(tileRenderer->getTileWidth() > 0)) {
209 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000210 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000211 exit(-1);
212 }
213 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000214
215 ++argv;
216 if (argv >= stop) {
217 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000218 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000219 usage(argv0);
220 exit(-1);
221 }
222
keyar@chromium.org163b5672012-08-01 17:53:29 +0000223 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000224 tileRenderer->setTileHeightPercentage(atof(*argv));
225 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
226 SkDELETE(tileRenderer);
227 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000228 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000229 exit(-1);
230 }
231 } else {
232 tileRenderer->setTileHeight(atoi(*argv));
233 if (!(tileRenderer->getTileHeight() > 0)) {
234 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000235 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000236 exit(-1);
237 }
238 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000239
240 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000241 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000242 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000243 usage(argv0);
244 exit(-1);
245 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000246 } else if (0 == strcmp(*argv, "--device")) {
247 ++argv;
248 if (argv >= stop) {
249 SkDebugf("Missing mode for --deivce\n");
250 usage(argv0);
251 exit(-1);
252 }
253
254 if (0 == strcmp(*argv, "bitmap")) {
255 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
256 }
257#if SK_SUPPORT_GPU
258 else if (0 == strcmp(*argv, "gpu")) {
259 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
260 }
261#endif
262 else {
263 SkDebugf("%s is not a valid mode for --device\n", *argv);
264 usage(argv0);
265 exit(-1);
266 }
267
keyar@chromium.org472b3792012-07-20 22:34:27 +0000268 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000269 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000270 usage(argv0);
271 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000272 } else {
273 inputs->push_back(SkString(*argv));
274 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000275 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000276
277 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000278 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000279 usage(argv0);
280 exit(-1);
281 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000282
283 if (NULL == renderer) {
284 renderer = SkNEW(sk_tools::SimplePictureRenderer);
285 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000286
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000287 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000288}
289
caryclark@google.com5987f582012-10-02 18:33:14 +0000290int tool_main(int argc, char** argv);
291int tool_main(int argc, char** argv) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000292 SkAutoGraphics ag;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000293 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000294 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000295
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000296 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000297 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000298 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000299
borenet@google.com66bcbd12012-09-17 18:26:06 +0000300 int failures = 0;
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000301 for (int i = 0; i < inputs.count() - 1; i ++) {
borenet@google.com66bcbd12012-09-17 18:26:06 +0000302 failures += process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000303 }
borenet@google.com66bcbd12012-09-17 18:26:06 +0000304 if (failures != 0) {
305 SkDebugf("Failed to render %i pictures.\n", failures);
306 return 1;
307 }
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000308#if SK_SUPPORT_GPU
309#if GR_CACHE_STATS
310 if (renderer->isUsingGpuDevice()) {
311 GrContext* ctx = renderer->getGrContext();
312
313 ctx->printCacheStats();
314 }
315#endif
316#endif
317
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000318 SkDELETE(renderer);
caryclark@google.com868e1f62012-10-02 20:00:03 +0000319 return 0;
junov@chromium.org777442d2012-06-12 14:56:36 +0000320}
caryclark@google.com5987f582012-10-02 18:33:14 +0000321
322#if !defined SK_BUILD_FOR_IOS
323int main(int argc, char * const argv[]) {
324 return tool_main(argc, (char**) argv);
325}
326#endif