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