OLD | NEW |
| (Empty) |
1 /* | |
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 #if SK_SUPPORT_GPU | |
12 #include "GrContextOptions.h" | |
13 #endif | |
14 #include "PictureRenderer.h" | |
15 #include "picture_utils.h" | |
16 #include "SkCommandLineFlags.h" | |
17 #include "SkData.h" | |
18 #include "SkImage.h" | |
19 #include "SkImageDecoder.h" | |
20 #include "SkString.h" | |
21 | |
22 #include <stdlib.h> | |
23 | |
24 // Alphabetized list of flags used by this file or bench_ and render_pictures. | |
25 DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarc
hy type to " | |
26 "be used. Accepted values are: none, rtree, grid. " | |
27 "Not compatible with --pipe. With value " | |
28 "'grid', width and height must be specified. 'grid' can " | |
29 "only be used with modes tile, record, and " | |
30 "playbackCreation."); | |
31 | |
32 | |
33 #if SK_SUPPORT_GPU | |
34 static const char kGpuAPINameGL[] = "gl"; | |
35 static const char kGpuAPINameGLES[] = "gles"; | |
36 #define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16|gpudft" | |
37 #else | |
38 #define GPU_CONFIG_STRING "" | |
39 #endif | |
40 #if SK_ANGLE | |
41 #define ANGLE_CONFIG_STRING "|angle" | |
42 #else | |
43 #define ANGLE_CONFIG_STRING "" | |
44 #endif | |
45 #if SK_COMMAND_BUFFER | |
46 #define COMMAND_BUFFER_CONFIG_STRING "|commandbuffer" | |
47 #else | |
48 #define COMMAND_BUFFER_CONFIG_STRING "" | |
49 #endif | |
50 #if SK_MESA | |
51 #define MESA_CONFIG_STRING "|mesa" | |
52 #else | |
53 #define MESA_CONFIG_STRING "" | |
54 #endif | |
55 | |
56 // Although this config does not support all the same options as gm, the names s
hould be kept | |
57 // consistent. | |
58 DEFINE_string(config, "8888", "[" | |
59 "8888" GPU_CONFIG_STRING ANGLE_CONFIG_STRING COMMAND_BUFFER_CONFIG
_STRING MESA_CONFIG_STRING | |
60 "]: Use the corresponding config."); | |
61 | |
62 DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. " | |
63 "Has no effect if the provided skp does not have its images encoded.
"); | |
64 DEFINE_string(mode, "simple", "Run in the corresponding mode:\n" | |
65 "simple: Simple rendering.\n" | |
66 "tile width height: Use tiles with the given dimensions or percent
ages.\n" | |
67 "pow2tile minWidth height: Use tiles with widths that are all a po
wer\n" | |
68 "\tof two such that they minimize the amount of wasted tile space.
\n" | |
69 "\tminWidth must be a power of two.\n" | |
70 "copyTile width height: Draw the picture, then copy into tiles. If
the\n" | |
71 "\tpicture is large enough, it is broken into larger tiles to avoi
d\n" | |
72 "\tcreating a large canvas.\n" | |
73 // TODO: If bench_pictures and render_pictures were two separate targets, we cou
ld use build flags | |
74 // to determine which modes to display. | |
75 "record: (Only in bench_pictures) Time recording from a picture to
a new\n" | |
76 "\tpicture.\n" | |
77 "playbackCreation: (Only in bench_pictures) Time creation of the \
n" | |
78 "\tSkPicturePlayback.\n" | |
79 "rerecord: (Only in render_pictures) Record the picture as a new s
kp,\n" | |
80 "\twith the bitmaps PNG encoded.\n"); | |
81 DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"m
ode\"."); | |
82 DEFINE_string2(readPath, r, "", "skp files or directories of skp files to proces
s."); | |
83 DEFINE_double(scale, 1, "Set the scale factor."); | |
84 DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles p
er larger tile " | |
85 "in the x and y directions."); | |
86 DEFINE_string(viewport, "", "width height: Set the viewport."); | |
87 #if SK_SUPPORT_GPU | |
88 DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " | |
89 "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " | |
90 "Defaults to empty string, which selects the API native to the " | |
91 "system."); | |
92 DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling
back to " | |
93 "software path rendering."); | |
94 #endif | |
95 | |
96 sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) { | |
97 error.reset(); | |
98 | |
99 bool useTiles = false; | |
100 const char* widthString = nullptr; | |
101 const char* heightString = nullptr; | |
102 bool isPowerOf2Mode = false; | |
103 bool isCopyMode = false; | |
104 const char* mode = nullptr; | |
105 | |
106 #if SK_SUPPORT_GPU | |
107 GrContextOptions grContextOpts; | |
108 grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks; | |
109 #define RENDERER_ARGS (grContextOpts) | |
110 #else | |
111 #define RENDERER_ARGS () | |
112 #endif | |
113 | |
114 SkAutoTUnref<sk_tools::PictureRenderer> renderer; | |
115 if (FLAGS_mode.count() >= 1) { | |
116 mode = FLAGS_mode[0]; | |
117 if (0 == strcmp(mode, "record")) { | |
118 renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS); | |
119 } else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile") | |
120 || 0 == strcmp(mode, "copyTile")) { | |
121 useTiles = true; | |
122 | |
123 if (0 == strcmp(mode, "pow2tile")) { | |
124 isPowerOf2Mode = true; | |
125 } else if (0 == strcmp(mode, "copyTile")) { | |
126 isCopyMode = true; | |
127 } | |
128 | |
129 if (FLAGS_mode.count() < 2) { | |
130 error.printf("Missing width for --mode %s\n", mode); | |
131 return nullptr; | |
132 } | |
133 | |
134 widthString = FLAGS_mode[1]; | |
135 if (FLAGS_mode.count() < 3) { | |
136 error.printf("Missing height for --mode %s\n", mode); | |
137 return nullptr; | |
138 } | |
139 | |
140 heightString = FLAGS_mode[2]; | |
141 } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool =
= tool) { | |
142 renderer.reset(new sk_tools::PlaybackCreationRenderer RENDERER_ARGS)
; | |
143 // undocumented | |
144 } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool)
{ | |
145 renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS); | |
146 } else if (0 == strcmp(mode, "simple")) { | |
147 // Allow 'mode' to be set to 'simple', but do not create a renderer,
so we can | |
148 // ensure that pipe does not override a mode besides simple. The ren
derer will | |
149 // be created below. | |
150 } else { | |
151 error.printf("%s is not a valid mode for --mode\n", mode); | |
152 return nullptr; | |
153 } | |
154 } | |
155 | |
156 if (useTiles) { | |
157 SkASSERT(nullptr == renderer); | |
158 SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer; | |
159 if (isCopyMode) { | |
160 int xTiles = -1; | |
161 int yTiles = -1; | |
162 if (FLAGS_tiles.count() > 0) { | |
163 if (FLAGS_tiles.count() != 2) { | |
164 error.printf("--tiles requires an x value and a y value.\n")
; | |
165 return nullptr; | |
166 } | |
167 xTiles = atoi(FLAGS_tiles[0]); | |
168 yTiles = atoi(FLAGS_tiles[1]); | |
169 } | |
170 | |
171 int x, y; | |
172 if (xTiles != -1 && yTiles != -1) { | |
173 x = xTiles; | |
174 y = yTiles; | |
175 if (x <= 0 || y <= 0) { | |
176 error.printf("--tiles must be given values > 0\n"); | |
177 return nullptr; | |
178 } | |
179 } else { | |
180 x = y = 4; | |
181 } | |
182 #if SK_SUPPORT_GPU | |
183 tiledRenderer.reset(new sk_tools::CopyTilesRenderer(grContextOpts, x
, y)); | |
184 #else | |
185 tiledRenderer.reset(new sk_tools::CopyTilesRenderer(x, y)); | |
186 #endif | |
187 } else { | |
188 tiledRenderer.reset(new sk_tools::TiledPictureRenderer RENDERER_ARGS
); | |
189 } | |
190 | |
191 if (isPowerOf2Mode) { | |
192 int minWidth = atoi(widthString); | |
193 if (!SkIsPow2(minWidth) || minWidth < 0) { | |
194 SkString err; | |
195 error.printf("-mode %s must be given a width" | |
196 " value that is a power of two\n", mode); | |
197 return nullptr; | |
198 } | |
199 tiledRenderer->setTileMinPowerOf2Width(minWidth); | |
200 } else if (sk_tools::is_percentage(widthString)) { | |
201 if (isCopyMode) { | |
202 error.printf("--mode %s does not support percentages.\n", mode); | |
203 return nullptr; | |
204 } | |
205 tiledRenderer->setTileWidthPercentage(atof(widthString)); | |
206 if (!(tiledRenderer->getTileWidthPercentage() > 0)) { | |
207 error.printf("--mode %s must be given a width percentage > 0\n",
mode); | |
208 return nullptr; | |
209 } | |
210 } else { | |
211 tiledRenderer->setTileWidth(atoi(widthString)); | |
212 if (!(tiledRenderer->getTileWidth() > 0)) { | |
213 error.printf("--mode %s must be given a width > 0\n", mode); | |
214 return nullptr; | |
215 } | |
216 } | |
217 | |
218 if (sk_tools::is_percentage(heightString)) { | |
219 if (isCopyMode) { | |
220 error.printf("--mode %s does not support percentages.\n", mode); | |
221 return nullptr; | |
222 } | |
223 tiledRenderer->setTileHeightPercentage(atof(heightString)); | |
224 if (!(tiledRenderer->getTileHeightPercentage() > 0)) { | |
225 error.printf("--mode %s must be given a height percentage > 0\n"
, mode); | |
226 return nullptr; | |
227 } | |
228 } else { | |
229 tiledRenderer->setTileHeight(atoi(heightString)); | |
230 if (!(tiledRenderer->getTileHeight() > 0)) { | |
231 SkString err; | |
232 error.printf("--mode %s must be given a height > 0\n", mode); | |
233 return nullptr; | |
234 } | |
235 } | |
236 | |
237 renderer.reset(tiledRenderer.detach()); | |
238 if (FLAGS_pipe) { | |
239 error.printf("Pipe rendering is currently not compatible with tiling
.\n" | |
240 "Turning off pipe.\n"); | |
241 } | |
242 | |
243 } else { // useTiles | |
244 if (FLAGS_pipe) { | |
245 if (renderer != nullptr) { | |
246 error.printf("Pipe is incompatible with other modes.\n"); | |
247 return nullptr; | |
248 } | |
249 renderer.reset(new sk_tools::PipePictureRenderer RENDERER_ARGS); | |
250 } | |
251 } | |
252 | |
253 if (nullptr == renderer) { | |
254 renderer.reset(new sk_tools::SimplePictureRenderer RENDERER_ARGS); | |
255 } | |
256 | |
257 if (FLAGS_viewport.count() > 0) { | |
258 if (FLAGS_viewport.count() != 2) { | |
259 error.printf("--viewport requires a width and a height.\n"); | |
260 return nullptr; | |
261 } | |
262 SkISize viewport; | |
263 viewport.fWidth = atoi(FLAGS_viewport[0]); | |
264 viewport.fHeight = atoi(FLAGS_viewport[1]); | |
265 renderer->setViewport(viewport); | |
266 } | |
267 | |
268 sk_tools::PictureRenderer::SkDeviceTypes deviceType = | |
269 sk_tools::PictureRenderer::kBitmap_DeviceType; | |
270 #if SK_SUPPORT_GPU | |
271 GrGLStandard gpuAPI = kNone_GrGLStandard; | |
272 if (1 == FLAGS_gpuAPI.count()) { | |
273 if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { | |
274 gpuAPI = kGL_GrGLStandard; | |
275 } else if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { | |
276 gpuAPI = kGLES_GrGLStandard; | |
277 } else { | |
278 error.printf("--gpuAPI invalid api value.\n"); | |
279 return nullptr; | |
280 } | |
281 } else if (FLAGS_gpuAPI.count() > 1) { | |
282 error.printf("--gpuAPI invalid api value.\n"); | |
283 return nullptr; | |
284 } | |
285 | |
286 int sampleCount = 0; | |
287 bool useDFText = false; | |
288 #endif | |
289 if (FLAGS_config.count() > 0) { | |
290 if (0 == strcmp(FLAGS_config[0], "8888")) { | |
291 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; | |
292 } | |
293 #if SK_SUPPORT_GPU | |
294 else if (0 == strcmp(FLAGS_config[0], "gpu")) { | |
295 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; | |
296 } | |
297 else if (0 == strcmp(FLAGS_config[0], "msaa4")) { | |
298 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; | |
299 sampleCount = 4; | |
300 } | |
301 else if (0 == strcmp(FLAGS_config[0], "msaa16")) { | |
302 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; | |
303 sampleCount = 16; | |
304 } | |
305 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa4")) { | |
306 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType; | |
307 sampleCount = 4; | |
308 } | |
309 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa16")) { | |
310 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType; | |
311 sampleCount = 16; | |
312 } | |
313 else if (0 == strcmp(FLAGS_config[0], "gpudft")) { | |
314 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType; | |
315 useDFText = true; | |
316 } | |
317 #if SK_ANGLE | |
318 else if (0 == strcmp(FLAGS_config[0], "angle")) { | |
319 deviceType = sk_tools::PictureRenderer::kAngle_DeviceType; | |
320 } | |
321 #endif | |
322 #if SK_COMMAND_BUFFER | |
323 else if (0 == strcmp(FLAGS_config[0], "commandbuffer")) { | |
324 deviceType = sk_tools::PictureRenderer::kCommandBuffer_DeviceType; | |
325 } | |
326 #endif | |
327 #if SK_MESA | |
328 else if (0 == strcmp(FLAGS_config[0], "mesa")) { | |
329 deviceType = sk_tools::PictureRenderer::kMesa_DeviceType; | |
330 } | |
331 #endif | |
332 #endif | |
333 else { | |
334 error.printf("%s is not a valid mode for --config\n", FLAGS_config[0
]); | |
335 return nullptr; | |
336 } | |
337 #if SK_SUPPORT_GPU | |
338 if (!renderer->setDeviceType(deviceType, gpuAPI)) { | |
339 #else | |
340 if (!renderer->setDeviceType(deviceType)) { | |
341 #endif | |
342 error.printf("Could not create backend for --config %s\n", FLAGS_con
fig[0]); | |
343 return nullptr; | |
344 } | |
345 #if SK_SUPPORT_GPU | |
346 renderer->setSampleCount(sampleCount); | |
347 renderer->setUseDFText(useDFText); | |
348 #endif | |
349 } | |
350 | |
351 | |
352 sk_tools::PictureRenderer::BBoxHierarchyType bbhType | |
353 = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; | |
354 if (FLAGS_bbh.count() > 0) { | |
355 const char* type = FLAGS_bbh[0]; | |
356 if (0 == strcmp(type, "none")) { | |
357 bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType; | |
358 } else if (0 == strcmp(type, "rtree")) { | |
359 bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType; | |
360 } else { | |
361 error.printf("%s is not a valid value for --bbhType\n", type); | |
362 return nullptr; | |
363 } | |
364 if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType !=
bbhType) { | |
365 error.printf("--pipe and --bbh cannot be used together\n"); | |
366 return nullptr; | |
367 } | |
368 } | |
369 renderer->setBBoxHierarchyType(bbhType); | |
370 renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale)); | |
371 | |
372 return renderer.detach(); | |
373 } | |
OLD | NEW |