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