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 "SkColorSpace.h"
9#include "SkCommonFlagsConfig.h"
10#include "Test.h"
11#include <initializer_list>
12
13using sk_gpu_test::GrContextFactory;
14
15namespace {
16// The code
17//   SkCommandLineFlags::StringArray FLAGS_config1 = make_string_array({"a", "b"})
18// can be used to construct string array that one gets with command line flags.
19// For example, the call above is equivalent of
20//   DEFINE_string(config1, "a b", "");
21// in cases where the default command line flag value ("a b") is used.
22// make_string_array can be used to construct StringArray strings that have spaces in
23// them.
24SkCommandLineFlags::StringArray make_string_array(std::initializer_list<const char*> strings) {
25    SkTArray<SkString> array;
26    for (auto& s : strings) {
27        array.push_back(SkString(s));
28    }
29    return SkCommandLineFlags::StringArray(array);
30}
31}
32DEF_TEST(ParseConfigs_Gpu, reporter) {
33    // Parses a normal config and returns correct "tag".
34    // Simple GL config works
35    SkCommandLineFlags::StringArray config1 = make_string_array({"gl"});
36    SkCommandLineConfigArray configs;
37    ParseConfigs(config1, &configs);
38
39    REPORTER_ASSERT(reporter, configs.count() == 1);
40    REPORTER_ASSERT(reporter, configs[0]->getTag().equals("gl"));
41    REPORTER_ASSERT(reporter, configs[0]->getViaParts().count() == 0);
42#if SK_SUPPORT_GPU
43    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu());
44    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getContextType()
45                    == GrContextFactory::kGL_ContextType);
46    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getUseNVPR() == false);
47    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getUseDIText() == false);
48    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getSamples() == 1);
49    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getColorType() == kRGBA_8888_SkColorType);
50    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getColorSpace() == nullptr);
51#endif
52}
53
54DEF_TEST(ParseConfigs_OutParam, reporter) {
55    // Clears the out parameter.
56    SkCommandLineFlags::StringArray config1 = make_string_array({"gles"});
57    SkCommandLineConfigArray configs;
58    ParseConfigs(config1, &configs);
59    REPORTER_ASSERT(reporter, configs.count() == 1);
60    REPORTER_ASSERT(reporter, configs[0]->getTag().equals("gles"));
61
62    SkCommandLineFlags::StringArray config2 = make_string_array({"8888"});
63    ParseConfigs(config2, &configs);
64    REPORTER_ASSERT(reporter, configs.count() == 1);
65    REPORTER_ASSERT(reporter, configs[0]->getTag().equals("8888"));
66
67    SkCommandLineFlags::StringArray config3 = make_string_array({"gl"});
68    ParseConfigs(config3, &configs);
69    REPORTER_ASSERT(reporter, configs.count() == 1);
70    REPORTER_ASSERT(reporter, configs[0]->getTag().equals("gl"));
71}
72
73DEF_TEST(ParseConfigs_DefaultConfigs, reporter) {
74    // Parses all default configs and returns correct "tag".
75
76    SkCommandLineFlags::StringArray config1 = make_string_array({
77        "565",
78        "8888",
79        "debuggl",
80        "gl",
81        "gldft",
82        "nullgl",
83        "glmsaa8",
84        "glmsaa4",
85        "nonrendering",
86        "nullgl",
87        "gles",
88        "glnvpr8",
89        "glnvpr4",
90        "glnvprdit8",
91        "glesnvprdit4",
92        "pdf",
93        "skp",
94        "svg",
95        "xps",
96        "angle_d3d11_es2",
97        "angle_gl_es2",
98        "commandbuffer",
99        "mesa",
100        "hwui",
101        "glf16",
102        "glessrgb",
103        "gl",
104        "glnvpr4",
105        "glnvprdit4",
106        "glsrgb",
107        "glmsaa4",
108        "vk",
109        "glwide",
110        "glnarrow",
111        "glnostencils",
112        "mock",
113        "mtl",
114        "gl4444",
115        "gl565",
116        "gltestthreading"
117    });
118
119    SkCommandLineConfigArray configs;
120    ParseConfigs(config1, &configs);
121
122    auto srgbColorSpace = SkColorSpace::MakeSRGB();
123
124    REPORTER_ASSERT(reporter, configs.count() == config1.count());
125    for (int i = 0; i < config1.count(); ++i) {
126        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
127        REPORTER_ASSERT(reporter, configs[i]->getViaParts().count() == 0);
128    }
129#if SK_SUPPORT_GPU
130    REPORTER_ASSERT(reporter, !configs[0]->asConfigGpu());
131    REPORTER_ASSERT(reporter, !configs[1]->asConfigGpu());
132    REPORTER_ASSERT(reporter, configs[2]->asConfigGpu());
133    REPORTER_ASSERT(reporter, configs[3]->asConfigGpu());
134    REPORTER_ASSERT(reporter, configs[4]->asConfigGpu()->getUseDIText());
135    REPORTER_ASSERT(reporter, configs[5]->asConfigGpu());
136    REPORTER_ASSERT(reporter, configs[6]->asConfigGpu()->getSamples() == 8);
137    REPORTER_ASSERT(reporter, configs[7]->asConfigGpu()->getSamples() == 4);
138    REPORTER_ASSERT(reporter, !configs[8]->asConfigGpu());
139    REPORTER_ASSERT(reporter, configs[9]->asConfigGpu());
140    REPORTER_ASSERT(reporter, configs[10]->asConfigGpu());
141    REPORTER_ASSERT(reporter, configs[11]->asConfigGpu()->getSamples() == 8);
142    REPORTER_ASSERT(reporter, configs[11]->asConfigGpu()->getUseNVPR());
143    REPORTER_ASSERT(reporter, !configs[11]->asConfigGpu()->getUseDIText());
144    REPORTER_ASSERT(reporter, configs[12]->asConfigGpu()->getSamples() == 4);
145    REPORTER_ASSERT(reporter, configs[12]->asConfigGpu()->getUseNVPR());
146    REPORTER_ASSERT(reporter, !configs[12]->asConfigGpu()->getUseDIText());
147    REPORTER_ASSERT(reporter, configs[13]->asConfigGpu()->getSamples() == 8);
148    REPORTER_ASSERT(reporter, configs[13]->asConfigGpu()->getUseNVPR());
149    REPORTER_ASSERT(reporter, configs[13]->asConfigGpu()->getUseDIText());
150    REPORTER_ASSERT(reporter, configs[14]->asConfigGpu()->getSamples() == 4);
151    REPORTER_ASSERT(reporter, configs[14]->asConfigGpu()->getUseNVPR());
152    REPORTER_ASSERT(reporter, configs[14]->asConfigGpu()->getUseDIText());
153    REPORTER_ASSERT(reporter, !configs[15]->asConfigGpu());
154    REPORTER_ASSERT(reporter, !configs[16]->asConfigGpu());
155    REPORTER_ASSERT(reporter, !configs[17]->asConfigGpu());
156    REPORTER_ASSERT(reporter, !configs[18]->asConfigGpu());
157    REPORTER_ASSERT(reporter, !configs[23]->asConfigGpu());
158    REPORTER_ASSERT(reporter, configs[24]->asConfigGpu()->getColorType() == kRGBA_F16_SkColorType);
159    REPORTER_ASSERT(reporter, configs[24]->asConfigGpu()->getColorSpace());
160    REPORTER_ASSERT(reporter, configs[24]->asConfigGpu()->getColorSpace()->gammaIsLinear());
161    const SkMatrix44* srgbXYZ = srgbColorSpace->toXYZD50();
162    SkASSERT(srgbXYZ);
163    const SkMatrix44* config25XYZ = configs[24]->asConfigGpu()->getColorSpace()->toXYZD50();
164    SkASSERT(config25XYZ);
165    REPORTER_ASSERT(reporter, *config25XYZ == *srgbXYZ);
166    REPORTER_ASSERT(reporter, configs[25]->asConfigGpu()->getColorType() == kRGBA_8888_SkColorType);
167    REPORTER_ASSERT(reporter, configs[25]->asConfigGpu()->getColorSpace() == srgbColorSpace.get());
168    REPORTER_ASSERT(reporter, configs[32]->asConfigGpu()->getColorType() == kRGBA_F16_SkColorType);
169    REPORTER_ASSERT(reporter, configs[32]->asConfigGpu()->getColorSpace());
170    REPORTER_ASSERT(reporter, configs[32]->asConfigGpu()->getColorSpace()->gammaIsLinear());
171    const SkMatrix44* config41XYZ = configs[32]->asConfigGpu()->getColorSpace()->toXYZD50();
172    SkASSERT(config41XYZ);
173    REPORTER_ASSERT(reporter, *config41XYZ != *srgbXYZ);
174    REPORTER_ASSERT(reporter, configs[33]->asConfigGpu()->getColorType() == kRGBA_F16_SkColorType);
175    REPORTER_ASSERT(reporter, configs[33]->asConfigGpu()->getColorSpace());
176    REPORTER_ASSERT(reporter, configs[33]->asConfigGpu()->getColorSpace()->gammaIsLinear());
177    REPORTER_ASSERT(reporter, *configs[33]->asConfigGpu()->getColorSpace()->toXYZD50() !=
178                    *srgbColorSpace->toXYZD50());
179    REPORTER_ASSERT(reporter, configs[34]->asConfigGpu()->getContextType() ==
180                              GrContextFactory::kGL_ContextType);
181    REPORTER_ASSERT(reporter, SkToBool(configs[34]->asConfigGpu()->getContextOverrides() &
182                              SkCommandLineConfigGpu::ContextOverrides::kAvoidStencilBuffers));
183    REPORTER_ASSERT(reporter, configs[35]->asConfigGpu()->getContextType() ==
184                              GrContextFactory::kMock_ContextType);
185    REPORTER_ASSERT(reporter, configs[19]->asConfigGpu());
186    REPORTER_ASSERT(reporter, configs[20]->asConfigGpu());
187    REPORTER_ASSERT(reporter, configs[21]->asConfigGpu());
188    REPORTER_ASSERT(reporter, configs[37]->asConfigGpu()->getContextType() ==
189                              GrContextFactory::kGL_ContextType);
190    REPORTER_ASSERT(reporter, configs[37]->asConfigGpu()->getColorType() == kARGB_4444_SkColorType);
191    REPORTER_ASSERT(reporter, configs[37]->asConfigGpu()->getAlphaType() == kPremul_SkAlphaType);
192    REPORTER_ASSERT(reporter, configs[38]->asConfigGpu()->getContextType() ==
193                              GrContextFactory::kGL_ContextType);
194    REPORTER_ASSERT(reporter, configs[38]->asConfigGpu()->getColorType() == kRGB_565_SkColorType);
195    REPORTER_ASSERT(reporter, configs[38]->asConfigGpu()->getAlphaType() == kOpaque_SkAlphaType);
196    REPORTER_ASSERT(reporter, !configs[22]->asConfigGpu());
197    REPORTER_ASSERT(reporter, configs[26]->asConfigGpu());
198    REPORTER_ASSERT(reporter, configs[27]->asConfigGpu());
199    REPORTER_ASSERT(reporter, configs[27]->asConfigGpu()->getSamples() == 4);
200    REPORTER_ASSERT(reporter, configs[27]->asConfigGpu()->getUseNVPR());
201    REPORTER_ASSERT(reporter, configs[28]->asConfigGpu());
202    REPORTER_ASSERT(reporter, configs[28]->asConfigGpu()->getSamples() == 4);
203    REPORTER_ASSERT(reporter, configs[28]->asConfigGpu()->getUseNVPR());
204    REPORTER_ASSERT(reporter, configs[28]->asConfigGpu()->getUseDIText());
205    REPORTER_ASSERT(reporter, configs[29]->asConfigGpu());
206    REPORTER_ASSERT(reporter, configs[29]->asConfigGpu()->getColorType()  == kRGBA_8888_SkColorType);
207    REPORTER_ASSERT(reporter, configs[29]->asConfigGpu()->getColorSpace() == srgbColorSpace.get());
208    REPORTER_ASSERT(reporter, configs[30]->asConfigGpu());
209    REPORTER_ASSERT(reporter, configs[30]->asConfigGpu()->getSamples() == 4);
210    REPORTER_ASSERT(reporter, configs[39]->asConfigGpu());
211    REPORTER_ASSERT(reporter, configs[39]->asConfigGpu()->getTestThreading());
212#ifdef SK_VULKAN
213    REPORTER_ASSERT(reporter, configs[31]->asConfigGpu());
214#endif
215#endif
216}
217
218DEF_TEST(ParseConfigs_ExtendedGpuConfigsCorrect, reporter) {
219    SkCommandLineFlags::StringArray config1 = make_string_array({
220        "gpu[api=gl,nvpr=true,dit=false]",
221        "gpu[api=angle_d3d9_es2]",
222        "gpu[api=angle_gl_es3]",
223        "gpu[api=mesa,samples=77]",
224        "gpu[dit=true,api=commandbuffer]",
225        "gpu[api=gles]",
226        "gpu[api=gl]",
227        "gpu[api=vulkan]",
228        "gpu[api=metal]",
229        "gpu[api=mock]",
230    });
231
232    SkCommandLineConfigArray configs;
233    ParseConfigs(config1, &configs);
234    REPORTER_ASSERT(reporter, configs.count() == config1.count());
235    for (int i = 0; i < config1.count(); ++i) {
236        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
237    }
238#if SK_SUPPORT_GPU
239    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getContextType() ==
240                    GrContextFactory::kGL_ContextType);
241    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getUseNVPR());
242    REPORTER_ASSERT(reporter, !configs[0]->asConfigGpu()->getUseDIText());
243    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu()->getSamples() == 1);
244    REPORTER_ASSERT(reporter, configs[1]->asConfigGpu()->getContextType() ==
245                    GrContextFactory::kANGLE_D3D9_ES2_ContextType);
246    REPORTER_ASSERT(reporter, configs[1]->asConfigGpu());
247    REPORTER_ASSERT(reporter, configs[2]->asConfigGpu()->getContextType() ==
248                    GrContextFactory::kANGLE_GL_ES3_ContextType);
249    REPORTER_ASSERT(reporter, configs[2]->asConfigGpu());
250    REPORTER_ASSERT(reporter, !configs[3]->asConfigGpu());
251    REPORTER_ASSERT(reporter, configs[4]->asConfigGpu()->getContextType() ==
252                    GrContextFactory::kCommandBuffer_ContextType);
253    REPORTER_ASSERT(reporter, configs[5]->asConfigGpu()->getContextType() ==
254                    GrContextFactory::kGLES_ContextType);
255    REPORTER_ASSERT(reporter, !configs[5]->asConfigGpu()->getUseNVPR());
256    REPORTER_ASSERT(reporter, !configs[5]->asConfigGpu()->getUseDIText());
257    REPORTER_ASSERT(reporter, configs[5]->asConfigGpu()->getSamples() == 1);
258    REPORTER_ASSERT(reporter, configs[6]->asConfigGpu()->getContextType() ==
259                              GrContextFactory::kGL_ContextType);
260    REPORTER_ASSERT(reporter, !configs[6]->asConfigGpu()->getUseNVPR());
261    REPORTER_ASSERT(reporter, !configs[6]->asConfigGpu()->getUseDIText());
262    REPORTER_ASSERT(reporter, configs[6]->asConfigGpu()->getSamples() == 1);
263#ifdef SK_VULKAN
264    REPORTER_ASSERT(reporter, configs[7]->asConfigGpu()->getContextType() ==
265                              GrContextFactory::kVulkan_ContextType);
266    REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseNVPR());
267    REPORTER_ASSERT(reporter, !configs[7]->asConfigGpu()->getUseDIText());
268    REPORTER_ASSERT(reporter, configs[7]->asConfigGpu()->getSamples() == 1);
269#endif
270#ifdef SK_METAL
271    REPORTER_ASSERT(reporter, configs[8]->asConfigGpu()->getContextType() ==
272                              GrContextFactory::kMetal_ContextType);
273    REPORTER_ASSERT(reporter, !configs[8]->asConfigGpu()->getUseNVPR());
274    REPORTER_ASSERT(reporter, !configs[8]->asConfigGpu()->getUseDIText());
275    REPORTER_ASSERT(reporter, configs[8]->asConfigGpu()->getSamples() == 0);
276#endif
277    REPORTER_ASSERT(reporter, configs[9]->asConfigGpu()->getContextType() ==
278                   GrContextFactory::kMock_ContextType);
279#endif
280}
281
282DEF_TEST(ParseConfigs_ExtendedGpuConfigsIncorrect, reporter) {
283    SkCommandLineFlags::StringArray config1 = make_string_array({
284        "gpu[api=gl,nvpr=1]", // Number as bool.
285        "gpu[api=gl,]", // Trailing in comma.
286        "gpu[api=angle_glu]", // Unknown api.
287        "gpu[api=,samples=0]", // Empty api.
288        "gpu[api=gl,samples=true]", // Value true as a number.
289        "gpu[api=gl,samples=0,samples=0]", // Duplicate option key.
290        "gpu[,api=gl,samples=0]", // Leading comma.
291        "gpu[samples=54", // Missing closing parenthesis.
292        ",,",
293        "gpu[]", // Missing required api specifier
294        "gpu[samples=4]", // Missing required api specifier
295        "gpu[", // Missing bracket.
296        "samples=54" // No backend.
297        "gpu[nvpr=true ]", // Space.
298    });
299
300    SkCommandLineConfigArray configs;
301    ParseConfigs(config1, &configs);
302    REPORTER_ASSERT(reporter, configs.count() == config1.count());
303    for (int i = 0; i < config1.count(); ++i) {
304        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
305        REPORTER_ASSERT(reporter, configs[i]->getBackend().equals(config1[i]));
306#if SK_SUPPORT_GPU
307        REPORTER_ASSERT(reporter, !configs[i]->asConfigGpu());
308#endif
309    }
310}
311
312DEF_TEST(ParseConfigs_ExtendedGpuConfigsSurprises, reporter) {
313    // These just list explicitly some properties of the system.
314    SkCommandLineFlags::StringArray config1 = make_string_array({
315        // Options are not canonized -> two same configs have a different tag.
316        "gpu[api=gl,nvpr=true,dit=true]", "gpu[api=gl,dit=true,nvpr=true]",
317        "gpu[api=debuggl]", "gpu[api=gl]", "gpu[api=gles]", ""
318        "gpu[api=gl]", "gpu[api=gl,samples=0]", "gpu[api=gles,samples=0]"
319    });
320    SkCommandLineConfigArray configs;
321    ParseConfigs(config1, &configs);
322    REPORTER_ASSERT(reporter, configs.count() == config1.count());
323    for (int i = 0; i < config1.count(); ++i) {
324        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
325#if SK_SUPPORT_GPU
326        REPORTER_ASSERT(reporter, configs[i]->getBackend().equals("gpu"));
327        REPORTER_ASSERT(reporter, configs[i]->asConfigGpu());
328#else
329        REPORTER_ASSERT(reporter, configs[i]->getBackend().equals(config1[i]));
330#endif
331    }
332}
333
334#if SK_SUPPORT_GPU
335DEF_TEST(ParseConfigs_ViaParsing, reporter) {
336    SkCommandLineFlags::StringArray config1 = make_string_array({
337        "a-b-c-8888",
338        "zz-qq-gpu",
339        "a-angle_gl_es2"
340    });
341
342    SkCommandLineConfigArray configs;
343    ParseConfigs(config1, &configs);
344    const struct {
345        const char* backend;
346        const char* vias[3];
347    } expectedConfigs[] = {
348        {"8888", {"a", "b", "c"}},
349        {"gpu", {"zz", "qq", nullptr}},
350        {"gpu", { "a", nullptr, nullptr }}
351    };
352    for (int i = 0; i < config1.count(); ++i) {
353        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
354        REPORTER_ASSERT(reporter, configs[i]->getBackend().equals(expectedConfigs[i].backend));
355        for (int j = 0; j < static_cast<int>(SK_ARRAY_COUNT(expectedConfigs[i].vias)); ++j) {
356            if (!expectedConfigs[i].vias[j]) {
357                REPORTER_ASSERT(reporter, configs[i]->getViaParts().count() == j);
358                break;
359            }
360            REPORTER_ASSERT(reporter,
361                            configs[i]->getViaParts()[j].equals(expectedConfigs[i].vias[j]));
362        }
363    }
364}
365#endif
366
367DEF_TEST(ParseConfigs_ViaParsingExtendedForm, reporter) {
368    SkCommandLineFlags::StringArray config1 = make_string_array({
369        "zz-qq-gpu[api=gles]",
370        "abc-nbc-cbs-gpu[api=angle_d3d9_es2,samples=1]",
371        "a-gpu[api=gl",
372        "abc-def-angle_gl_es2[api=gles]",
373    });
374
375    SkCommandLineConfigArray configs;
376    ParseConfigs(config1, &configs);
377    const struct {
378        const char* backend;
379        const char* vias[3];
380    } expectedConfigs[] = {
381#if SK_SUPPORT_GPU
382        {"gpu", {"zz", "qq", nullptr}},
383        {"gpu", {"abc", "nbc", "cbs"}},
384#else
385        {"gpu[api=gles]", {"zz", "qq", nullptr}},
386        {"gpu[api=angle_d3d9_es2,samples=1]", {"abc", "nbc", "cbs"}},
387#endif
388        {"gpu[api=gl", {"a", nullptr, nullptr}}, // Missing bracket makes this is not extended
389                                                 // form but via still works as expected.
390        {"angle_gl_es2[api=gles]", {"abc", "def", nullptr}}  // This is not extended form.
391                                                             // angle_gl_es2 is an api type not a
392                                                             // backend.
393    };
394    for (int i = 0; i < config1.count(); ++i) {
395        REPORTER_ASSERT(reporter, configs[i]->getTag().equals(config1[i]));
396        REPORTER_ASSERT(reporter, configs[i]->getBackend().equals(expectedConfigs[i].backend));
397        for (int j = 0; j < static_cast<int>(SK_ARRAY_COUNT(expectedConfigs[i].vias)); ++j) {
398            if (!expectedConfigs[i].vias[j]) {
399                REPORTER_ASSERT(reporter, configs[i]->getViaParts().count() ==
400                                static_cast<int>(j));
401                break;
402            }
403            REPORTER_ASSERT(reporter,
404                            configs[i]->getViaParts()[j].equals(expectedConfigs[i].vias[j]));
405        }
406    }
407#if SK_SUPPORT_GPU
408    REPORTER_ASSERT(reporter, configs[0]->asConfigGpu());
409    REPORTER_ASSERT(reporter, configs[1]->asConfigGpu());
410    REPORTER_ASSERT(reporter, !configs[2]->asConfigGpu());
411    REPORTER_ASSERT(reporter, !configs[3]->asConfigGpu());
412#endif
413}
414