2013-03-04 16:41:06 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "PictureRenderingFlags.h"
|
|
|
|
|
|
|
|
#include "CopyTilesRenderer.h"
|
2015-05-22 21:01:46 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
#include "GrContextOptions.h"
|
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
#include "PictureRenderer.h"
|
|
|
|
#include "picture_utils.h"
|
2013-03-21 19:43:15 +00:00
|
|
|
#include "SkCommandLineFlags.h"
|
2013-03-18 21:37:39 +00:00
|
|
|
#include "SkData.h"
|
|
|
|
#include "SkImage.h"
|
|
|
|
#include "SkImageDecoder.h"
|
|
|
|
#include "SkString.h"
|
2013-03-04 16:41:06 +00:00
|
|
|
|
2015-08-26 12:15:46 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2013-03-04 16:41:06 +00:00
|
|
|
// Alphabetized list of flags used by this file or bench_ and render_pictures.
|
|
|
|
DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarchy type to "
|
2014-08-26 21:07:04 +00:00
|
|
|
"be used. Accepted values are: none, rtree, grid. "
|
2013-03-04 16:41:06 +00:00
|
|
|
"Not compatible with --pipe. With value "
|
|
|
|
"'grid', width and height must be specified. 'grid' can "
|
|
|
|
"only be used with modes tile, record, and "
|
|
|
|
"playbackCreation.");
|
2014-01-06 19:09:29 +00:00
|
|
|
|
|
|
|
|
2014-01-06 18:37:24 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-06-30 13:36:31 +00:00
|
|
|
static const char kGpuAPINameGL[] = "gl";
|
|
|
|
static const char kGpuAPINameGLES[] = "gles";
|
2014-11-07 15:12:46 +00:00
|
|
|
#define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16|gpudft"
|
2014-01-06 19:09:29 +00:00
|
|
|
#else
|
|
|
|
#define GPU_CONFIG_STRING ""
|
2014-01-06 18:37:24 +00:00
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
#if SK_ANGLE
|
2014-01-06 19:09:29 +00:00
|
|
|
#define ANGLE_CONFIG_STRING "|angle"
|
|
|
|
#else
|
|
|
|
#define ANGLE_CONFIG_STRING ""
|
2013-03-04 16:41:06 +00:00
|
|
|
#endif
|
2014-01-06 18:37:24 +00:00
|
|
|
#if SK_MESA
|
2014-01-06 19:09:29 +00:00
|
|
|
#define MESA_CONFIG_STRING "|mesa"
|
|
|
|
#else
|
|
|
|
#define MESA_CONFIG_STRING ""
|
2014-01-06 18:37:24 +00:00
|
|
|
#endif
|
2014-01-06 19:09:29 +00:00
|
|
|
|
|
|
|
// Although this config does not support all the same options as gm, the names should be kept
|
|
|
|
// consistent.
|
|
|
|
DEFINE_string(config, "8888", "["
|
|
|
|
"8888" GPU_CONFIG_STRING ANGLE_CONFIG_STRING MESA_CONFIG_STRING
|
2014-01-06 18:37:24 +00:00
|
|
|
"]: Use the corresponding config.");
|
2013-03-04 16:41:06 +00:00
|
|
|
|
|
|
|
DEFINE_bool(deferImageDecoding, false, "Defer decoding until drawing images. "
|
|
|
|
"Has no effect if the provided skp does not have its images encoded.");
|
|
|
|
DEFINE_string(mode, "simple", "Run in the corresponding mode:\n"
|
|
|
|
"simple: Simple rendering.\n"
|
|
|
|
"tile width height: Use tiles with the given dimensions or percentages.\n"
|
|
|
|
"pow2tile minWidth height: Use tiles with widths that are all a power\n"
|
|
|
|
"\tof two such that they minimize the amount of wasted tile space.\n"
|
|
|
|
"\tminWidth must be a power of two.\n"
|
|
|
|
"copyTile width height: Draw the picture, then copy into tiles. If the\n"
|
|
|
|
"\tpicture is large enough, it is broken into larger tiles to avoid\n"
|
|
|
|
"\tcreating a large canvas.\n"
|
|
|
|
// TODO: If bench_pictures and render_pictures were two separate targets, we could use build flags
|
|
|
|
// to determine which modes to display.
|
|
|
|
"record: (Only in bench_pictures) Time recording from a picture to a new\n"
|
|
|
|
"\tpicture.\n"
|
|
|
|
"playbackCreation: (Only in bench_pictures) Time creation of the \n"
|
|
|
|
"\tSkPicturePlayback.\n"
|
|
|
|
"rerecord: (Only in render_pictures) Record the picture as a new skp,\n"
|
|
|
|
"\twith the bitmaps PNG encoded.\n");
|
|
|
|
DEFINE_bool(pipe, false, "Use SkGPipe rendering. Currently incompatible with \"mode\".");
|
2013-04-09 21:25:46 +00:00
|
|
|
DEFINE_string2(readPath, r, "", "skp files or directories of skp files to process.");
|
2013-03-04 16:41:06 +00:00
|
|
|
DEFINE_double(scale, 1, "Set the scale factor.");
|
|
|
|
DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile "
|
|
|
|
"in the x and y directions.");
|
|
|
|
DEFINE_string(viewport, "", "width height: Set the viewport.");
|
2014-06-30 13:36:31 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" "
|
|
|
|
"forces OpenGL API. Using \"gles\" forces OpenGL ES API. "
|
|
|
|
"Defaults to empty string, which selects the API native to the "
|
|
|
|
"system.");
|
2014-08-18 14:52:17 +00:00
|
|
|
DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
|
|
|
|
"software path rendering.");
|
2014-06-30 13:36:31 +00:00
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
|
|
|
|
sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) {
|
|
|
|
error.reset();
|
|
|
|
|
|
|
|
bool useTiles = false;
|
|
|
|
const char* widthString = NULL;
|
|
|
|
const char* heightString = NULL;
|
|
|
|
bool isPowerOf2Mode = false;
|
|
|
|
bool isCopyMode = false;
|
|
|
|
const char* mode = NULL;
|
|
|
|
|
2014-08-18 14:52:17 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2015-05-22 21:01:46 +00:00
|
|
|
GrContextOptions grContextOpts;
|
2014-08-18 14:52:17 +00:00
|
|
|
grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
|
|
|
|
#define RENDERER_ARGS (grContextOpts)
|
|
|
|
#else
|
|
|
|
#define RENDERER_ARGS ()
|
|
|
|
#endif
|
|
|
|
|
2013-03-04 16:41:06 +00:00
|
|
|
SkAutoTUnref<sk_tools::PictureRenderer> renderer;
|
|
|
|
if (FLAGS_mode.count() >= 1) {
|
|
|
|
mode = FLAGS_mode[0];
|
|
|
|
if (0 == strcmp(mode, "record")) {
|
2014-08-18 14:52:17 +00:00
|
|
|
renderer.reset(SkNEW_ARGS(sk_tools::RecordPictureRenderer, RENDERER_ARGS));
|
2013-03-04 16:41:06 +00:00
|
|
|
} else if (0 == strcmp(mode, "tile") || 0 == strcmp(mode, "pow2tile")
|
|
|
|
|| 0 == strcmp(mode, "copyTile")) {
|
|
|
|
useTiles = true;
|
|
|
|
|
|
|
|
if (0 == strcmp(mode, "pow2tile")) {
|
|
|
|
isPowerOf2Mode = true;
|
|
|
|
} else if (0 == strcmp(mode, "copyTile")) {
|
|
|
|
isCopyMode = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FLAGS_mode.count() < 2) {
|
|
|
|
error.printf("Missing width for --mode %s\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
widthString = FLAGS_mode[1];
|
|
|
|
if (FLAGS_mode.count() < 3) {
|
|
|
|
error.printf("Missing height for --mode %s\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
heightString = FLAGS_mode[2];
|
|
|
|
} else if (0 == strcmp(mode, "playbackCreation") && kBench_PictureTool == tool) {
|
2014-08-18 14:52:17 +00:00
|
|
|
renderer.reset(SkNEW_ARGS(sk_tools::PlaybackCreationRenderer, RENDERER_ARGS));
|
2013-03-04 16:41:06 +00:00
|
|
|
// undocumented
|
|
|
|
} else if (0 == strcmp(mode, "rerecord") && kRender_PictureTool == tool) {
|
2014-08-18 14:52:17 +00:00
|
|
|
renderer.reset(SkNEW_ARGS(sk_tools::RecordPictureRenderer, RENDERER_ARGS));
|
2015-01-13 18:51:36 +00:00
|
|
|
} else if (0 == strcmp(mode, "simple")) {
|
|
|
|
// Allow 'mode' to be set to 'simple', but do not create a renderer, so we can
|
|
|
|
// ensure that pipe does not override a mode besides simple. The renderer will
|
|
|
|
// be created below.
|
2014-04-17 23:35:06 +00:00
|
|
|
} else {
|
2013-03-04 16:41:06 +00:00
|
|
|
error.printf("%s is not a valid mode for --mode\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (useTiles) {
|
|
|
|
SkASSERT(NULL == renderer);
|
|
|
|
SkAutoTUnref<sk_tools::TiledPictureRenderer> tiledRenderer;
|
|
|
|
if (isCopyMode) {
|
|
|
|
int xTiles = -1;
|
|
|
|
int yTiles = -1;
|
|
|
|
if (FLAGS_tiles.count() > 0) {
|
|
|
|
if (FLAGS_tiles.count() != 2) {
|
|
|
|
error.printf("--tiles requires an x value and a y value.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
xTiles = atoi(FLAGS_tiles[0]);
|
|
|
|
yTiles = atoi(FLAGS_tiles[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
int x, y;
|
|
|
|
if (xTiles != -1 && yTiles != -1) {
|
|
|
|
x = xTiles;
|
|
|
|
y = yTiles;
|
|
|
|
if (x <= 0 || y <= 0) {
|
|
|
|
error.printf("--tiles must be given values > 0\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
x = y = 4;
|
|
|
|
}
|
2014-08-18 14:52:17 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
tiledRenderer.reset(SkNEW_ARGS(sk_tools::CopyTilesRenderer, (grContextOpts, x, y)));
|
|
|
|
#else
|
2013-03-04 16:41:06 +00:00
|
|
|
tiledRenderer.reset(SkNEW_ARGS(sk_tools::CopyTilesRenderer, (x, y)));
|
2014-08-18 14:52:17 +00:00
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
} else {
|
2014-08-18 14:52:17 +00:00
|
|
|
tiledRenderer.reset(SkNEW_ARGS(sk_tools::TiledPictureRenderer, RENDERER_ARGS));
|
2013-03-04 16:41:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isPowerOf2Mode) {
|
|
|
|
int minWidth = atoi(widthString);
|
|
|
|
if (!SkIsPow2(minWidth) || minWidth < 0) {
|
|
|
|
SkString err;
|
|
|
|
error.printf("-mode %s must be given a width"
|
|
|
|
" value that is a power of two\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tiledRenderer->setTileMinPowerOf2Width(minWidth);
|
|
|
|
} else if (sk_tools::is_percentage(widthString)) {
|
|
|
|
if (isCopyMode) {
|
|
|
|
error.printf("--mode %s does not support percentages.\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tiledRenderer->setTileWidthPercentage(atof(widthString));
|
|
|
|
if (!(tiledRenderer->getTileWidthPercentage() > 0)) {
|
|
|
|
error.printf("--mode %s must be given a width percentage > 0\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tiledRenderer->setTileWidth(atoi(widthString));
|
|
|
|
if (!(tiledRenderer->getTileWidth() > 0)) {
|
|
|
|
error.printf("--mode %s must be given a width > 0\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sk_tools::is_percentage(heightString)) {
|
|
|
|
if (isCopyMode) {
|
|
|
|
error.printf("--mode %s does not support percentages.\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tiledRenderer->setTileHeightPercentage(atof(heightString));
|
|
|
|
if (!(tiledRenderer->getTileHeightPercentage() > 0)) {
|
|
|
|
error.printf("--mode %s must be given a height percentage > 0\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tiledRenderer->setTileHeight(atoi(heightString));
|
|
|
|
if (!(tiledRenderer->getTileHeight() > 0)) {
|
|
|
|
SkString err;
|
|
|
|
error.printf("--mode %s must be given a height > 0\n", mode);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
renderer.reset(tiledRenderer.detach());
|
|
|
|
if (FLAGS_pipe) {
|
|
|
|
error.printf("Pipe rendering is currently not compatible with tiling.\n"
|
|
|
|
"Turning off pipe.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
} else { // useTiles
|
|
|
|
if (FLAGS_pipe) {
|
|
|
|
if (renderer != NULL) {
|
|
|
|
error.printf("Pipe is incompatible with other modes.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-08-18 14:52:17 +00:00
|
|
|
renderer.reset(SkNEW_ARGS(sk_tools::PipePictureRenderer, RENDERER_ARGS));
|
2013-03-04 16:41:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL == renderer) {
|
2014-08-18 14:52:17 +00:00
|
|
|
renderer.reset(SkNEW_ARGS(sk_tools::SimplePictureRenderer, RENDERER_ARGS));
|
2013-03-04 16:41:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (FLAGS_viewport.count() > 0) {
|
|
|
|
if (FLAGS_viewport.count() != 2) {
|
|
|
|
error.printf("--viewport requires a width and a height.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
SkISize viewport;
|
|
|
|
viewport.fWidth = atoi(FLAGS_viewport[0]);
|
|
|
|
viewport.fHeight = atoi(FLAGS_viewport[1]);
|
|
|
|
renderer->setViewport(viewport);
|
|
|
|
}
|
|
|
|
|
|
|
|
sk_tools::PictureRenderer::SkDeviceTypes deviceType =
|
|
|
|
sk_tools::PictureRenderer::kBitmap_DeviceType;
|
2013-05-02 12:39:37 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
2014-06-30 13:36:31 +00:00
|
|
|
GrGLStandard gpuAPI = kNone_GrGLStandard;
|
|
|
|
if (1 == FLAGS_gpuAPI.count()) {
|
|
|
|
if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
|
|
|
|
gpuAPI = kGL_GrGLStandard;
|
|
|
|
} else if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
|
|
|
|
gpuAPI = kGLES_GrGLStandard;
|
|
|
|
} else {
|
|
|
|
error.printf("--gpuAPI invalid api value.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else if (FLAGS_gpuAPI.count() > 1) {
|
|
|
|
error.printf("--gpuAPI invalid api value.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-02 12:39:37 +00:00
|
|
|
int sampleCount = 0;
|
2014-11-07 15:12:46 +00:00
|
|
|
bool useDFText = false;
|
2013-05-02 12:39:37 +00:00
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
if (FLAGS_config.count() > 0) {
|
|
|
|
if (0 == strcmp(FLAGS_config[0], "8888")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
|
|
|
|
}
|
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
else if (0 == strcmp(FLAGS_config[0], "gpu")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
|
|
|
|
}
|
2013-05-02 12:39:37 +00:00
|
|
|
else if (0 == strcmp(FLAGS_config[0], "msaa4")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
|
|
|
|
sampleCount = 4;
|
|
|
|
}
|
|
|
|
else if (0 == strcmp(FLAGS_config[0], "msaa16")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
|
|
|
|
sampleCount = 16;
|
|
|
|
}
|
2014-03-07 18:41:14 +00:00
|
|
|
else if (0 == strcmp(FLAGS_config[0], "nvprmsaa4")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
|
|
|
|
sampleCount = 4;
|
|
|
|
}
|
|
|
|
else if (0 == strcmp(FLAGS_config[0], "nvprmsaa16")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kNVPR_DeviceType;
|
|
|
|
sampleCount = 16;
|
|
|
|
}
|
2014-11-07 15:12:46 +00:00
|
|
|
else if (0 == strcmp(FLAGS_config[0], "gpudft")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
|
|
|
|
useDFText = true;
|
|
|
|
}
|
2013-03-04 16:41:06 +00:00
|
|
|
#if SK_ANGLE
|
|
|
|
else if (0 == strcmp(FLAGS_config[0], "angle")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kAngle_DeviceType;
|
|
|
|
}
|
|
|
|
#endif
|
2014-01-06 18:37:24 +00:00
|
|
|
#if SK_MESA
|
|
|
|
else if (0 == strcmp(FLAGS_config[0], "mesa")) {
|
|
|
|
deviceType = sk_tools::PictureRenderer::kMesa_DeviceType;
|
|
|
|
}
|
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-06-30 13:36:31 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
if (!renderer->setDeviceType(deviceType, gpuAPI)) {
|
|
|
|
#else
|
|
|
|
if (!renderer->setDeviceType(deviceType)) {
|
|
|
|
#endif
|
|
|
|
error.printf("Could not create backend for --config %s\n", FLAGS_config[0]);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-05-02 12:39:37 +00:00
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
renderer->setSampleCount(sampleCount);
|
2014-11-07 15:12:46 +00:00
|
|
|
renderer->setUseDFText(useDFText);
|
2013-05-02 12:39:37 +00:00
|
|
|
#endif
|
2013-03-04 16:41:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sk_tools::PictureRenderer::BBoxHierarchyType bbhType
|
|
|
|
= sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
|
|
|
|
if (FLAGS_bbh.count() > 0) {
|
|
|
|
const char* type = FLAGS_bbh[0];
|
|
|
|
if (0 == strcmp(type, "none")) {
|
|
|
|
bbhType = sk_tools::PictureRenderer::kNone_BBoxHierarchyType;
|
|
|
|
} else if (0 == strcmp(type, "rtree")) {
|
|
|
|
bbhType = sk_tools::PictureRenderer::kRTree_BBoxHierarchyType;
|
|
|
|
} else {
|
|
|
|
error.printf("%s is not a valid value for --bbhType\n", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (FLAGS_pipe && sk_tools::PictureRenderer::kNone_BBoxHierarchyType != bbhType) {
|
|
|
|
error.printf("--pipe and --bbh cannot be used together\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
renderer->setBBoxHierarchyType(bbhType);
|
|
|
|
renderer->setScaleFactor(SkDoubleToScalar(FLAGS_scale));
|
|
|
|
|
|
|
|
return renderer.detach();
|
|
|
|
}
|