blob: e1cc72fe852d31fcbaf8ccfe233fc0513f8a3b18 [file] [log] [blame]
scroggo@google.com161e1ba2013-03-04 16:41:06 +00001/*
2 * Copyright 2013 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
8#include "PictureRenderingFlags.h"
9
10#include "CopyTilesRenderer.h"
11#include "PictureRenderer.h"
12#include "picture_utils.h"
scroggo@google.comd9ba9a02013-03-21 19:43:15 +000013#include "SkCommandLineFlags.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000014#include "SkData.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000015#include "SkImage.h"
16#include "SkImageDecoder.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000017#include "SkString.h"
scroggo@google.com161e1ba2013-03-04 16:41:06 +000018
19// Alphabetized list of flags used by this file or bench_ and render_pictures.
20DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarchy type to "
21 "be used. Accepted values are: none, rtree, grid. "
22 "Not compatible with --pipe. With value "
23 "'grid', width and height must be specified. 'grid' can "
24 "only be used with modes tile, record, and "
25 "playbackCreation.");
26// Although this config does not support all the same options as gm, the names should be kept
27// consistent.
rmistry@google.com6ab96732014-01-06 18:37:24 +000028DEFINE_string(config, "8888", "["
29 "8888"
30#if SK_SUPPORT_GPU
31 "|gpu|msaa4|msaa16"
scroggo@google.com161e1ba2013-03-04 16:41:06 +000032#endif
rmistry@google.com6ab96732014-01-06 18:37:24 +000033#if SK_ANGLE
34 "|angle"
35#endif
36#if SK_MESA
37 "|mesa"
38#endif
39 "]: Use the corresponding config.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000040
41DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. "
42 "Has no effect if the provided skp does not have its images encoded.");
43DEFINE_string(mode, "simple", "Run in the corresponding mode:\n"
44 "simple: Simple rendering.\n"
45 "tile width height: Use tiles with the given dimensions or percentages.\n"
46 "pow2tile minWidth height: Use tiles with widths that are all a power\n"
47 "\tof two such that they minimize the amount of wasted tile space.\n"
48 "\tminWidth must be a power of two.\n"
49 "copyTile width height: Draw the picture, then copy into tiles. If the\n"
50 "\tpicture is large enough, it is broken into larger tiles to avoid\n"
51 "\tcreating a large canvas.\n"
52// TODO: If bench_pictures and render_pictures were two separate targets, we could use build flags
53// to determine which modes to display.
54 "record: (Only in bench_pictures) Time recording from a picture to a new\n"
55 "\tpicture.\n"
56 "playbackCreation: (Only in bench_pictures) Time creation of the \n"
57 "\tSkPicturePlayback.\n"
58 "rerecord: (Only in render_pictures) Record the picture as a new skp,\n"
59 "\twith the bitmaps PNG encoded.\n");
60DEFINE_int32(multi, 1, "Set the number of threads for multi threaded drawing. "
61 "If > 1, requires tiled rendering.");
62DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\".");
scroggo@google.com604e0c22013-04-09 21:25:46 +000063DEFINE_string2(readPath, r, "", "skp files or directories of skp files to process.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000064DEFINE_double(scale, 1, "Set the scale factor.");
65DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile "
66 "in the x and y directions.");
67DEFINE_string(viewport, "", "width height: Set the viewport.");
68
69sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
70 error.reset();
71
72 if (FLAGS_multi <= 0) {
73 error.printf("--multi must be > 0, was %i", FLAGS_multi);
74 return NULL;
75 }
76
77 bool useTiles = false;
78 const char* widthString = NULL;
79 const char* heightString = NULL;
80 bool isPowerOf2Mode = false;
81 bool isCopyMode = false;
82 const char* mode = NULL;
83 bool gridSupported = false;
84
85 SkAutoTUnref<sk_tools::PictureRenderer> renderer;
86 if (FLAGS_mode.count() >= 1) {
87 mode = FLAGS_mode[0];
88 if (0 == strcmp(mode, "record")) {
89 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
90 gridSupported = true;
91 // undocumented
92 } else if (0 == strcmp(mode, "clone")) {
93 renderer.reset(sk_tools::CreatePictureCloneRenderer());
94 } else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile")
95 || 0 == strcmp(mode, "copyTile")) {
96 useTiles = true;
97
98 if (0 == strcmp(mode, "pow2tile")) {
99 isPowerOf2Mode = true;
100 } else if (0 == strcmp(mode, "copyTile")) {
101 isCopyMode = true;
102 } else {
103 gridSupported = true;
104 }
105
106 if (FLAGS_mode.count() < 2) {
107 error.printf("Missing width for --mode %s\n", mode);
108 return NULL;
109 }
110
111 widthString = FLAGS_mode[1];
112 if (FLAGS_mode.count() < 3) {
113 error.printf("Missing height for --mode %s\n", mode);
114 return NULL;
115 }
116
117 heightString = FLAGS_mode[2];
118 } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
119 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
120 gridSupported = true;
121 // undocumented
122 } else if (0 == strcmp(mode, "gatherPixelRefs") && kBench_PictureTool == tool) {
123 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
124 } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
125 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
126 // Allow 'mode' to be set to 'simple', but do not create a renderer, so we can
127 // ensure that pipe does not override a mode besides simple. The renderer will
128 // be created below.
129 } else if (0 != strcmp(mode, "simple")) {
130 error.printf("%s is not a valid mode for --mode\n", mode);
131 return NULL;
132 }
133 }
134
135 if (useTiles) {
136 SkASSERT(NULL == renderer);
137 SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer;
138 if (isCopyMode) {
139 int xTiles = -1;
140 int yTiles = -1;
141 if (FLAGS_tiles.count() > 0) {
142 if (FLAGS_tiles.count() != 2) {
143 error.printf("--tiles requires an x value and a y value.\n");
144 return NULL;
145 }
146 xTiles = atoi(FLAGS_tiles[0]);
147 yTiles = atoi(FLAGS_tiles[1]);
148 }
149
150 int x, y;
151 if (xTiles != -1 && yTiles != -1) {
152 x = xTiles;
153 y = yTiles;
154 if (x <= 0 || y <= 0) {
155 error.printf("--tiles must be given values > 0\n");
156 return NULL;
157 }
158 } else {
159 x = y = 4;
160 }
161 tiledRenderer.reset(SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)));
162 } else if (FLAGS_multi > 1) {
163 tiledRenderer.reset(SkNEW_ARGS(sk_tools::MultiCorePictureRenderer,
164 (FLAGS_multi)));
165 } else {
166 tiledRenderer.reset(SkNEW(sk_tools::TiledPictureRenderer));
167 }
168
169 if (isPowerOf2Mode) {
170 int minWidth = atoi(widthString);
171 if (!SkIsPow2(minWidth) || minWidth < 0) {
172 SkString err;
173 error.printf("-mode %s must be given a width"
174 " value that is a power of two\n", mode);
175 return NULL;
176 }
177 tiledRenderer->setTileMinPowerOf2Width(minWidth);
178 } else if (sk_tools::is_percentage(widthString)) {
179 if (isCopyMode) {
180 error.printf("--mode %s does not support percentages.\n", mode);
181 return NULL;
182 }
183 tiledRenderer->setTileWidthPercentage(atof(widthString));
184 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
185 error.printf("--mode %s must be given a width percentage > 0\n", mode);
186 return NULL;
187 }
188 } else {
189 tiledRenderer->setTileWidth(atoi(widthString));
190 if (!(tiledRenderer->getTileWidth() > 0)) {
191 error.printf("--mode %s must be given a width > 0\n", mode);
192 return NULL;
193 }
194 }
195
196 if (sk_tools::is_percentage(heightString)) {
197 if (isCopyMode) {
198 error.printf("--mode %s does not support percentages.\n", mode);
199 return NULL;
200 }
201 tiledRenderer->setTileHeightPercentage(atof(heightString));
202 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
203 error.printf("--mode %s must be given a height percentage > 0\n", mode);
204 return NULL;
205 }
206 } else {
207 tiledRenderer->setTileHeight(atoi(heightString));
208 if (!(tiledRenderer->getTileHeight() > 0)) {
209 SkString err;
210 error.printf("--mode %s must be given a height > 0\n", mode);
211 return NULL;
212 }
213 }
214
215 renderer.reset(tiledRenderer.detach());
216 if (FLAGS_pipe) {
217 error.printf("Pipe rendering is currently not compatible with tiling.\n"
218 "Turning off pipe.\n");
219 }
220
221 } else { // useTiles
222 if (FLAGS_multi > 1) {
223 error.printf("Multithreaded drawing requires tiled rendering.\n");
224 return NULL;
225 }
226 if (FLAGS_pipe) {
227 if (renderer != NULL) {
228 error.printf("Pipe is incompatible with other modes.\n");
229 return NULL;
230 }
231 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
232 }
233 }
234
235 if (NULL == renderer) {
236 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
237 }
238
239 if (FLAGS_viewport.count() > 0) {
240 if (FLAGS_viewport.count() != 2) {
241 error.printf("--viewport requires a width and a height.\n");
242 return NULL;
243 }
244 SkISize viewport;
245 viewport.fWidth = atoi(FLAGS_viewport[0]);
246 viewport.fHeight = atoi(FLAGS_viewport[1]);
247 renderer->setViewport(viewport);
248 }
249
250 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
251 sk_tools::PictureRenderer::kBitmap_DeviceType;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000252#if SK_SUPPORT_GPU
253 int sampleCount = 0;
254#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000255 if (FLAGS_config.count() > 0) {
256 if (0 == strcmp(FLAGS_config[0], "8888")) {
257 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
258 }
259#if SK_SUPPORT_GPU
260 else if (0 == strcmp(FLAGS_config[0], "gpu")) {
261 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
262 if (FLAGS_multi > 1) {
263 error.printf("GPU not compatible with multithreaded tiling.\n");
264 return NULL;
265 }
266 }
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000267 else if (0 == strcmp(FLAGS_config[0], "msaa4")) {
268 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
269 if (FLAGS_multi > 1) {
270 error.printf("GPU not compatible with multithreaded tiling.\n");
271 return NULL;
272 }
273 sampleCount = 4;
274 }
275 else if (0 == strcmp(FLAGS_config[0], "msaa16")) {
276 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
277 if (FLAGS_multi > 1) {
278 error.printf("GPU not compatible with multithreaded tiling.\n");
279 return NULL;
280 }
281 sampleCount = 16;
282 }
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000283#if SK_ANGLE
284 else if (0 == strcmp(FLAGS_config[0], "angle")) {
285 deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
286 if (FLAGS_multi > 1) {
287 error.printf("Angle not compatible with multithreaded tiling.\n");
288 return NULL;
289 }
290 }
291#endif
rmistry@google.com6ab96732014-01-06 18:37:24 +0000292#if SK_MESA
293 else if (0 == strcmp(FLAGS_config[0], "mesa")) {
294 deviceType = sk_tools::PictureRenderer::kMesa_DeviceType;
295 if (FLAGS_multi > 1) {
296 error.printf("Mesa not compatible with multithreaded tiling.\n");
297 return NULL;
298 }
299 }
300#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000301#endif
302 else {
303 error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]);
304 return NULL;
305 }
306 renderer->setDeviceType(deviceType);
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000307#if SK_SUPPORT_GPU
308 renderer->setSampleCount(sampleCount);
309#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000310 }
311
312
313 sk_tools::PictureRenderer::BBoxHierarchyType bbhType
314 = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
315 if (FLAGS_bbh.count() > 0) {
316 const char* type = FLAGS_bbh[0];
317 if (0 == strcmp(type, "none")) {
318 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
319 } else if (0 == strcmp(type, "rtree")) {
320 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
321 } else if (0 == strcmp(type, "grid")) {
322 if (!gridSupported) {
323 error.printf("'--bbh grid' is not compatible with --mode=%s.\n", mode);
324 return NULL;
325 }
326 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
327 if (FLAGS_bbh.count() != 3) {
328 error.printf("--bbh grid requires a width and a height.\n");
329 return NULL;
330 }
331 int gridWidth = atoi(FLAGS_bbh[1]);
332 int gridHeight = atoi(FLAGS_bbh[2]);
333 renderer->setGridSize(gridWidth, gridHeight);
334
335 } else {
336 error.printf("%s is not a valid value for --bbhType\n", type);
337 return NULL;
338 }
339 if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
340 error.printf("--pipe and --bbh cannot be used together\n");
341 return NULL;
342 }
343 }
344 renderer->setBBoxHierarchyType(bbhType);
345 renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale));
346
347 return renderer.detach();
348}