blob: ea316843a9429c590902d189df8a5e665a57343d [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"
bsalomon682c2692015-05-22 14:01:46 -070011#if SK_SUPPORT_GPU
12#include "GrContextOptions.h"
13#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +000014#include "PictureRenderer.h"
15#include "picture_utils.h"
scroggo@google.comd9ba9a02013-03-21 19:43:15 +000016#include "SkCommandLineFlags.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000017#include "SkData.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000018#include "SkImage.h"
19#include "SkImageDecoder.h"
scroggo@google.combb281f72013-03-18 21:37:39 +000020#include "SkString.h"
scroggo@google.com161e1ba2013-03-04 16:41:06 +000021
bungeman60e0fee2015-08-26 05:15:46 -070022#include <stdlib.h>
23
scroggo@google.com161e1ba2013-03-04 16:41:06 +000024// Alphabetized list of flags used by this file or bench_ and render_pictures.
25DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarchy type to "
mtklein2a65a232014-08-26 14:07:04 -070026 "be used. Accepted values are: none, rtree, grid. "
scroggo@google.com161e1ba2013-03-04 16:41:06 +000027 "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.");
robertphillips@google.com11e10e32014-01-06 19:09:29 +000031
32
33#if SK_SUPPORT_GPU
kkinnunen80549fc2014-06-30 06:36:31 -070034static const char kGpuAPINameGL[] = "gl";
35static const char kGpuAPINameGLES[] = "gles";
jvanverth4736e142014-11-07 07:12:46 -080036#define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16|gpudft"
robertphillips@google.com11e10e32014-01-06 19:09:29 +000037#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
hendrikw885bf092015-08-27 10:38:39 -070045#if SK_COMMAND_BUFFER
46#define COMMAND_BUFFER_CONFIG_STRING "|commandbuffer"
47#else
48#define COMMAND_BUFFER_CONFIG_STRING ""
49#endif
robertphillips@google.com11e10e32014-01-06 19:09:29 +000050#if SK_MESA
51#define MESA_CONFIG_STRING "|mesa"
52#else
53#define MESA_CONFIG_STRING ""
54#endif
55
scroggo@google.com161e1ba2013-03-04 16:41:06 +000056// Although this config does not support all the same options as gm, the names should be kept
57// consistent.
rmistry@google.com6ab96732014-01-06 18:37:24 +000058DEFINE_string(config, "8888", "["
hendrikw885bf092015-08-27 10:38:39 -070059 "8888" GPU_CONFIG_STRING ANGLE_CONFIG_STRING COMMAND_BUFFER_CONFIG_STRING MESA_CONFIG_STRING
rmistry@google.com6ab96732014-01-06 18:37:24 +000060 "]: Use the corresponding config.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000061
62DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. "
63 "Has no effect if the provided skp does not have its images encoded.");
64DEFINE_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 percentages.\n"
67 "pow2tile minWidth height: Use tiles with widths that are all a power\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 avoid\n"
72 "\tcreating a large canvas.\n"
73// TODO: If bench_pictures and render_pictures were two separate targets, we could 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 skp,\n"
80 "\twith the bitmaps PNG encoded.\n");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000081DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\".");
scroggo@google.com604e0c22013-04-09 21:25:46 +000082DEFINE_string2(readPath, r, "", "skp files or directories of skp files to process.");
scroggo@google.com161e1ba2013-03-04 16:41:06 +000083DEFINE_double(scale, 1, "Set the scale factor.");
84DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile "
85 "in the x and y directions.");
86DEFINE_string(viewport, "", "width height: Set the viewport.");
kkinnunen80549fc2014-06-30 06:36:31 -070087#if SK_SUPPORT_GPU
88DEFINE_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.");
krajcevskib1aded82014-08-18 07:52:17 -070092DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
93 "software path rendering.");
kkinnunen80549fc2014-06-30 06:36:31 -070094#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +000095
96sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
97 error.reset();
98
scroggo@google.com161e1ba2013-03-04 16:41:06 +000099 bool useTiles = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700100 const char* widthString = nullptr;
101 const char* heightString = nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000102 bool isPowerOf2Mode = false;
103 bool isCopyMode = false;
halcanary96fcdcc2015-08-27 07:41:13 -0700104 const char* mode = nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000105
krajcevskib1aded82014-08-18 07:52:17 -0700106#if SK_SUPPORT_GPU
bsalomon682c2692015-05-22 14:01:46 -0700107 GrContextOptions grContextOpts;
krajcevskib1aded82014-08-18 07:52:17 -0700108 grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
109 #define RENDERER_ARGS (grContextOpts)
110#else
111 #define RENDERER_ARGS ()
112#endif
113
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000114 SkAutoTUnref<sk_tools::PictureRenderer> renderer;
115 if (FLAGS_mode.count() >= 1) {
116 mode = FLAGS_mode[0];
117 if (0 == strcmp(mode, "record")) {
halcanary385fe4d2015-08-26 13:07:48 -0700118 renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000119 } 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;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000127 }
128
129 if (FLAGS_mode.count() < 2) {
130 error.printf("Missing width for --mode %s\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700131 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000132 }
133
134 widthString = FLAGS_mode[1];
135 if (FLAGS_mode.count() < 3) {
136 error.printf("Missing height for --mode %s\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700137 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000138 }
139
140 heightString = FLAGS_mode[2];
141 } else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
halcanary385fe4d2015-08-26 13:07:48 -0700142 renderer.reset(new sk_tools::PlaybackCreationRenderer RENDERER_ARGS);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000143 // undocumented
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000144 } else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
halcanary385fe4d2015-08-26 13:07:48 -0700145 renderer.reset(new sk_tools::RecordPictureRenderer RENDERER_ARGS);
mtklein963b8322015-01-13 10:51:36 -0800146 } 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 renderer will
149 // be created below.
commit-bot@chromium.org5fb2ce32014-04-17 23:35:06 +0000150 } else {
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000151 error.printf("%s is not a valid mode for --mode\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700152 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000153 }
154 }
155
156 if (useTiles) {
halcanary96fcdcc2015-08-27 07:41:13 -0700157 SkASSERT(nullptr == renderer);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000158 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");
halcanary96fcdcc2015-08-27 07:41:13 -0700165 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000166 }
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");
halcanary96fcdcc2015-08-27 07:41:13 -0700177 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000178 }
179 } else {
180 x = y = 4;
181 }
krajcevskib1aded82014-08-18 07:52:17 -0700182#if SK_SUPPORT_GPU
halcanary385fe4d2015-08-26 13:07:48 -0700183 tiledRenderer.reset(new sk_tools::CopyTilesRenderer(grContextOpts, x, y));
krajcevskib1aded82014-08-18 07:52:17 -0700184#else
halcanary385fe4d2015-08-26 13:07:48 -0700185 tiledRenderer.reset(new sk_tools::CopyTilesRenderer(x, y));
krajcevskib1aded82014-08-18 07:52:17 -0700186#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000187 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700188 tiledRenderer.reset(new sk_tools::TiledPictureRenderer RENDERER_ARGS);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000189 }
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);
halcanary96fcdcc2015-08-27 07:41:13 -0700197 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000198 }
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);
halcanary96fcdcc2015-08-27 07:41:13 -0700203 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000204 }
205 tiledRenderer->setTileWidthPercentage(atof(widthString));
206 if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
207 error.printf("--mode %s must be given a width percentage > 0\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700208 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000209 }
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);
halcanary96fcdcc2015-08-27 07:41:13 -0700214 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000215 }
216 }
217
218 if (sk_tools::is_percentage(heightString)) {
219 if (isCopyMode) {
220 error.printf("--mode %s does not support percentages.\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700221 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000222 }
223 tiledRenderer->setTileHeightPercentage(atof(heightString));
224 if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
225 error.printf("--mode %s must be given a height percentage > 0\n", mode);
halcanary96fcdcc2015-08-27 07:41:13 -0700226 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000227 }
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);
halcanary96fcdcc2015-08-27 07:41:13 -0700233 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000234 }
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
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000244 if (FLAGS_pipe) {
halcanary96fcdcc2015-08-27 07:41:13 -0700245 if (renderer != nullptr) {
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000246 error.printf("Pipe is incompatible with other modes.\n");
halcanary96fcdcc2015-08-27 07:41:13 -0700247 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000248 }
halcanary385fe4d2015-08-26 13:07:48 -0700249 renderer.reset(new sk_tools::PipePictureRenderer RENDERER_ARGS);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000250 }
251 }
252
halcanary96fcdcc2015-08-27 07:41:13 -0700253 if (nullptr == renderer) {
halcanary385fe4d2015-08-26 13:07:48 -0700254 renderer.reset(new sk_tools::SimplePictureRenderer RENDERER_ARGS);
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000255 }
256
257 if (FLAGS_viewport.count() > 0) {
258 if (FLAGS_viewport.count() != 2) {
259 error.printf("--viewport requires a width and a height.\n");
halcanary96fcdcc2015-08-27 07:41:13 -0700260 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000261 }
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;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000270#if SK_SUPPORT_GPU
kkinnunen80549fc2014-06-30 06:36:31 -0700271 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");
halcanary96fcdcc2015-08-27 07:41:13 -0700279 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700280 }
281 } else if (FLAGS_gpuAPI.count() > 1) {
282 error.printf("--gpuAPI invalid api value.\n");
halcanary96fcdcc2015-08-27 07:41:13 -0700283 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700284 }
285
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000286 int sampleCount = 0;
jvanverth4736e142014-11-07 07:12:46 -0800287 bool useDFText = false;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000288#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000289 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;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000296 }
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000297 else if (0 == strcmp(FLAGS_config[0], "msaa4")) {
298 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000299 sampleCount = 4;
300 }
301 else if (0 == strcmp(FLAGS_config[0], "msaa16")) {
302 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000303 sampleCount = 16;
304 }
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +0000305 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa4")) {
306 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +0000307 sampleCount = 4;
308 }
309 else if (0 == strcmp(FLAGS_config[0], "nvprmsaa16")) {
310 deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
commit-bot@chromium.org0fd52702014-03-07 18:41:14 +0000311 sampleCount = 16;
312 }
jvanverth4736e142014-11-07 07:12:46 -0800313 else if (0 == strcmp(FLAGS_config[0], "gpudft")) {
314 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
315 useDFText = true;
316 }
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000317#if SK_ANGLE
318 else if (0 == strcmp(FLAGS_config[0], "angle")) {
319 deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000320 }
321#endif
hendrikw885bf092015-08-27 10:38:39 -0700322#if SK_COMMAND_BUFFER
323 else if (0 == strcmp(FLAGS_config[0], "commandbuffer")) {
324 deviceType = sk_tools::PictureRenderer::kCommandBuffer_DeviceType;
325 }
326#endif
rmistry@google.com6ab96732014-01-06 18:37:24 +0000327#if SK_MESA
328 else if (0 == strcmp(FLAGS_config[0], "mesa")) {
329 deviceType = sk_tools::PictureRenderer::kMesa_DeviceType;
rmistry@google.com6ab96732014-01-06 18:37:24 +0000330 }
331#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000332#endif
333 else {
334 error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]);
halcanary96fcdcc2015-08-27 07:41:13 -0700335 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000336 }
kkinnunen80549fc2014-06-30 06:36:31 -0700337#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_config[0]);
halcanary96fcdcc2015-08-27 07:41:13 -0700343 return nullptr;
kkinnunen80549fc2014-06-30 06:36:31 -0700344 }
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000345#if SK_SUPPORT_GPU
346 renderer->setSampleCount(sampleCount);
jvanverth4736e142014-11-07 07:12:46 -0800347 renderer->setUseDFText(useDFText);
jvanverth@google.comf6a90332013-05-02 12:39:37 +0000348#endif
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000349 }
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;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000360 } else {
361 error.printf("%s is not a valid value for --bbhType\n", type);
halcanary96fcdcc2015-08-27 07:41:13 -0700362 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000363 }
364 if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
365 error.printf("--pipe and --bbh cannot be used together\n");
halcanary96fcdcc2015-08-27 07:41:13 -0700366 return nullptr;
scroggo@google.com161e1ba2013-03-04 16:41:06 +0000367 }
368 }
369 renderer->setBBoxHierarchyType(bbhType);
370 renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale));
371
372 return renderer.detach();
373}