blob: 5acec267b075e8e71c84ea7e766c2ba5366c3172 [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 "
commit-bot@chromium.orgc22d1392014-02-03 18:08:33 +000021 "be used. Accepted values are: none, rtree, quadtree, grid. "
scroggo@google.com161e1ba2013-03-04 16:41:06 +000022 "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.");
robertphillips@google.com11e10e32014-01-06 19:09:29 +000026
27
28#if SK_SUPPORT_GPU
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +000029#define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16"
robertphillips@google.com11e10e32014-01-06 19:09:29 +000030#else
31#define GPU_CONFIG_STRING ""
32#endif
33#if SK_ANGLE
34#define ANGLE_CONFIG_STRING "|angle"
35#else
36#define ANGLE_CONFIG_STRING ""
37#endif
38#if SK_MESA
39#define MESA_CONFIG_STRING "|mesa"
40#else
41#define MESA_CONFIG_STRING ""
42#endif
43
scroggo@google.com161e1ba2013-03-04 16:41:06 +000044// Although this config does not support all the same options as gm, the names should be kept
45// consistent.
rmistry@google.com6ab96732014-01-06 18:37:24 +000046DEFINE_string(config, "8888", "["
robertphillips@google.com11e10e32014-01-06 19:09:29 +000047 "8888" GPU_CONFIG_STRING ANGLE_CONFIG_STRING MESA_CONFIG_STRING
rmistry@google.com6ab96732014-01-06 18:37:24 +000048 "]: Use the corresponding config.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000049
50DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. "
51 "Has no effect if the provided skp does not have its images encoded.");
52DEFINE_string(mode, "simple", "Run in the corresponding mode:\n"
53 "simple: Simple rendering.\n"
54 "tile width height: Use tiles with the given dimensions or percentages.\n"
55 "pow2tile minWidth height: Use tiles with widths that are all a power\n"
56 "\tof two such that they minimize the amount of wasted tile space.\n"
57 "\tminWidth must be a power of two.\n"
58 "copyTile width height: Draw the picture, then copy into tiles. If the\n"
59 "\tpicture is large enough, it is broken into larger tiles to avoid\n"
60 "\tcreating a large canvas.\n"
61// TODO: If bench_pictures and render_pictures were two separate targets, we could use build flags
62// to determine which modes to display.
63 "record: (Only in bench_pictures) Time recording from a picture to a new\n"
64 "\tpicture.\n"
65 "playbackCreation: (Only in bench_pictures) Time creation of the \n"
66 "\tSkPicturePlayback.\n"
67 "rerecord: (Only in render_pictures) Record the picture as a new skp,\n"
68 "\twith the bitmaps PNG encoded.\n");
69DEFINE_int32(multi, 1, "Set the number of threads for multi threaded drawing. "
70 "If > 1, requires tiled rendering.");
71DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\".");
scroggo@google.com604e0c22013-04-09 21:25:46 +000072DEFINE_string2(readPath, r, "", "skp files or directories of skp files to process.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000073DEFINE_double(scale, 1, "Set the scale factor.");
74DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile "
75 "in the x and y directions.");
76DEFINE_string(viewport, "", "width height: Set the viewport.");
77
78sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
79 error.reset();
80
81 if (FLAGS_multi <= 0) {
82 error.printf("--multi must be > 0, was %i", FLAGS_multi);
83 return NULL;
84 }
85
86 bool useTiles = false;
87 const char* widthString = NULL;
88 const char* heightString = NULL;
89 bool isPowerOf2Mode = false;
90 bool isCopyMode = false;
91 const char* mode = NULL;
92 bool gridSupported = false;
93
94 SkAutoTUnref<sk_tools::PictureRenderer> renderer;
95 if (FLAGS_mode.count() >= 1) {
96 mode = FLAGS_mode[0];
97 if (0 == strcmp(mode, "record")) {
98 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
99 gridSupported = true;
100 // undocumented
101 } else if (0 == strcmp(mode, "clone")) {
102 renderer.reset(sk_tools::CreatePictureCloneRenderer());
103 } else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile")
104 || 0 == strcmp(mode, "copyTile")) {
105 useTiles = true;
106
107 if (0 == strcmp(mode, "pow2tile")) {
108 isPowerOf2Mode = true;
109 } else if (0 == strcmp(mode, "copyTile")) {
110 isCopyMode = true;
111 } else {
112 gridSupported = true;
113 }
114
115 if (FLAGS_mode.count() < 2) {
116 error.printf("Missing width for --mode %s\n", mode);
117 return NULL;
118 }
119
120 widthString = FLAGS_mode[1];
121 if (FLAGS_mode.count() < 3) {
122 error.printf("Missing height for --mode %s\n", mode);
123 return NULL;
124 }
125
126 heightString = FLAGS_mode[2];
127 } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
128 renderer.reset(SkNEW(sk_tools::PlaybackCreationRenderer));
129 gridSupported = true;
130 // undocumented
131 } else if (0 == strcmp(mode, "gatherPixelRefs") && kBench_PictureTool == tool) {
132 renderer.reset(sk_tools::CreateGatherPixelRefsRenderer());
133 } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
134 renderer.reset(SkNEW(sk_tools::RecordPictureRenderer));
135 // Allow 'mode' to be set to 'simple', but do not create a renderer, so we can
136 // ensure that pipe does not override a mode besides simple. The renderer will
137 // be created below.
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000138 } else if (0 == strcmp(mode, "simple")) {
139 gridSupported = true;
140 } else {
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000141 error.printf("%s is not a valid mode for --mode\n", mode);
142 return NULL;
143 }
144 }
145
146 if (useTiles) {
147 SkASSERT(NULL == renderer);
148 SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer;
149 if (isCopyMode) {
150 int xTiles = -1;
151 int yTiles = -1;
152 if (FLAGS_tiles.count() > 0) {
153 if (FLAGS_tiles.count() != 2) {
154 error.printf("--tiles requires an x value and a y value.\n");
155 return NULL;
156 }
157 xTiles = atoi(FLAGS_tiles[0]);
158 yTiles = atoi(FLAGS_tiles[1]);
159 }
160
161 int x, y;
162 if (xTiles != -1 && yTiles != -1) {
163 x = xTiles;
164 y = yTiles;
165 if (x <= 0 || y <= 0) {
166 error.printf("--tiles must be given values > 0\n");
167 return NULL;
168 }
169 } else {
170 x = y = 4;
171 }
172 tiledRenderer.reset(SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)));
173 } else if (FLAGS_multi > 1) {
174 tiledRenderer.reset(SkNEW_ARGS(sk_tools::MultiCorePictureRenderer,
175 (FLAGS_multi)));
176 } else {
177 tiledRenderer.reset(SkNEW(sk_tools::TiledPictureRenderer));
178 }
179
180 if (isPowerOf2Mode) {
181 int minWidth = atoi(widthString);
182 if (!SkIsPow2(minWidth) || minWidth < 0) {
183 SkString err;
184 error.printf("-mode %s must be given a width"
185 " value that is a power of two\n", mode);
186 return NULL;
187 }
188 tiledRenderer->setTileMinPowerOf2Width(minWidth);
189 } else if (sk_tools::is_percentage(widthString)) {
190 if (isCopyMode) {
191 error.printf("--mode %s does not support percentages.\n", mode);
192 return NULL;
193 }
194 tiledRenderer->setTileWidthPercentage(atof(widthString));
195 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
196 error.printf("--mode %s must be given a width percentage > 0\n", mode);
197 return NULL;
198 }
199 } else {
200 tiledRenderer->setTileWidth(atoi(widthString));
201 if (!(tiledRenderer->getTileWidth() > 0)) {
202 error.printf("--mode %s must be given a width > 0\n", mode);
203 return NULL;
204 }
205 }
206
207 if (sk_tools::is_percentage(heightString)) {
208 if (isCopyMode) {
209 error.printf("--mode %s does not support percentages.\n", mode);
210 return NULL;
211 }
212 tiledRenderer->setTileHeightPercentage(atof(heightString));
213 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
214 error.printf("--mode %s must be given a height percentage > 0\n", mode);
215 return NULL;
216 }
217 } else {
218 tiledRenderer->setTileHeight(atoi(heightString));
219 if (!(tiledRenderer->getTileHeight() > 0)) {
220 SkString err;
221 error.printf("--mode %s must be given a height > 0\n", mode);
222 return NULL;
223 }
224 }
225
226 renderer.reset(tiledRenderer.detach());
227 if (FLAGS_pipe) {
228 error.printf("Pipe rendering is currently not compatible with tiling.\n"
229 "Turning off pipe.\n");
230 }
231
232 } else { // useTiles
233 if (FLAGS_multi > 1) {
234 error.printf("Multithreaded drawing requires tiled rendering.\n");
235 return NULL;
236 }
237 if (FLAGS_pipe) {
238 if (renderer != NULL) {
239 error.printf("Pipe is incompatible with other modes.\n");
240 return NULL;
241 }
242 renderer.reset(SkNEW(sk_tools::PipePictureRenderer));
243 }
244 }
245
246 if (NULL == renderer) {
247 renderer.reset(SkNEW(sk_tools::SimplePictureRenderer));
248 }
249
250 if (FLAGS_viewport.count() > 0) {
251 if (FLAGS_viewport.count() != 2) {
252 error.printf("--viewport requires a width and a height.\n");
253 return NULL;
254 }
255 SkISize viewport;
256 viewport.fWidth = atoi(FLAGS_viewport[0]);
257 viewport.fHeight = atoi(FLAGS_viewport[1]);
258 renderer->setViewport(viewport);
259 }
260
261 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
262 sk_tools::PictureRenderer::kBitmap_DeviceType;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000263#if SK_SUPPORT_GPU
264 int sampleCount = 0;
265#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000266 if (FLAGS_config.count() > 0) {
267 if (0 == strcmp(FLAGS_config[0], "8888")) {
268 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
269 }
270#if SK_SUPPORT_GPU
271 else if (0 == strcmp(FLAGS_config[0], "gpu")) {
272 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
273 if (FLAGS_multi > 1) {
274 error.printf("GPU not compatible with multithreaded tiling.\n");
275 return NULL;
276 }
277 }
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000278 else if (0 == strcmp(FLAGS_config[0], "msaa4")) {
279 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
280 if (FLAGS_multi > 1) {
281 error.printf("GPU not compatible with multithreaded tiling.\n");
282 return NULL;
283 }
284 sampleCount = 4;
285 }
286 else if (0 == strcmp(FLAGS_config[0], "msaa16")) {
287 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
288 if (FLAGS_multi > 1) {
289 error.printf("GPU not compatible with multithreaded tiling.\n");
290 return NULL;
291 }
292 sampleCount = 16;
293 }
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +0000294 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa4")) {
295 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
296 if (FLAGS_multi > 1) {
297 error.printf("GPU not compatible with multithreaded tiling.\n");
298 return NULL;
299 }
300 sampleCount = 4;
301 }
302 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa16")) {
303 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
304 if (FLAGS_multi > 1) {
305 error.printf("GPU not compatible with multithreaded tiling.\n");
306 return NULL;
307 }
308 sampleCount = 16;
309 }
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000310#if SK_ANGLE
311 else if (0 == strcmp(FLAGS_config[0], "angle")) {
312 deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
313 if (FLAGS_multi > 1) {
314 error.printf("Angle not compatible with multithreaded tiling.\n");
315 return NULL;
316 }
317 }
318#endif
rmistry@google.com6ab96732014-01-06 18:37:24 +0000319#if SK_MESA
320 else if (0 == strcmp(FLAGS_config[0], "mesa")) {
321 deviceType = sk_tools::PictureRenderer::kMesa_DeviceType;
322 if (FLAGS_multi > 1) {
323 error.printf("Mesa not compatible with multithreaded tiling.\n");
324 return NULL;
325 }
326 }
327#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000328#endif
329 else {
330 error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]);
331 return NULL;
332 }
333 renderer->setDeviceType(deviceType);
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000334#if SK_SUPPORT_GPU
335 renderer->setSampleCount(sampleCount);
336#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000337 }
338
339
340 sk_tools::PictureRenderer::BBoxHierarchyType bbhType
341 = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
342 if (FLAGS_bbh.count() > 0) {
343 const char* type = FLAGS_bbh[0];
344 if (0 == strcmp(type, "none")) {
345 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
commit-bot@chromium.orgc22d1392014-02-03 18:08:33 +0000346 } else if (0 == strcmp(type, "quadtree")) {
347 bbhType = sk_tools::PictureRenderer::kQuadTree_BBoxHierarchyType;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000348 } else if (0 == strcmp(type, "rtree")) {
349 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
350 } else if (0 == strcmp(type, "grid")) {
351 if (!gridSupported) {
352 error.printf("'--bbh grid' is not compatible with --mode=%s.\n", mode);
353 return NULL;
354 }
355 bbhType = sk_tools::PictureRenderer::kTileGrid_BBoxHierarchyType;
356 if (FLAGS_bbh.count() != 3) {
357 error.printf("--bbh grid requires a width and a height.\n");
358 return NULL;
359 }
360 int gridWidth = atoi(FLAGS_bbh[1]);
361 int gridHeight = atoi(FLAGS_bbh[2]);
362 renderer->setGridSize(gridWidth, gridHeight);
363
364 } else {
365 error.printf("%s is not a valid value for --bbhType\n", type);
366 return NULL;
367 }
368 if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
369 error.printf("--pipe and --bbh cannot be used together\n");
370 return NULL;
371 }
372 }
373 renderer->setBBoxHierarchyType(bbhType);
374 renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale));
375
376 return renderer.detach();
377}