blob: 7d54516d8d5d10d3a49135975d7ed33a007a5112 [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
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000082static void 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 }
90}
91
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000092static void render_picture(const SkString& inputPath, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000093 sk_tools::PictureRenderer& renderer) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000094 SkString inputFilename;
95 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +000096
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000097 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +000098 inputStream.setPath(inputPath.c_str());
99 if (!inputStream.isValid()) {
100 SkDebugf("Could not open file %s\n", inputPath.c_str());
101 return;
102 }
103
borenet@google.come21795e2012-09-14 14:34:28 +0000104 SkPicture* picture = SkNEW_ARGS(SkPicture, (&inputStream));
105 SkAutoTUnref<SkPicture> aur(picture);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000106
borenet@google.come21795e2012-09-14 14:34:28 +0000107 SkDebugf("drawing... [%i %i] %s\n", picture->width(), picture->height(),
borenet@google.com03fcee82012-09-10 18:18:38 +0000108 inputPath.c_str());
skia.committer@gmail.com1d225f22012-09-14 02:01:10 +0000109
borenet@google.come21795e2012-09-14 14:34:28 +0000110 // rescale to avoid memory issues allocating a very large offscreen
111 sk_tools::resize_if_needed(&aur);
reed@google.come04e92b2012-09-13 17:44:32 +0000112
borenet@google.come21795e2012-09-14 14:34:28 +0000113 renderer.init(aur);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000114
scroggo@google.com9a412522012-09-07 15:21:18 +0000115 renderer.render(true);
116
117 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000118
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000119 write_output(outputDir, inputFilename, renderer);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000120
121 renderer.end();
junov@chromium.org777442d2012-06-12 14:56:36 +0000122}
123
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000124static void 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;
128
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);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000133 render_picture(inputPath, outputDir, renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000134 } while(iter.next(&inputFilename));
135 } else {
136 SkString inputPath(input);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000137 render_picture(inputPath, outputDir, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000138 }
139}
140
141static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000142 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000143 const char* argv0 = argv[0];
144 char* const* stop = argv + argc;
145
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000146 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
147 sk_tools::PictureRenderer::kBitmap_DeviceType;
148
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000149 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000150 if (0 == strcmp(*argv, "--mode")) {
151 SkDELETE(renderer);
152
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000153 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000154 if (argv >= stop) {
155 SkDebugf("Missing mode for --mode\n");
156 usage(argv0);
157 exit(-1);
158 }
159
160 if (0 == strcmp(*argv, "pipe")) {
161 renderer = SkNEW(sk_tools::PipePictureRenderer);
162 } else if (0 == strcmp(*argv, "simple")) {
163 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000164 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
165 char* mode = *argv;
166 bool isPowerOf2Mode = false;
167
168 if (0 == strcmp(*argv, "pow2tile")) {
169 isPowerOf2Mode = true;
170 }
171
keyar@chromium.org795cd472012-08-02 18:57:53 +0000172 sk_tools::TiledPictureRenderer* tileRenderer =
173 SkNEW(sk_tools::TiledPictureRenderer);
174 ++argv;
175 if (argv >= stop) {
176 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000177 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000178 usage(argv0);
179 exit(-1);
180 }
181
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000182 if (isPowerOf2Mode) {
183 int minWidth = atoi(*argv);
184
185 if (!SkIsPow2(minWidth) || minWidth <= 0) {
186 SkDELETE(tileRenderer);
187 SkDebugf("--mode %s must be given a width"
188 " value that is a power of two\n", mode);
189 exit(-1);
190 }
191
192 tileRenderer->setTileMinPowerOf2Width(minWidth);
193 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000194 tileRenderer->setTileWidthPercentage(atof(*argv));
195 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
196 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000197 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000198 exit(-1);
199 }
200 } else {
201 tileRenderer->setTileWidth(atoi(*argv));
202 if (!(tileRenderer->getTileWidth() > 0)) {
203 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000204 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000205 exit(-1);
206 }
207 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000208
209 ++argv;
210 if (argv >= stop) {
211 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000212 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000213 usage(argv0);
214 exit(-1);
215 }
216
keyar@chromium.org163b5672012-08-01 17:53:29 +0000217 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000218 tileRenderer->setTileHeightPercentage(atof(*argv));
219 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
220 SkDELETE(tileRenderer);
221 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000222 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000223 exit(-1);
224 }
225 } else {
226 tileRenderer->setTileHeight(atoi(*argv));
227 if (!(tileRenderer->getTileHeight() > 0)) {
228 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000229 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000230 exit(-1);
231 }
232 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000233
234 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000235 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000236 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000237 usage(argv0);
238 exit(-1);
239 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000240 } else if (0 == strcmp(*argv, "--device")) {
241 ++argv;
242 if (argv >= stop) {
243 SkDebugf("Missing mode for --deivce\n");
244 usage(argv0);
245 exit(-1);
246 }
247
248 if (0 == strcmp(*argv, "bitmap")) {
249 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
250 }
251#if SK_SUPPORT_GPU
252 else if (0 == strcmp(*argv, "gpu")) {
253 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
254 }
255#endif
256 else {
257 SkDebugf("%s is not a valid mode for --device\n", *argv);
258 usage(argv0);
259 exit(-1);
260 }
261
keyar@chromium.org472b3792012-07-20 22:34:27 +0000262 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000263 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000264 usage(argv0);
265 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000266 } else {
267 inputs->push_back(SkString(*argv));
268 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000269 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000270
271 if (inputs->count() < 2) {
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);
275 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000276
277 if (NULL == renderer) {
278 renderer = SkNEW(sk_tools::SimplePictureRenderer);
279 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000280
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000281 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000282}
283
284int main(int argc, char* const argv[]) {
borenet@google.com10ef79e2012-09-10 17:19:06 +0000285 SkGraphics::Init();
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000286 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000287 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000288
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000289 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000290 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000291 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000292
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000293 for (int i = 0; i < inputs.count() - 1; i ++) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000294 process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000295 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000296
robertphillips@google.com163c84b2012-09-13 15:40:37 +0000297#if SK_SUPPORT_GPU
298#if GR_CACHE_STATS
299 if (renderer->isUsingGpuDevice()) {
300 GrContext* ctx = renderer->getGrContext();
301
302 ctx->printCacheStats();
303 }
304#endif
305#endif
306
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000307 SkDELETE(renderer);
borenet@google.com10ef79e2012-09-10 17:19:06 +0000308 SkGraphics::Term();
junov@chromium.org777442d2012-06-12 14:56:36 +0000309}