1 /*
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 "tools/flags/CommonFlagsConfig.h"
9
10 #include "include/core/SkImageInfo.h"
11 #include "include/core/SkSurfaceProps.h"
12 #include "include/private/SkTHash.h"
13 #include "src/core/SkColorSpacePriv.h"
14 #include "src/core/SkSurfacePriv.h"
15
16 #include <stdlib.h>
17
18 using sk_gpu_test::GrContextFactory;
19
20 #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_IOS)
21 #define DEFAULT_GPU_CONFIG "gles"
22 #else
23 #define DEFAULT_GPU_CONFIG "gl"
24 #endif
25
26 static const char defaultConfigs[] = "8888 " DEFAULT_GPU_CONFIG
27 " nonrendering "
28 #if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
29 " angle_d3d11_es2"
30 #endif
31 ;
32
33 #undef DEFAULT_GPU_CONFIG
34
35 // clang-format off
36 static const struct {
37 const char* predefinedConfig;
38 const char* backend;
39 const char* options;
40 } gPredefinedConfigs[] = {
41 { "gl", "gpu", "api=gl" },
42 { "gles", "gpu", "api=gles" },
43 { "glesfakev2", "gpu", "api=glesfakev2" },
44 { "gldmsaa", "gpu", "api=gl,dmsaa=true" },
45 { "glesdmsaa", "gpu", "api=gles,dmsaa=true" },
46 { "glmsaa4", "gpu", "api=gl,samples=4" },
47 { "glmsaa8" , "gpu", "api=gl,samples=8" },
48 { "glesmsaa4", "gpu", "api=gles,samples=4" },
49 { "glbetex", "gpu", "api=gl,surf=betex" },
50 { "glesbetex", "gpu", "api=gles,surf=betex" },
51 { "glbert", "gpu", "api=gl,surf=bert" },
52 { "glesbert", "gpu", "api=gles,surf=bert" },
53 { "gl4444", "gpu", "api=gl,color=4444" },
54 { "gles4444", "gpu", "api=gles,color=4444" },
55 { "gl565", "gpu", "api=gl,color=565" },
56 { "gl888x", "gpu", "api=gl,color=888x" },
57 { "gles888x", "gpu", "api=gles,color=888x" },
58 { "gl1010102", "gpu", "api=gl,color=1010102" },
59 { "gles1010102", "gpu", "api=gles,color=1010102" },
60 { "glsrgb", "gpu", "api=gl,color=srgb" },
61 { "glp3", "gpu", "api=gl,color=p3" },
62 { "glesrgb", "gpu", "api=gl,color=esrgb" },
63 { "glnarrow", "gpu", "api=gl,color=narrow" },
64 { "glenarrow", "gpu", "api=gl,color=enarrow" },
65 { "glf16", "gpu", "api=gl,color=f16" },
66 { "glf16norm", "gpu", "api=gl,color=f16norm" },
67 { "glessrgb", "gpu", "api=gles,color=srgb" },
68 { "glesesrgb", "gpu", "api=gles,color=esrgb" },
69 { "glesnarrow", "gpu", "api=gles,color=narrow" },
70 { "glesenarrow", "gpu", "api=gles,color=enarrow" },
71 { "glesf16", "gpu", "api=gles,color=f16" },
72 { "glnostencils", "gpu", "api=gl,stencils=false" },
73 { "gldft", "gpu", "api=gl,dit=true" },
74 { "glesdft", "gpu", "api=gles,dit=true" },
75 { "gltestthreading", "gpu", "api=gl,testThreading=true" },
76 { "gltestpersistentcache", "gpu", "api=gl,testPersistentCache=1" },
77 { "gltestglslcache", "gpu", "api=gl,testPersistentCache=2" },
78 { "gltestprecompile", "gpu", "api=gl,testPrecompile=true" },
79 { "glestestprecompile", "gpu", "api=gles,testPrecompile=true" },
80 { "glddl", "gpu", "api=gl,useDDLSink=true" },
81 { "glooprddl", "gpu", "api=gl,OOPRish=true" },
82 { "glreducedshaders", "gpu", "api=gl,reducedShaders=true" },
83 { "glesreducedshaders", "gpu", "api=gles,reducedShaders=true" },
84 { "angle_d3d11_es2", "gpu", "api=angle_d3d11_es2" },
85 { "angle_d3d11_es3", "gpu", "api=angle_d3d11_es3" },
86 { "angle_d3d9_es2", "gpu", "api=angle_d3d9_es2" },
87 { "angle_d3d11_es2_msaa4", "gpu", "api=angle_d3d11_es2,samples=4" },
88 { "angle_d3d11_es2_msaa8", "gpu", "api=angle_d3d11_es2,samples=8" },
89 { "angle_d3d11_es3_msaa4", "gpu", "api=angle_d3d11_es3,samples=4" },
90 { "angle_d3d11_es3_msaa8", "gpu", "api=angle_d3d11_es3,samples=8" },
91 { "angle_gl_es2", "gpu", "api=angle_gl_es2" },
92 { "angle_gl_es3", "gpu", "api=angle_gl_es3" },
93 { "angle_gl_es2_msaa4", "gpu", "api=angle_gl_es2,samples=4" },
94 { "angle_gl_es2_msaa8", "gpu", "api=angle_gl_es2,samples=8" },
95 { "angle_gl_es3_msaa4", "gpu", "api=angle_gl_es3,samples=4" },
96 { "angle_gl_es3_msaa8", "gpu", "api=angle_gl_es3,samples=8" },
97 { "commandbuffer", "gpu", "api=commandbuffer" },
98 { "mock", "gpu", "api=mock" },
99 #ifdef SK_DAWN
100 { "dawn", "gpu", "api=dawn" },
101 #endif
102 #ifdef SK_VULKAN
103 { "vk", "gpu", "api=vulkan" },
104 { "vknostencils", "gpu", "api=vulkan,stencils=false" },
105 { "vk1010102", "gpu", "api=vulkan,color=1010102" },
106 { "vksrgb", "gpu", "api=vulkan,color=srgb" },
107 { "vkesrgb", "gpu", "api=vulkan,color=esrgb" },
108 { "vknarrow", "gpu", "api=vulkan,color=narrow" },
109 { "vkenarrow", "gpu", "api=vulkan,color=enarrow" },
110 { "vkf16", "gpu", "api=vulkan,color=f16" },
111 { "vkmsaa4", "gpu", "api=vulkan,samples=4" },
112 { "vkmsaa8", "gpu", "api=vulkan,samples=8" },
113 { "vkbetex", "gpu", "api=vulkan,surf=betex" },
114 { "vkbert", "gpu", "api=vulkan,surf=bert" },
115 { "vktestpersistentcache", "gpu", "api=vulkan,testPersistentCache=1" },
116 { "vkddl", "gpu", "api=vulkan,useDDLSink=true" },
117 { "vkooprddl", "gpu", "api=vulkan,OOPRish=true" },
118 #endif
119 #ifdef SK_METAL
120 { "mtl", "gpu", "api=metal" },
121 { "mtl1010102", "gpu", "api=metal,color=1010102" },
122 { "mtlmsaa4", "gpu", "api=metal,samples=4" },
123 { "mtlmsaa8", "gpu", "api=metal,samples=8" },
124 { "mtlddl", "gpu", "api=metal,useDDLSink=true" },
125 { "mtlooprddl", "gpu", "api=metal,OOPRish=true" },
126 { "mtltestprecompile", "gpu", "api=metal,testPrecompile=true" },
127 { "mtlreducedshaders", "gpu", "api=metal,reducedShaders=true" },
128 #endif
129 #ifdef SK_DIRECT3D
130 { "d3d", "gpu", "api=direct3d" },
131 { "d3dmsaa4", "gpu", "api=direct3d,samples=4" },
132 { "d3dmsaa8", "gpu", "api=direct3d,samples=8" },
133 #endif
134 };
135 // clang-format on
136
137 static const char configHelp[] =
138 "Options: 565 8888 srgb f16 nonrendering null pdf pdfa skp pipe svg xps";
139
config_help_fn()140 static const char* config_help_fn() {
141 static SkString helpString;
142 helpString.set(configHelp);
143 for (const auto& config : gPredefinedConfigs) {
144 helpString.appendf(" %s", config.predefinedConfig);
145 }
146 helpString.append(" or use extended form 'backend[option=value,...]'.\n");
147 return helpString.c_str();
148 }
149
150 static const char configExtendedHelp[] =
151 "Extended form: 'backend(option=value,...)'\n\n"
152 "Possible backends and options:\n"
153 "\n"
154 "gpu[api=string,color=string,dit=bool,dmsaa=bool,samples=int]\n"
155 "\tapi\ttype: string\trequired\n"
156 "\t Select graphics API to use with gpu backend.\n"
157 "\t Options:\n"
158 "\t\tgl \t\t\tUse OpenGL.\n"
159 "\t\tgles \t\t\tUse OpenGL ES.\n"
160 "\t\tglesfakev2 \t\t\tUse OpenGL ES with version faked as 2.0.\n"
161 "\t\tnullgl \t\t\tUse null OpenGL.\n"
162 "\t\tangle_d3d9_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D9 backend.\n"
163 "\t\tangle_d3d11_es2\t\tUse OpenGL ES2 on the ANGLE Direct3D11 backend.\n"
164 "\t\tangle_d3d11_es3\t\tUse OpenGL ES3 on the ANGLE Direct3D11 backend.\n"
165 "\t\tangle_gl_es2\t\tUse OpenGL ES2 on the ANGLE OpenGL backend.\n"
166 "\t\tangle_gl_es3\t\tUse OpenGL ES3 on the ANGLE OpenGL backend.\n"
167 "\t\tcommandbuffer\t\tUse command buffer.\n"
168 "\t\tmock\t\t\tUse mock context.\n"
169 #ifdef SK_VULKAN
170 "\t\tvulkan\t\t\tUse Vulkan.\n"
171 #endif
172 #ifdef SK_METAL
173 "\t\tmetal\t\t\tUse Metal.\n"
174 #endif
175 "\tcolor\ttype: string\tdefault: 8888.\n"
176 "\t Select framebuffer color format.\n"
177 "\t Options:\n"
178 "\t\t8888\t\t\tLinear 8888.\n"
179 "\t\t888x\t\t\tLinear 888x.\n"
180 "\t\t4444\t\t\tLinear 4444.\n"
181 "\t\t565\t\t\tLinear 565.\n"
182 "\t\t1010102\t\t\tLinear 1010102.\n"
183 "\t\tsrgb\t\t\tsRGB 8888.\n"
184 "\t\tesrgb\t\t\tsRGB 16-bit floating point.\n"
185 "\t\tnarrow\t\t\tNarrow gamut 8888.\n"
186 "\t\tenarrow\t\t\tNarrow gamut 16-bit floating point.\n"
187 "\t\tf16\t\t\tLinearly blended 16-bit floating point.\n"
188 "\tdit\ttype: bool\tdefault: false.\n"
189 "\t Use device independent text.\n"
190 "\tdmsaa\ttype: bool\tdefault: false.\n"
191 "\t Use internal MSAA to render to non-MSAA surfaces.\n"
192 "\tsamples\ttype: int\tdefault: 0.\n"
193 "\t Use multisampling with N samples.\n"
194 "\tstencils\ttype: bool\tdefault: true.\n"
195 "\t Allow the use of stencil buffers.\n"
196 "\ttestThreading\ttype: bool\tdefault: false.\n"
197 "\t Run with and without worker threads, check that results match.\n"
198 "\ttestPersistentCache\ttype: int\tdefault: 0.\n"
199 "\t 1: Run using a pre-warmed binary GrContextOptions::fPersistentCache.\n"
200 "\t 2: Run using a pre-warmed GLSL GrContextOptions::fPersistentCache.\n"
201 "\tsurf\ttype: string\tdefault: default.\n"
202 "\t Controls the type of backing store for SkSurfaces.\n"
203 "\t Options:\n"
204 "\t\tdefault\t\t\tA renderable texture created in Skia's resource cache.\n"
205 "\t\tbetex\t\t\tA wrapped backend texture.\n"
206 "\t\tbert\t\t\tA wrapped backend render target\n"
207 "\n"
208 "Predefined configs:\n\n"
209 // Help text for pre-defined configs is auto-generated from gPredefinedConfigs
210 ;
211
config_extended_help_fn()212 static const char* config_extended_help_fn() {
213 static SkString helpString;
214 helpString.set(configExtendedHelp);
215 for (const auto& config : gPredefinedConfigs) {
216 helpString.appendf("\t%-10s\t= gpu(%s)\n", config.predefinedConfig, config.options);
217 }
218 return helpString.c_str();
219 }
220
221 DEFINE_extended_string(config, defaultConfigs, config_help_fn(), config_extended_help_fn());
222
SkCommandLineConfig(const SkString & tag,const SkString & backend,const SkTArray<SkString> & viaParts)223 SkCommandLineConfig::SkCommandLineConfig(const SkString& tag,
224 const SkString& backend,
225 const SkTArray<SkString>& viaParts)
226 : fTag(tag), fBackend(backend), fViaParts(viaParts) {}
~SkCommandLineConfig()227 SkCommandLineConfig::~SkCommandLineConfig() {}
228
parse_option_int(const SkString & value,int * outInt)229 static bool parse_option_int(const SkString& value, int* outInt) {
230 if (value.isEmpty()) {
231 return false;
232 }
233 char* endptr = nullptr;
234 long intValue = strtol(value.c_str(), &endptr, 10);
235 if (*endptr != '\0') {
236 return false;
237 }
238 *outInt = static_cast<int>(intValue);
239 return true;
240 }
parse_option_bool(const SkString & value,bool * outBool)241 static bool parse_option_bool(const SkString& value, bool* outBool) {
242 if (value.equals("true")) {
243 *outBool = true;
244 return true;
245 }
246 if (value.equals("false")) {
247 *outBool = false;
248 return true;
249 }
250 return false;
251 }
parse_option_gpu_api(const SkString & value,SkCommandLineConfigGpu::ContextType * outContextType,bool * outFakeGLESVersion2)252 static bool parse_option_gpu_api(const SkString& value,
253 SkCommandLineConfigGpu::ContextType* outContextType,
254 bool* outFakeGLESVersion2) {
255 *outFakeGLESVersion2 = false;
256 if (value.equals("gl")) {
257 *outContextType = GrContextFactory::kGL_ContextType;
258 return true;
259 }
260 if (value.equals("gles")) {
261 *outContextType = GrContextFactory::kGLES_ContextType;
262 return true;
263 }
264 if (value.equals("glesfakev2")) {
265 *outContextType = GrContextFactory::kGLES_ContextType;
266 *outFakeGLESVersion2 = true;
267 return true;
268 }
269 if (value.equals("angle_d3d9_es2")) {
270 *outContextType = GrContextFactory::kANGLE_D3D9_ES2_ContextType;
271 return true;
272 }
273 if (value.equals("angle_d3d11_es2")) {
274 *outContextType = GrContextFactory::kANGLE_D3D11_ES2_ContextType;
275 return true;
276 }
277 if (value.equals("angle_d3d11_es3")) {
278 *outContextType = GrContextFactory::kANGLE_D3D11_ES3_ContextType;
279 return true;
280 }
281 if (value.equals("angle_gl_es2")) {
282 *outContextType = GrContextFactory::kANGLE_GL_ES2_ContextType;
283 return true;
284 }
285 if (value.equals("angle_gl_es3")) {
286 *outContextType = GrContextFactory::kANGLE_GL_ES3_ContextType;
287 return true;
288 }
289 if (value.equals("commandbuffer")) {
290 *outContextType = GrContextFactory::kCommandBuffer_ContextType;
291 return true;
292 }
293 if (value.equals("mock")) {
294 *outContextType = GrContextFactory::kMock_ContextType;
295 return true;
296 }
297 #ifdef SK_VULKAN
298 if (value.equals("vulkan")) {
299 *outContextType = GrContextFactory::kVulkan_ContextType;
300 return true;
301 }
302 #endif
303 #ifdef SK_METAL
304 if (value.equals("metal")) {
305 *outContextType = GrContextFactory::kMetal_ContextType;
306 return true;
307 }
308 #endif
309 #ifdef SK_DIRECT3D
310 if (value.equals("direct3d")) {
311 *outContextType = GrContextFactory::kDirect3D_ContextType;
312 return true;
313 }
314 #endif
315 #ifdef SK_DAWN
316 if (value.equals("dawn")) {
317 *outContextType = GrContextFactory::kDawn_ContextType;
318 return true;
319 }
320 #endif
321 return false;
322 }
323
parse_option_gpu_color(const SkString & value,SkColorType * outColorType,SkAlphaType * alphaType,sk_sp<SkColorSpace> * outColorSpace)324 static bool parse_option_gpu_color(const SkString& value,
325 SkColorType* outColorType,
326 SkAlphaType* alphaType,
327 sk_sp<SkColorSpace>* outColorSpace) {
328 // We always use premul unless the color type is 565.
329 *alphaType = kPremul_SkAlphaType;
330
331 if (value.equals("8888")) {
332 *outColorType = kRGBA_8888_SkColorType;
333 *outColorSpace = nullptr;
334 } else if (value.equals("888x")) {
335 *outColorType = kRGB_888x_SkColorType;
336 *outColorSpace = nullptr;
337 } else if (value.equals("8888s")) {
338 *outColorType = kRGBA_8888_SkColorType;
339 *outColorSpace = SkColorSpace::MakeSRGB();
340 } else if (value.equals("bgra8")) {
341 *outColorType = kBGRA_8888_SkColorType;
342 *outColorSpace = nullptr;
343 } else if (value.equals("bgra8s")) {
344 *outColorType = kBGRA_8888_SkColorType;
345 *outColorSpace = SkColorSpace::MakeSRGB();
346 } else if (value.equals("4444")) {
347 *outColorType = kARGB_4444_SkColorType;
348 *outColorSpace = nullptr;
349 } else if (value.equals("565")) {
350 *outColorType = kRGB_565_SkColorType;
351 *alphaType = kOpaque_SkAlphaType;
352 *outColorSpace = nullptr;
353 } else if (value.equals("1010102")) {
354 *outColorType = kRGBA_1010102_SkColorType;
355 *outColorSpace = nullptr;
356 } else if (value.equals("srgb")) {
357 *outColorType = kRGBA_8888_SkColorType;
358 *outColorSpace = SkColorSpace::MakeSRGB();
359 } else if (value.equals("p3")) {
360 *outColorType = kRGBA_8888_SkColorType;
361 *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);
362 } else if (value.equals("esrgb")) {
363 *outColorType = kRGBA_F16_SkColorType;
364 *outColorSpace = SkColorSpace::MakeSRGB();
365 } else if (value.equals("narrow") || value.equals("enarrow")) {
366 *outColorType = value.equals("narrow") ? kRGBA_8888_SkColorType : kRGBA_F16_SkColorType;
367 *outColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gNarrow_toXYZD50);
368 } else if (value.equals("f16")) {
369 *outColorType = kRGBA_F16_SkColorType;
370 *outColorSpace = SkColorSpace::MakeSRGBLinear();
371 } else if (value.equals("f16norm")) {
372 *outColorType = kRGBA_F16Norm_SkColorType;
373 *outColorSpace = SkColorSpace::MakeSRGB();
374 } else {
375 return false;
376 }
377 return true;
378 }
379
parse_option_gpu_surf_type(const SkString & value,SkCommandLineConfigGpu::SurfType * surfType)380 static bool parse_option_gpu_surf_type(const SkString& value,
381 SkCommandLineConfigGpu::SurfType* surfType) {
382 if (value.equals("default")) {
383 *surfType = SkCommandLineConfigGpu::SurfType::kDefault;
384 return true;
385 }
386 if (value.equals("betex")) {
387 *surfType = SkCommandLineConfigGpu::SurfType::kBackendTexture;
388 return true;
389 }
390 if (value.equals("bert")) {
391 *surfType = SkCommandLineConfigGpu::SurfType::kBackendRenderTarget;
392 return true;
393 }
394 return false;
395 }
396
397 // Extended options take form --config item[key1=value1,key2=value2,...]
398 // Example: --config gpu[api=gl,color=8888]
399 class ExtendedOptions {
400 public:
ExtendedOptions(const SkString & optionsString,bool * outParseSucceeded)401 ExtendedOptions(const SkString& optionsString, bool* outParseSucceeded) {
402 SkTArray<SkString> optionParts;
403 SkStrSplit(optionsString.c_str(), ",", kStrict_SkStrSplitMode, &optionParts);
404 for (int i = 0; i < optionParts.count(); ++i) {
405 SkTArray<SkString> keyValueParts;
406 SkStrSplit(optionParts[i].c_str(), "=", kStrict_SkStrSplitMode, &keyValueParts);
407 if (keyValueParts.count() != 2) {
408 *outParseSucceeded = false;
409 return;
410 }
411 const SkString& key = keyValueParts[0];
412 const SkString& value = keyValueParts[1];
413 if (fOptionsMap.find(key) == nullptr) {
414 fOptionsMap.set(key, value);
415 } else {
416 // Duplicate values are not allowed.
417 *outParseSucceeded = false;
418 return;
419 }
420 }
421 *outParseSucceeded = true;
422 }
423
get_option_gpu_color(const char * optionKey,SkColorType * outColorType,SkAlphaType * alphaType,sk_sp<SkColorSpace> * outColorSpace,bool optional=true) const424 bool get_option_gpu_color(const char* optionKey,
425 SkColorType* outColorType,
426 SkAlphaType* alphaType,
427 sk_sp<SkColorSpace>* outColorSpace,
428 bool optional = true) const {
429 SkString* optionValue = fOptionsMap.find(SkString(optionKey));
430 if (optionValue == nullptr) {
431 return optional;
432 }
433 return parse_option_gpu_color(*optionValue, outColorType, alphaType, outColorSpace);
434 }
435
get_option_gpu_api(const char * optionKey,SkCommandLineConfigGpu::ContextType * outContextType,bool * outFakeGLESVersion2,bool optional=true) const436 bool get_option_gpu_api(const char* optionKey,
437 SkCommandLineConfigGpu::ContextType* outContextType,
438 bool* outFakeGLESVersion2,
439 bool optional = true) const {
440 SkString* optionValue = fOptionsMap.find(SkString(optionKey));
441 if (optionValue == nullptr) {
442 return optional;
443 }
444 return parse_option_gpu_api(*optionValue, outContextType, outFakeGLESVersion2);
445 }
446
get_option_gpu_surf_type(const char * optionKey,SkCommandLineConfigGpu::SurfType * outSurfType,bool optional=true) const447 bool get_option_gpu_surf_type(const char* optionKey,
448 SkCommandLineConfigGpu::SurfType* outSurfType,
449 bool optional = true) const {
450 SkString* optionValue = fOptionsMap.find(SkString(optionKey));
451 if (optionValue == nullptr) {
452 return optional;
453 }
454 return parse_option_gpu_surf_type(*optionValue, outSurfType);
455 }
456
get_option_int(const char * optionKey,int * outInt,bool optional=true) const457 bool get_option_int(const char* optionKey, int* outInt, bool optional = true) const {
458 SkString* optionValue = fOptionsMap.find(SkString(optionKey));
459 if (optionValue == nullptr) {
460 return optional;
461 }
462 return parse_option_int(*optionValue, outInt);
463 }
464
get_option_bool(const char * optionKey,bool * outBool,bool optional=true) const465 bool get_option_bool(const char* optionKey, bool* outBool, bool optional = true) const {
466 SkString* optionValue = fOptionsMap.find(SkString(optionKey));
467 if (optionValue == nullptr) {
468 return optional;
469 }
470 return parse_option_bool(*optionValue, outBool);
471 }
472
473 private:
474 SkTHashMap<SkString, SkString> fOptionsMap;
475 };
476
SkCommandLineConfigGpu(const SkString & tag,const SkTArray<SkString> & viaParts,ContextType contextType,bool fakeGLESVersion2,uint32_t surfaceFlags,int samples,SkColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,bool useStencilBuffers,bool testThreading,int testPersistentCache,bool testPrecompile,bool useDDLSink,bool OOPRish,bool reducedShaders,SurfType surfType)477 SkCommandLineConfigGpu::SkCommandLineConfigGpu(const SkString& tag,
478 const SkTArray<SkString>& viaParts,
479 ContextType contextType,
480 bool fakeGLESVersion2,
481 uint32_t surfaceFlags,
482 int samples,
483 SkColorType colorType,
484 SkAlphaType alphaType,
485 sk_sp<SkColorSpace> colorSpace,
486 bool useStencilBuffers,
487 bool testThreading,
488 int testPersistentCache,
489 bool testPrecompile,
490 bool useDDLSink,
491 bool OOPRish,
492 bool reducedShaders,
493 SurfType surfType)
494 : SkCommandLineConfig(tag, SkString("gpu"), viaParts)
495 , fContextType(contextType)
496 , fContextOverrides(ContextOverrides::kNone)
497 , fSurfaceFlags(surfaceFlags)
498 , fSamples(samples)
499 , fColorType(colorType)
500 , fAlphaType(alphaType)
501 , fColorSpace(std::move(colorSpace))
502 , fTestThreading(testThreading)
503 , fTestPersistentCache(testPersistentCache)
504 , fTestPrecompile(testPrecompile)
505 , fUseDDLSink(useDDLSink)
506 , fOOPRish(OOPRish)
507 , fReducedShaders(reducedShaders)
508 , fSurfType(surfType) {
509 if (!useStencilBuffers) {
510 fContextOverrides |= ContextOverrides::kAvoidStencilBuffers;
511 }
512 if (fakeGLESVersion2) {
513 fContextOverrides |= ContextOverrides::kFakeGLESVersionAs2;
514 }
515 if (reducedShaders) {
516 fContextOverrides |= ContextOverrides ::kReducedShaders;
517 }
518 }
519
parse_command_line_config_gpu(const SkString & tag,const SkTArray<SkString> & vias,const SkString & options)520 SkCommandLineConfigGpu* parse_command_line_config_gpu(const SkString& tag,
521 const SkTArray<SkString>& vias,
522 const SkString& options) {
523 // Defaults for GPU backend.
524 SkCommandLineConfigGpu::ContextType contextType = GrContextFactory::kGL_ContextType;
525 bool useDIText = false;
526 bool useDMSAA = false;
527 int samples = 1;
528 SkColorType colorType = kRGBA_8888_SkColorType;
529 SkAlphaType alphaType = kPremul_SkAlphaType;
530 sk_sp<SkColorSpace> colorSpace = nullptr;
531 bool useStencils = true;
532 bool testThreading = false;
533 int testPersistentCache = 0;
534 bool testPrecompile = false;
535 bool useDDLs = false;
536 bool ooprish = false;
537 bool reducedShaders = false;
538 bool fakeGLESVersion2 = false;
539 SkCommandLineConfigGpu::SurfType surfType = SkCommandLineConfigGpu::SurfType::kDefault;
540
541 bool parseSucceeded = false;
542 ExtendedOptions extendedOptions(options, &parseSucceeded);
543 if (!parseSucceeded) {
544 return nullptr;
545 }
546
547 bool validOptions =
548 extendedOptions.get_option_gpu_api("api", &contextType, &fakeGLESVersion2, false) &&
549 extendedOptions.get_option_bool("dit", &useDIText) &&
550 extendedOptions.get_option_int("samples", &samples) &&
551 extendedOptions.get_option_bool("dmsaa", &useDMSAA) &&
552 extendedOptions.get_option_gpu_color("color", &colorType, &alphaType, &colorSpace) &&
553 extendedOptions.get_option_bool("stencils", &useStencils) &&
554 extendedOptions.get_option_bool("testThreading", &testThreading) &&
555 extendedOptions.get_option_int("testPersistentCache", &testPersistentCache) &&
556 extendedOptions.get_option_bool("testPrecompile", &testPrecompile) &&
557 extendedOptions.get_option_bool("useDDLSink", &useDDLs) &&
558 extendedOptions.get_option_bool("OOPRish", &ooprish) &&
559 extendedOptions.get_option_bool("reducedShaders", &reducedShaders) &&
560 extendedOptions.get_option_gpu_surf_type("surf", &surfType);
561
562 // testing threading and the persistent cache are mutually exclusive.
563 if (!validOptions || (testThreading && (testPersistentCache != 0))) {
564 return nullptr;
565 }
566
567 uint32_t surfaceFlags = 0;
568 if (useDIText) {
569 surfaceFlags |= SkSurfaceProps::kUseDeviceIndependentFonts_Flag;
570 }
571 if (useDMSAA) {
572 surfaceFlags |= kDMSAA_SkSurfacePropsPrivateFlag;
573 }
574
575 return new SkCommandLineConfigGpu(tag,
576 vias,
577 contextType,
578 fakeGLESVersion2,
579 surfaceFlags,
580 samples,
581 colorType,
582 alphaType,
583 colorSpace,
584 useStencils,
585 testThreading,
586 testPersistentCache,
587 testPrecompile,
588 useDDLs,
589 ooprish,
590 reducedShaders,
591 surfType);
592 }
593
SkCommandLineConfigSvg(const SkString & tag,const SkTArray<SkString> & viaParts,int pageIndex)594 SkCommandLineConfigSvg::SkCommandLineConfigSvg(const SkString& tag,
595 const SkTArray<SkString>& viaParts,
596 int pageIndex)
597 : SkCommandLineConfig(tag, SkString("svg"), viaParts), fPageIndex(pageIndex) {}
598
parse_command_line_config_svg(const SkString & tag,const SkTArray<SkString> & vias,const SkString & options)599 SkCommandLineConfigSvg* parse_command_line_config_svg(const SkString& tag,
600 const SkTArray<SkString>& vias,
601 const SkString& options) {
602 // Defaults for SVG backend.
603 int pageIndex = 0;
604
605 bool parseSucceeded = false;
606 ExtendedOptions extendedOptions(options, &parseSucceeded);
607 if (!parseSucceeded) {
608 return nullptr;
609 }
610
611 bool validOptions = extendedOptions.get_option_int("page", &pageIndex);
612
613 if (!validOptions) {
614 return nullptr;
615 }
616
617 return new SkCommandLineConfigSvg(tag, vias, pageIndex);
618 }
619
ParseConfigs(const CommandLineFlags::StringArray & configs,SkCommandLineConfigArray * outResult)620 void ParseConfigs(const CommandLineFlags::StringArray& configs,
621 SkCommandLineConfigArray* outResult) {
622 outResult->reset();
623 for (int i = 0; i < configs.count(); ++i) {
624 SkString extendedBackend;
625 SkString extendedOptions;
626 SkString simpleBackend;
627 SkTArray<SkString> vias;
628
629 SkString tag(configs[i]);
630 SkTArray<SkString> parts;
631 SkStrSplit(tag.c_str(), "[", kStrict_SkStrSplitMode, &parts);
632 if (parts.count() == 2) {
633 SkTArray<SkString> parts2;
634 SkStrSplit(parts[1].c_str(), "]", kStrict_SkStrSplitMode, &parts2);
635 if (parts2.count() == 2 && parts2[1].isEmpty()) {
636 SkStrSplit(parts[0].c_str(), "-", kStrict_SkStrSplitMode, &vias);
637 if (vias.count()) {
638 extendedBackend = vias[vias.count() - 1];
639 vias.pop_back();
640 } else {
641 extendedBackend = parts[0];
642 }
643 extendedOptions = parts2[0];
644 simpleBackend.printf("%s[%s]", extendedBackend.c_str(), extendedOptions.c_str());
645 }
646 }
647
648 if (extendedBackend.isEmpty()) {
649 simpleBackend = tag;
650 SkStrSplit(tag.c_str(), "-", kStrict_SkStrSplitMode, &vias);
651 if (vias.count()) {
652 simpleBackend = vias[vias.count() - 1];
653 vias.pop_back();
654 }
655 for (auto& predefinedConfig : gPredefinedConfigs) {
656 if (simpleBackend.equals(predefinedConfig.predefinedConfig)) {
657 extendedBackend = predefinedConfig.backend;
658 extendedOptions = predefinedConfig.options;
659 break;
660 }
661 }
662 }
663 SkCommandLineConfig* parsedConfig = nullptr;
664 if (extendedBackend.equals("gpu")) {
665 parsedConfig = parse_command_line_config_gpu(tag, vias, extendedOptions);
666 }
667 if (extendedBackend.equals("svg")) {
668 parsedConfig = parse_command_line_config_svg(tag, vias, extendedOptions);
669 }
670 if (!parsedConfig) {
671 parsedConfig = new SkCommandLineConfig(tag, simpleBackend, vias);
672 }
673 outResult->emplace_back(parsedConfig);
674 }
675 }
676