blob: 1d38b562a9af38be152b36d463e887378dcc1b8b [file] [log] [blame]
kkinnunen3e980c32015-12-23 01:33:00 -08001/*
2 * Copyright 2015 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 "SkCommonFlagsConfig.h"
csmartdalton6270e552016-09-13 10:41:49 -07009#include "SkImageInfo.h"
kkinnunen3e980c32015-12-23 01:33:00 -080010
11#include <stdlib.h>
12
bsalomon3724e572016-03-30 18:56:19 -070013#if SK_SUPPORT_GPU
14using sk_gpu_test::GrContextFactory;
15#endif
16
kkinnunen3e980c32015-12-23 01:33:00 -080017static const char defaultConfigs[] =
18 "565 8888 gpu nonrendering"
19#if SK_ANGLE
20#ifdef SK_BUILD_FOR_WIN
21 " angle"
22#endif
23#endif
24#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
25 " hwui"
26#endif
27 ;
28
29static const char configHelp[] =
bsalomonb8797bb2016-04-05 08:49:38 -070030 "Options: 565 8888 debug gpu gl gpudebug gpudft gpunull "
31 "msaa16 msaa4 glmsaa4 gpuf16 gpusrgb glsrgb nonrendering null nullgpu "
32 "nvpr16 nvpr4 nvprdit16 nvprdit4 glnvpr4 glnvprdit4 pdf skp svg xps"
csmartdaltone0d36292016-07-29 08:14:20 -070033 "glinst glinst4 glinstdit4 glinst16 glinstdit16 esinst esinst4 esinsdit4"
kkinnunen3e980c32015-12-23 01:33:00 -080034#if SK_ANGLE
35#ifdef SK_BUILD_FOR_WIN
brianosman744898a2016-03-01 13:44:28 -080036 " angle"
kkinnunen3e980c32015-12-23 01:33:00 -080037#endif
38 " angle-gl"
39#endif
40#if SK_COMMAND_BUFFER
41 " commandbuffer"
42#endif
43#if SK_MESA
44 " mesa"
45#endif
46#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
47 " hwui"
48#endif
bsalomondc0fcd42016-04-11 14:21:33 -070049#ifdef SK_VULKAN
brianosmana56800a2016-05-23 10:11:07 -070050 " vk vksrgb"
bsalomondc0fcd42016-04-11 14:21:33 -070051#endif
kkinnunen3e980c32015-12-23 01:33:00 -080052 " or use extended form 'backend(option=value,...)'.\n";
53
54static const char configExtendedHelp[] =
55 "Extended form: 'backend(option=value,...)'\n\n"
56 "Possible backends and options:\n"
57#if SK_SUPPORT_GPU
58 "\n"
csmartdaltone0d36292016-07-29 08:14:20 -070059 "gpu(api=string,color=string,dit=bool,nvpr=bool,inst=bool,samples=int)\tGPU backend\n"
kkinnunen3e980c32015-12-23 01:33:00 -080060 "\tapi\ttype: string\tdefault: native.\n"
61 "\t Select graphics API to use with gpu backend.\n"
62 "\t Options:\n"
63 "\t\tnative\t\t\tUse platform default OpenGL or OpenGL ES backend.\n"
64 "\t\tgl \t\t\tUse OpenGL.\n"
65 "\t\tgles \t\t\tUse OpenGL ES.\n"
66 "\t\tdebug \t\t\tUse debug OpenGL.\n"
67 "\t\tnull \t\t\tUse null OpenGL.\n"
68#if SK_ANGLE
69#ifdef SK_BUILD_FOR_WIN
70 "\t\tangle\t\t\tUse ANGLE DirectX.\n"
71#endif
72 "\t\tangle-gl\t\t\tUse ANGLE OpenGL.\n"
73#endif
74#if SK_COMMAND_BUFFER
75 "\t\tcommandbuffer\t\tUse command buffer.\n"
76#endif
77#if SK_MESA
78 "\t\tmesa\t\t\tUse MESA.\n"
79#endif
bsalomondc0fcd42016-04-11 14:21:33 -070080#ifdef SK_VULKAN
81 "\t\tvulkan\t\t\tUse Vulkan.\n"
82#endif
brianosmand93c1202016-03-10 07:49:08 -080083 "\tcolor\ttype: string\tdefault: 8888.\n"
84 "\t Select framebuffer color format.\n"
85 "\t Options:\n"
86 "\t\t8888\t\t\tLinear 8888.\n"
87 "\t\tf16 \t\t\tLinear 16-bit floating point.\n"
88 "\t\tsrgb\t\t\tsRGB 8888.\n"
kkinnunen3e980c32015-12-23 01:33:00 -080089 "\tdit\ttype: bool\tdefault: false.\n"
90 "\t Use device independent text.\n"
91 "\tnvpr\ttype: bool\tdefault: false.\n"
92 "\t Use NV_path_rendering OpenGL and OpenGL ES extension.\n"
93 "\tsamples\ttype: int\tdefault: 0.\n"
94 "\t Use multisampling with N samples.\n"
95 "\n"
96 "Predefined configs:\n\n"
cdaltonc28afdb2016-03-29 20:05:07 -070097 "\tgpu \t= gpu()\n"
bsalomonb8797bb2016-04-05 08:49:38 -070098 "\tgl \t= gpu(api=gl)\n"
cdaltonc28afdb2016-03-29 20:05:07 -070099 "\tmsaa4 \t= gpu(samples=4)\n"
bsalomonb8797bb2016-04-05 08:49:38 -0700100 "\tglmsaa4 \t= gpu(api=gl,samples=4)\n"
cdaltonc28afdb2016-03-29 20:05:07 -0700101 "\tmsaa16 \t= gpu(samples=16)\n"
102 "\tnvpr4 \t= gpu(nvpr=true,samples=4)\n"
bsalomonb8797bb2016-04-05 08:49:38 -0700103 "\tglnvpr4 \t= gpu(api=gl,nvpr=true,samples=4)\n"
cdaltonc28afdb2016-03-29 20:05:07 -0700104 "\tnvpr16 \t= gpu(nvpr=true,samples=16)\n"
105 "\tnvprdit4 \t= gpu(nvpr=true,samples=4,dit=true)\n"
bsalomonb8797bb2016-04-05 08:49:38 -0700106 "\tglnvprdit4\t= gpu(api=gl,nvpr=true,samples=4,dit=true)\n"
cdaltonc28afdb2016-03-29 20:05:07 -0700107 "\tnvprdit16 \t= gpu(nvpr=true,samples=16,dit=true)\n"
brianosmand93c1202016-03-10 07:49:08 -0800108 "\tgpuf16 \t= gpu(color=f16)\n"
109 "\tgpusrgb \t= gpu(color=srgb)\n"
bsalomonb8797bb2016-04-05 08:49:38 -0700110 "\tglsrgb \t= gpu(api=gl,color=srgb)\n"
kkinnunen3e980c32015-12-23 01:33:00 -0800111 "\tgpudft \t= gpu(dit=true)\n"
112 "\tgpudebug \t= gpu(api=debug)\n"
113 "\tgpunull \t= gpu(api=null)\n"
114 "\tdebug \t= gpu(api=debug)\n"
115 "\tnullgpu \t= gpu(api=null)\n"
116#if SK_ANGLE
117#ifdef SK_BUILD_FOR_WIN
118 "\tangle \t= gpu(api=angle)\n"
119#endif
120 "\tangle-gl \t= gpu(api=angle-gl)\n"
121#endif
122#if SK_COMMAND_BUFFER
123 "\tcommandbuffer\t= gpu(api=commandbuffer)\n"
124#endif
125#if SK_MESA
126 "\tmesa \t= gpu(api=mesa)\n"
127#endif
bsalomondc0fcd42016-04-11 14:21:33 -0700128#ifdef SK_VULKAN
brianosmana56800a2016-05-23 10:11:07 -0700129 "\tvk \t= gpu(api=vulkan)\n"
130 "\tvksrgb \t= gpu(api=vulkan,color=srgb)\n"
egdanielbf63e612016-08-17 06:26:16 -0700131 "\tvkmsaa4 \t= gpu(api=gl,samples=4)\n"
132 "\tvkmsaa16 \t= gpu(api=gl,samples=16)\n"
bsalomondc0fcd42016-04-11 14:21:33 -0700133#endif
kkinnunen3e980c32015-12-23 01:33:00 -0800134#endif
135 ;
136
137DEFINE_extended_string(config, defaultConfigs, configHelp, configExtendedHelp);
138
139static const struct {
140 const char* predefinedConfig;
141 const char* backend;
142 const char* options;
143} gPredefinedConfigs[] = {
144#if SK_SUPPORT_GPU
csmartdaltone0d36292016-07-29 08:14:20 -0700145 { "gpu", "gpu", "" },
146 { "gl", "gpu", "api=gl" },
147 { "msaa4", "gpu", "samples=4" },
148 { "glmsaa4", "gpu", "api=gl,samples=4" },
149 { "msaa16", "gpu", "samples=16" },
150 { "nvpr4", "gpu", "nvpr=true,samples=4" },
151 { "glnvpr4", "gpu", "api=gl,nvpr=true,samples=4" },
152 { "nvpr16", "gpu", "nvpr=true,samples=16" },
153 { "nvprdit4", "gpu", "nvpr=true,samples=4,dit=true" },
154 { "glnvprdit4", "gpu", "api=gl,nvpr=true,samples=4,dit=true" },
155 { "nvprdit16", "gpu", "nvpr=true,samples=16,dit=true" },
156 { "glinst", "gpu", "api=gl,inst=true" },
157 { "glinst4", "gpu", "api=gl,inst=true,samples=4" },
158 { "glinstdit4", "gpu", "api=gl,inst=true,samples=4,dit=true" },
159 { "glinst16", "gpu", "api=gl,inst=true,samples=16" },
160 { "glinstdit16", "gpu", "api=gl,inst=true,samples=16,dit=true" },
161 { "esinst", "gpu", "api=gles,inst=true" },
162 { "esinst4", "gpu", "api=gles,inst=true,samples=4" },
163 { "esinstdit4", "gpu", "api=gles,inst=true,samples=4,dit=true" },
164 { "gpuf16", "gpu", "color=f16" },
165 { "gpusrgb", "gpu", "color=srgb" },
166 { "glsrgb", "gpu", "api=gl,color=srgb" },
167 { "gpudft", "gpu", "dit=true" },
168 { "gpudebug", "gpu", "api=debug" },
169 { "gpunull", "gpu", "api=null" },
170 { "debug", "gpu", "api=debug" },
171 { "nullgpu", "gpu", "api=null" }
kkinnunen3e980c32015-12-23 01:33:00 -0800172#if SK_ANGLE
173#ifdef SK_BUILD_FOR_WIN
174 , { "angle", "gpu", "api=angle" }
175#endif
176 , { "angle-gl", "gpu", "api=angle-gl" }
177#endif
178#if SK_COMMAND_BUFFER
179 , { "commandbuffer", "gpu", "api=commandbuffer" }
180#endif
181#if SK_MESA
182 , { "mesa", "gpu", "api=mesa" }
183#endif
bsalomondc0fcd42016-04-11 14:21:33 -0700184#ifdef SK_VULKAN
egdanielbf63e612016-08-17 06:26:16 -0700185 , { "vk", "gpu", "api=vulkan" }
186 , { "vksrgb", "gpu", "api=vulkan,color=srgb" }
187 , { "vkmsaa4", "gpu", "api=vulkan,samples=4" }
188 , { "vkmsaa16", "gpu", "api=vulkan,samples=16" }
bsalomondc0fcd42016-04-11 14:21:33 -0700189#endif
190
kkinnunen3e980c32015-12-23 01:33:00 -0800191#else
192 { "", "", "" }
193#endif
194};
195
196SkCommandLineConfig::SkCommandLineConfig(const SkString& tag, const SkString& backend,
197 const SkTArray<SkString>& viaParts)
198 : fTag(tag)
199 , fBackend(backend)
200 , fViaParts(viaParts) {
201}
202SkCommandLineConfig::~SkCommandLineConfig() {
203}
204
205#if SK_SUPPORT_GPU
206SkCommandLineConfigGpu::SkCommandLineConfigGpu(
csmartdaltone0d36292016-07-29 08:14:20 -0700207 const SkString& tag, const SkTArray<SkString>& viaParts, ContextType contextType, bool useNVPR,
208 bool useInstanced, bool useDIText, int samples, SkColorType colorType,
209 sk_sp<SkColorSpace> colorSpace)
kkinnunen3e980c32015-12-23 01:33:00 -0800210 : SkCommandLineConfig(tag, SkString("gpu"), viaParts)
211 , fContextType(contextType)
csmartdalton6270e552016-09-13 10:41:49 -0700212 , fContextOptions(ContextOptions::kNone)
kkinnunen3e980c32015-12-23 01:33:00 -0800213 , fUseDIText(useDIText)
brianosmand93c1202016-03-10 07:49:08 -0800214 , fSamples(samples)
215 , fColorType(colorType)
brianosmanb109b8c2016-06-16 13:03:24 -0700216 , fColorSpace(std::move(colorSpace)) {
csmartdalton6270e552016-09-13 10:41:49 -0700217 if (useNVPR) {
218 fContextOptions |= ContextOptions::kEnableNVPR;
219 }
220 if (useInstanced) {
221 fContextOptions |= ContextOptions::kUseInstanced;
222 }
223 if (SkColorAndColorSpaceAreGammaCorrect(colorType, colorSpace.get())) {
224 fContextOptions |= ContextOptions::kRequireSRGBSupport;
225 }
kkinnunen3e980c32015-12-23 01:33:00 -0800226}
227static bool parse_option_int(const SkString& value, int* outInt) {
228 if (value.isEmpty()) {
229 return false;
230 }
231 char* endptr = nullptr;
232 long intValue = strtol(value.c_str(), &endptr, 10);
233 if (*endptr != '\0') {
234 return false;
235 }
236 *outInt = static_cast<int>(intValue);
237 return true;
238}
239static bool parse_option_bool(const SkString& value, bool* outBool) {
240 if (value.equals("true")) {
241 *outBool = true;
242 return true;
243 }
244 if (value.equals("false")) {
245 *outBool = false;
246 return true;
247 }
248 return false;
249}
250static bool parse_option_gpu_api(const SkString& value,
251 SkCommandLineConfigGpu::ContextType* outContextType) {
kkinnunen3e980c32015-12-23 01:33:00 -0800252 if (value.equals("gl")) {
bsalomon85b4b532016-04-05 11:06:27 -0700253 *outContextType = GrContextFactory::kGL_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800254 return true;
255 }
256 if (value.equals("gles")) {
bsalomon85b4b532016-04-05 11:06:27 -0700257 *outContextType = GrContextFactory::kGLES_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800258 return true;
259 }
260 if (value.equals("debug")) {
bsalomon85b4b532016-04-05 11:06:27 -0700261 *outContextType = GrContextFactory::kDebugGL_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800262 return true;
263 }
264 if (value.equals("null")) {
bsalomon85b4b532016-04-05 11:06:27 -0700265 *outContextType = GrContextFactory::kNullGL_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800266 return true;
267 }
268#if SK_ANGLE
269#ifdef SK_BUILD_FOR_WIN
270 if (value.equals("angle")) {
bsalomon85b4b532016-04-05 11:06:27 -0700271 *outContextType = GrContextFactory::kANGLE_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800272 return true;
273 }
274#endif
275 if (value.equals("angle-gl")) {
bsalomon85b4b532016-04-05 11:06:27 -0700276 *outContextType = GrContextFactory::kANGLE_GL_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800277 return true;
278 }
279#endif
280#if SK_COMMAND_BUFFER
281 if (value.equals("commandbuffer")) {
bsalomon85b4b532016-04-05 11:06:27 -0700282 *outContextType = GrContextFactory::kCommandBuffer_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800283 return true;
284 }
285#endif
286#if SK_MESA
287 if (value.equals("mesa")) {
bsalomon85b4b532016-04-05 11:06:27 -0700288 *outContextType = GrContextFactory::kMESA_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800289 return true;
290 }
291#endif
bsalomondc0fcd42016-04-11 14:21:33 -0700292#ifdef SK_VULKAN
293 if (value.equals("vulkan")) {
294 *outContextType = GrContextFactory::kVulkan_ContextType;
295 return true;
296 }
297#endif
kkinnunen3e980c32015-12-23 01:33:00 -0800298 return false;
299}
brianosmand93c1202016-03-10 07:49:08 -0800300static bool parse_option_gpu_color(const SkString& value,
301 SkColorType* outColorType,
brianosmanb109b8c2016-06-16 13:03:24 -0700302 sk_sp<SkColorSpace>* outColorSpace) {
brianosmand93c1202016-03-10 07:49:08 -0800303 if (value.equals("8888")) {
304 *outColorType = kN32_SkColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700305 *outColorSpace = nullptr;
brianosmand93c1202016-03-10 07:49:08 -0800306 return true;
307 }
308 if (value.equals("f16")) {
309 *outColorType = kRGBA_F16_SkColorType;
brianosman0e22eb82016-08-30 07:07:59 -0700310 *outColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
brianosmand93c1202016-03-10 07:49:08 -0800311 return true;
312 }
313 if (value.equals("srgb")) {
314 *outColorType = kN32_SkColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700315 *outColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
brianosmand93c1202016-03-10 07:49:08 -0800316 return true;
317 }
318 return false;
319}
kkinnunen3e980c32015-12-23 01:33:00 -0800320
321SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
322 const SkTArray<SkString>& vias,
323 const SkString& options) {
324 // Defaults for GPU backend.
325 bool seenAPI = false;
bsalomon85b4b532016-04-05 11:06:27 -0700326 SkCommandLineConfigGpu::ContextType contextType = GrContextFactory::kNativeGL_ContextType;
kkinnunen3e980c32015-12-23 01:33:00 -0800327 bool seenUseNVPR = false;
328 bool useNVPR = false;
csmartdaltone0d36292016-07-29 08:14:20 -0700329 bool seenUseInstanced = false;
330 bool useInstanced = false;
kkinnunen3e980c32015-12-23 01:33:00 -0800331 bool seenUseDIText =false;
332 bool useDIText = false;
333 bool seenSamples = false;
334 int samples = 0;
brianosmand93c1202016-03-10 07:49:08 -0800335 bool seenColor = false;
336 SkColorType colorType = kN32_SkColorType;
brianosmanb109b8c2016-06-16 13:03:24 -0700337 sk_sp<SkColorSpace> colorSpace = nullptr;
kkinnunen3e980c32015-12-23 01:33:00 -0800338
339 SkTArray<SkString> optionParts;
340 SkStrSplit(options.c_str(), ",", kStrict_SkStrSplitMode, &optionParts);
341 for (int i = 0; i < optionParts.count(); ++i) {
342 SkTArray<SkString> keyValueParts;
343 SkStrSplit(optionParts[i].c_str(), "=", kStrict_SkStrSplitMode, &keyValueParts);
344 if (keyValueParts.count() != 2) {
345 return nullptr;
346 }
347 const SkString& key = keyValueParts[0];
348 const SkString& value = keyValueParts[1];
349 bool valueOk = false;
350 if (key.equals("api") && !seenAPI) {
351 valueOk = parse_option_gpu_api(value, &contextType);
352 seenAPI = true;
353 } else if (key.equals("nvpr") && !seenUseNVPR) {
354 valueOk = parse_option_bool(value, &useNVPR);
355 seenUseNVPR = true;
csmartdaltone0d36292016-07-29 08:14:20 -0700356 } else if (key.equals("inst") && !seenUseInstanced) {
357 valueOk = parse_option_bool(value, &useInstanced);
358 seenUseInstanced = true;
kkinnunen3e980c32015-12-23 01:33:00 -0800359 } else if (key.equals("dit") && !seenUseDIText) {
360 valueOk = parse_option_bool(value, &useDIText);
361 seenUseDIText = true;
362 } else if (key.equals("samples") && !seenSamples) {
363 valueOk = parse_option_int(value, &samples);
364 seenSamples = true;
brianosmand93c1202016-03-10 07:49:08 -0800365 } else if (key.equals("color") && !seenColor) {
brianosmanb109b8c2016-06-16 13:03:24 -0700366 valueOk = parse_option_gpu_color(value, &colorType, &colorSpace);
brianosmand93c1202016-03-10 07:49:08 -0800367 seenColor = true;
kkinnunen3e980c32015-12-23 01:33:00 -0800368 }
369 if (!valueOk) {
370 return nullptr;
371 }
372 }
csmartdaltone0d36292016-07-29 08:14:20 -0700373 return new SkCommandLineConfigGpu(tag, vias, contextType, useNVPR, useInstanced, useDIText,
374 samples, colorType, colorSpace);
kkinnunen3e980c32015-12-23 01:33:00 -0800375}
376#endif
377
378void ParseConfigs(const SkCommandLineFlags::StringArray& configs,
379 SkCommandLineConfigArray* outResult) {
380 outResult->reset();
381 for (int i = 0; i < configs.count(); ++i) {
382 SkString extendedBackend;
383 SkString extendedOptions;
384 SkString simpleBackend;
385 SkTArray<SkString> vias;
386
387 SkString tag(configs[i]);
388 SkTArray<SkString> parts;
389 SkStrSplit(tag.c_str(), "(", kStrict_SkStrSplitMode, &parts);
390 if (parts.count() == 2) {
391 SkTArray<SkString> parts2;
392 SkStrSplit(parts[1].c_str(), ")", kStrict_SkStrSplitMode, &parts2);
393 if (parts2.count() == 2 && parts2[1].isEmpty()) {
394 SkStrSplit(parts[0].c_str(), "-", kStrict_SkStrSplitMode, &vias);
395 if (vias.count()) {
396 extendedBackend = vias[vias.count() - 1];
397 vias.pop_back();
398 } else {
399 extendedBackend = parts[0];
400 }
401 extendedOptions = parts2[0];
402 simpleBackend.printf("%s(%s)", extendedBackend.c_str(), extendedOptions.c_str());
403 }
404 }
405
406 if (extendedBackend.isEmpty()) {
407 simpleBackend = tag;
408 SkStrSplit(tag.c_str(), "-", kStrict_SkStrSplitMode, &vias);
409 if (vias.count()) {
410 simpleBackend = vias[vias.count() - 1];
411 vias.pop_back();
412 }
413 // Note: no #if SK_ANGLE: this is a special rule in the via-tag grammar.
414 if (vias.count() && simpleBackend.equals("gl") &&
415 vias[vias.count() - 1].equals("angle")) {
416 simpleBackend = "angle-gl";
417 vias.pop_back();
418 }
419
420 for (auto& predefinedConfig : gPredefinedConfigs) {
421 if (simpleBackend.equals(predefinedConfig.predefinedConfig)) {
422 extendedBackend = predefinedConfig.backend;
423 extendedOptions = predefinedConfig.options;
424 break;
425 }
426 }
427 }
428 SkCommandLineConfig* parsedConfig = nullptr;
429#if SK_SUPPORT_GPU
430 if (extendedBackend.equals("gpu")) {
431 parsedConfig = parse_command_line_config_gpu(tag, vias, extendedOptions);
432 }
433#endif
434 if (!parsedConfig) {
435 parsedConfig = new SkCommandLineConfig(tag, simpleBackend, vias);
436 }
437 outResult->emplace_back(parsedConfig);
438 }
439}