• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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