• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // angle_test_instantiate.cpp: Adds support for filtering parameterized
8 // tests by platform, so we skip unsupported configs.
9 
10 #include "test_utils/angle_test_instantiate.h"
11 
12 #include <algorithm>
13 #include <array>
14 #include <iostream>
15 #include <map>
16 
17 #include "angle_gl.h"
18 #include "common/debug.h"
19 #include "common/platform.h"
20 #include "common/system_utils.h"
21 #include "common/third_party/base/anglebase/no_destructor.h"
22 #include "gpu_info_util/SystemInfo.h"
23 #include "test_utils/angle_test_configs.h"
24 #include "util/EGLWindow.h"
25 #include "util/OSWindow.h"
26 #include "util/test_utils.h"
27 
28 #if defined(ANGLE_PLATFORM_WINDOWS)
29 #    include <VersionHelpers.h>
30 #    include "util/windows/WGLWindow.h"
31 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
32 
33 #if defined(ANGLE_PLATFORM_APPLE)
34 #    include "test_utils/angle_test_instantiate_apple.h"
35 #endif
36 
37 namespace angle
38 {
39 namespace
40 {
IsAngleEGLConfigSupported(const PlatformParameters & param,OSWindow * osWindow)41 bool IsAngleEGLConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
42 {
43     std::unique_ptr<angle::Library> eglLibrary;
44 
45 #if defined(ANGLE_USE_UTIL_LOADER)
46     eglLibrary.reset(
47         angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir));
48 #endif
49 
50     EGLWindow *eglWindow = EGLWindow::New(param.majorVersion, param.minorVersion);
51     ConfigParameters configParams;
52     bool result =
53         eglWindow->initializeGL(osWindow, eglLibrary.get(), angle::GLESDriverType::AngleEGL,
54                                 param.eglParameters, configParams);
55     eglWindow->destroyGL();
56     EGLWindow::Delete(&eglWindow);
57     return result;
58 }
59 
IsSystemWGLConfigSupported(const PlatformParameters & param,OSWindow * osWindow)60 bool IsSystemWGLConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
61 {
62 #if defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER)
63     std::unique_ptr<angle::Library> openglLibrary(
64         angle::OpenSharedLibrary("opengl32", angle::SearchType::SystemDir));
65 
66     WGLWindow *wglWindow = WGLWindow::New(param.majorVersion, param.minorVersion);
67     ConfigParameters configParams;
68     bool result =
69         wglWindow->initializeGL(osWindow, openglLibrary.get(), angle::GLESDriverType::SystemWGL,
70                                 param.eglParameters, configParams);
71     wglWindow->destroyGL();
72     WGLWindow::Delete(&wglWindow);
73     return result;
74 #else
75     return false;
76 #endif  // defined(ANGLE_PLATFORM_WINDOWS) && defined(ANGLE_USE_UTIL_LOADER)
77 }
78 
IsSystemEGLConfigSupported(const PlatformParameters & param,OSWindow * osWindow)79 bool IsSystemEGLConfigSupported(const PlatformParameters &param, OSWindow *osWindow)
80 {
81 #if defined(ANGLE_USE_UTIL_LOADER)
82     std::unique_ptr<angle::Library> eglLibrary;
83 
84     eglLibrary.reset(OpenSharedLibraryWithExtension(GetNativeEGLLibraryNameWithExtension(),
85                                                     SearchType::SystemDir));
86 
87     EGLWindow *eglWindow = EGLWindow::New(param.majorVersion, param.minorVersion);
88     ConfigParameters configParams;
89     bool result =
90         eglWindow->initializeGL(osWindow, eglLibrary.get(), angle::GLESDriverType::SystemEGL,
91                                 param.eglParameters, configParams);
92     eglWindow->destroyGL();
93     EGLWindow::Delete(&eglWindow);
94     return result;
95 #else
96     return false;
97 #endif
98 }
99 
IsAndroidDevice(const std::string & deviceName)100 bool IsAndroidDevice(const std::string &deviceName)
101 {
102     if (!IsAndroid())
103     {
104         return false;
105     }
106     SystemInfo *systemInfo = GetTestSystemInfo();
107     if (systemInfo->machineModelName == deviceName)
108     {
109         return true;
110     }
111     return false;
112 }
113 
IsAndroid9OrNewer()114 bool IsAndroid9OrNewer()
115 {
116     if (!IsAndroid())
117     {
118         return false;
119     }
120     SystemInfo *systemInfo = GetTestSystemInfo();
121     if (systemInfo->androidSdkLevel >= 28)
122     {
123         return true;
124     }
125     return false;
126 }
127 
GetActiveGPUDeviceInfo()128 GPUDeviceInfo *GetActiveGPUDeviceInfo()
129 {
130     SystemInfo *systemInfo = GetTestSystemInfo();
131     // Unfortunately sometimes GPU info collection can fail.
132     if (systemInfo->gpus.empty())
133     {
134         return nullptr;
135     }
136     return &systemInfo->gpus[systemInfo->activeGPUIndex];
137 }
138 
HasSystemVendorID(VendorID vendorID)139 bool HasSystemVendorID(VendorID vendorID)
140 {
141     GPUDeviceInfo *gpuInfo = GetActiveGPUDeviceInfo();
142 
143     return gpuInfo && gpuInfo->vendorId == vendorID;
144 }
145 
HasSystemDeviceID(VendorID vendorID,DeviceID deviceID)146 bool HasSystemDeviceID(VendorID vendorID, DeviceID deviceID)
147 {
148     GPUDeviceInfo *gpuInfo = GetActiveGPUDeviceInfo();
149 
150     return gpuInfo && gpuInfo->vendorId == vendorID && gpuInfo->deviceId == deviceID;
151 }
152 
153 using ParamAvailabilityCache = std::map<PlatformParameters, bool>;
154 
GetAvailabilityCache()155 ParamAvailabilityCache &GetAvailabilityCache()
156 {
157     static angle::base::NoDestructor<std::unique_ptr<ParamAvailabilityCache>>
158         sParamAvailabilityCache(new ParamAvailabilityCache());
159     return **sParamAvailabilityCache;
160 }
161 
162 constexpr size_t kMaxConfigNameLen = 100;
163 std::array<char, kMaxConfigNameLen> gSelectedConfig;
164 }  // namespace
165 
166 bool gEnableANGLEPerTestCaptureLabel = false;
167 
IsConfigSelected()168 bool IsConfigSelected()
169 {
170     return gSelectedConfig[0] != 0;
171 }
172 
173 #if !defined(ANGLE_PLATFORM_APPLE)
174 // For Apple platform, see angle_test_instantiate_apple.mm
IsMetalTextureSwizzleAvailable()175 bool IsMetalTextureSwizzleAvailable()
176 {
177     return false;
178 }
179 #endif
180 
GetTestSystemInfo()181 SystemInfo *GetTestSystemInfo()
182 {
183     static SystemInfo *sSystemInfo = nullptr;
184     if (sSystemInfo == nullptr)
185     {
186         sSystemInfo = new SystemInfo;
187         if (!GetSystemInfo(sSystemInfo))
188         {
189             std::cerr << "Warning: incomplete system info collection.\n";
190         }
191 
192         // On dual-GPU Macs we want the active GPU to always appear to be the
193         // high-performance GPU for tests.
194         // We can call the generic GPU info collector which selects the
195         // non-Intel GPU as the active one on dual-GPU machines.
196         if (IsOSX())
197         {
198             GetDualGPUInfo(sSystemInfo);
199         }
200 
201         // Print complete system info when available.
202         // Seems to trip up Android test expectation parsing.
203         // Also don't print info when a config is selected to prevent test spam.
204         if (!IsAndroid() && !IsConfigSelected())
205         {
206             PrintSystemInfo(*sSystemInfo);
207         }
208     }
209     return sSystemInfo;
210 }
211 
IsAndroid()212 bool IsAndroid()
213 {
214 #if defined(ANGLE_PLATFORM_ANDROID)
215     return true;
216 #else
217     return false;
218 #endif
219 }
220 
IsLinux()221 bool IsLinux()
222 {
223 #if defined(ANGLE_PLATFORM_LINUX)
224     return true;
225 #else
226     return false;
227 #endif
228 }
229 
IsOSX()230 bool IsOSX()
231 {
232 #if defined(ANGLE_PLATFORM_MACOS)
233     return true;
234 #else
235     return false;
236 #endif
237 }
238 
IsIOS()239 bool IsIOS()
240 {
241 #if defined(ANGLE_PLATFORM_IOS)
242     return true;
243 #else
244     return false;
245 #endif
246 }
247 
IsARM64()248 bool IsARM64()
249 {
250 // _M_ARM64 is Windows-specific, while __aarch64__ is for other platforms.
251 #if defined(_M_ARM64) || defined(__aarch64__)
252     return true;
253 #else
254     return false;
255 #endif
256 }
257 
IsOzone()258 bool IsOzone()
259 {
260 #if defined(USE_OZONE) && (defined(USE_X11) || defined(ANGLE_USE_VULKAN_DISPLAY))
261     // We do not have a proper support for Ozone/Linux yet. Still, we need to figure out how to
262     // properly initialize tests and differentiate between X11 and Wayland. Probably, passing a
263     // command line argument could be sufficient. At the moment, run tests only for X11 backend
264     // as we don't have Wayland support in Angle. Yes, this is a bit weird to return false, but
265     // it makes it possible to continue angle tests with X11 regardless of the Chromium config
266     // for linux, which is use_x11 && use_ozone.  Also, IsOzone is a bit vague now. It was only
267     // expected that angle could run with ozone/drm backend for ChromeOS. And returning true
268     // for desktop Linux when USE_OZONE && USE_X11 are both defined results in incorrect tests'
269     // expectations. We should also rework them and make IsOzone less vague.
270     //
271     // TODO(crbug.com/angleproject/4977): make it possible to switch between X11 and Wayland on
272     // Ozone/Linux builds. Probably, it's possible to identify the WAYLAND backend by checking
273     // the WAYLAND_DISPLAY or XDG_SESSION_TYPE env vars. And also make the IsOzone method less
274     // vague (read the comment above).
275     return false;
276 #elif defined(USE_OZONE)
277     return true;
278 #else
279     return false;
280 #endif
281 }
282 
IsWindows()283 bool IsWindows()
284 {
285 #if defined(ANGLE_PLATFORM_WINDOWS)
286     return true;
287 #else
288     return false;
289 #endif
290 }
291 
IsWindows7()292 bool IsWindows7()
293 {
294 #if defined(ANGLE_PLATFORM_WINDOWS)
295     return ::IsWindows7OrGreater() && !::IsWindows8OrGreater();
296 #else
297     return false;
298 #endif
299 }
300 
IsFuchsia()301 bool IsFuchsia()
302 {
303 #if defined(ANGLE_PLATFORM_FUCHSIA)
304     return true;
305 #else
306     return false;
307 #endif
308 }
309 
IsNexus5X()310 bool IsNexus5X()
311 {
312     return IsAndroidDevice("Nexus 5X");
313 }
314 
IsNexus9()315 bool IsNexus9()
316 {
317     return IsAndroidDevice("Nexus 9");
318 }
319 
IsPixelXL()320 bool IsPixelXL()
321 {
322     return IsAndroidDevice("Pixel XL");
323 }
324 
IsPixel2()325 bool IsPixel2()
326 {
327     return IsAndroidDevice("Pixel 2");
328 }
329 
IsPixel2XL()330 bool IsPixel2XL()
331 {
332     return IsAndroidDevice("Pixel 2 XL");
333 }
334 
IsPixel4()335 bool IsPixel4()
336 {
337     return IsAndroidDevice("Pixel 4");
338 }
339 
IsNVIDIAShield()340 bool IsNVIDIAShield()
341 {
342     return IsAndroidDevice("SHIELD Android TV");
343 }
344 
IsIntel()345 bool IsIntel()
346 {
347     return HasSystemVendorID(kVendorID_Intel);
348 }
349 
IsIntelUHD630Mobile()350 bool IsIntelUHD630Mobile()
351 {
352     return HasSystemDeviceID(kVendorID_Intel, kDeviceID_UHD630Mobile);
353 }
354 
IsAMD()355 bool IsAMD()
356 {
357     return HasSystemVendorID(kVendorID_AMD);
358 }
359 
IsARM()360 bool IsARM()
361 {
362     return HasSystemVendorID(kVendorID_ARM);
363 }
364 
IsSwiftshaderDevice()365 bool IsSwiftshaderDevice()
366 {
367     return HasSystemDeviceID(kVendorID_GOOGLE, kDeviceID_Swiftshader);
368 }
369 
IsNVIDIA()370 bool IsNVIDIA()
371 {
372 #if defined(ANGLE_PLATFORM_ANDROID)
373     // NVIDIA Shield cannot detect vendor ID (http://anglebug.com/3541)
374     if (IsNVIDIAShield())
375     {
376         return true;
377     }
378 #endif
379     return HasSystemVendorID(kVendorID_NVIDIA);
380 }
381 
IsQualcomm()382 bool IsQualcomm()
383 {
384     return IsNexus5X() || IsNexus9() || IsPixelXL() || IsPixel2() || IsPixel2XL();
385 }
386 
IsConfigAllowlisted(const SystemInfo & systemInfo,const PlatformParameters & param)387 bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters &param)
388 {
389     VendorID vendorID =
390         systemInfo.gpus.empty() ? 0 : systemInfo.gpus[systemInfo.activeGPUIndex].vendorId;
391 
392     // We support the default and null back-ends on every platform.
393     if (param.driver == GLESDriverType::AngleEGL)
394     {
395         if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
396             return true;
397         if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE)
398             return true;
399     }
400 
401     // TODO: http://crbug.com/swiftshader/145
402     // Swiftshader does not currently have all the robustness features
403     // we need for ANGLE. In particular, it is unable to detect and recover
404     // from infinitely looping shaders. That bug is the tracker for fixing
405     // that and when resolved we can remove the following code.
406     // This test will disable tests marked with the config WithRobustness
407     // when run with the swiftshader Vulkan driver and on Android.
408     if ((param.isSwiftshader() || IsSwiftshaderDevice()) &&
409         param.eglParameters.robustness == EGL_TRUE)
410     {
411         return false;
412     }
413 
414     if (IsWindows())
415     {
416         switch (param.driver)
417         {
418             case GLESDriverType::AngleEGL:
419                 switch (param.getRenderer())
420                 {
421                     case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
422                     case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
423                         return true;
424                     case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
425                         // Note we disable AMD OpenGL testing on Windows due to using a very old and
426                         // outdated card with many driver bugs. See http://anglebug.com/5123
427                         return !IsAMD();
428                     case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
429                         if (IsARM64())
430                         {
431                             return param.getDeviceType() ==
432                                    EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
433                         }
434                         return true;
435                     case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
436                         // ES 3.1+ back-end is not supported properly.
437                         if (param.eglParameters.majorVersion == 3 &&
438                             param.eglParameters.minorVersion > 0)
439                         {
440                             return false;
441                         }
442 
443                         // Win ES emulation is currently only supported on NVIDIA.
444                         return IsNVIDIA(vendorID);
445                     default:
446                         return false;
447                 }
448             case GLESDriverType::SystemWGL:
449                 // AMD does not support the ES compatibility extensions.
450                 return !IsAMD(vendorID);
451             default:
452                 return false;
453         }
454     }
455 
456 #if defined(ANGLE_PLATFORM_APPLE)
457     if (IsOSX() || IsIOS())
458     {
459         // We do not support non-ANGLE bindings on OSX.
460         if (param.driver != GLESDriverType::AngleEGL)
461         {
462             return false;
463         }
464 
465         switch (param.getRenderer())
466         {
467             case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
468                 // ES 3.1+ back-end is not supported properly.
469                 if (param.majorVersion == 3 && param.minorVersion > 0)
470                 {
471                     return false;
472                 }
473                 return true;
474             case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
475                 if (!IsMetalRendererAvailable())
476                 {
477                     return false;
478                 }
479                 return true;
480             case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
481                 // OSX does not support native vulkan
482                 return param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
483             default:
484                 return false;
485         }
486     }
487 #endif  // #if defined(ANGLE_PLATFORM_APPLE)
488 
489     if (IsFuchsia())
490     {
491         // We do not support non-ANGLE bindings on Fuchsia.
492         if (param.driver != GLESDriverType::AngleEGL)
493         {
494             return false;
495         }
496 
497         // ES 3 configs do not work properly on Fuchsia ARM.
498         // TODO(anglebug.com/4352): Investigate missing features.
499         if (param.majorVersion > 2 && IsARM())
500             return false;
501 
502         // Loading swiftshader is not brought up on Fuchsia.
503         // TODO(anglebug.com/4353): Support loading swiftshader vulkan ICD.
504         if (param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE)
505             return false;
506 
507         // Currently we only support the Vulkan back-end on Fuchsia.
508         return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
509     }
510 
511     if (IsOzone())
512     {
513         // We do not support non-ANGLE bindings on Ozone.
514         if (param.driver != GLESDriverType::AngleEGL)
515             return false;
516 
517         // ES 3 configs do not work properly on Ozone.
518         if (param.majorVersion > 2)
519             return false;
520 
521         // Currently we only support the GLES back-end on Ozone.
522         return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE);
523     }
524 
525     if (IsLinux() || IsAndroid())
526     {
527         // We do not support WGL bindings on Linux/Android. We do support system EGL.
528         switch (param.driver)
529         {
530             case GLESDriverType::SystemEGL:
531                 return param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
532             case GLESDriverType::SystemWGL:
533                 return false;
534             default:
535                 break;
536         }
537     }
538 
539     if (IsLinux())
540     {
541         ASSERT(param.driver == GLESDriverType::AngleEGL);
542 
543         // Currently we support the OpenGL and Vulkan back-ends on Linux.
544         switch (param.getRenderer())
545         {
546             case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
547                 return true;
548             case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
549                 // http://issuetracker.google.com/173004081
550                 return !IsIntel() || param.eglParameters.asyncCommandQueueFeatureVulkan != EGL_TRUE;
551             default:
552                 return false;
553         }
554     }
555 
556     if (IsAndroid())
557     {
558         ASSERT(param.driver == GLESDriverType::AngleEGL);
559 
560         // Nexus Android devices don't support backing 3.2 contexts
561         if (param.eglParameters.majorVersion == 3 && param.eglParameters.minorVersion == 2)
562         {
563             if (IsNexus5X())
564             {
565                 return false;
566             }
567         }
568 
569         // Currently we support the GLES and Vulkan back-ends on Android.
570         switch (param.getRenderer())
571         {
572             case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
573                 return true;
574             case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
575                 // Swiftshader's vulkan frontend doesn't build on Android.
576                 if (param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE)
577                 {
578                     return false;
579                 }
580                 if (!IsAndroid9OrNewer())
581                 {
582                     return false;
583                 }
584                 if (param.eglParameters.supportsVulkanViewportFlip == EGL_FALSE)
585                 {
586                     return false;
587                 }
588                 return true;
589             default:
590                 return false;
591         }
592     }
593 
594     // Unknown platform.
595     return false;
596 }
597 
IsConfigSupported(const PlatformParameters & param)598 bool IsConfigSupported(const PlatformParameters &param)
599 {
600     OSWindow *osWindow = OSWindow::New();
601     bool result        = false;
602     if (osWindow->initialize("CONFIG_TESTER", 1, 1))
603     {
604         switch (param.driver)
605         {
606             case GLESDriverType::AngleEGL:
607                 result = IsAngleEGLConfigSupported(param, osWindow);
608                 break;
609             case GLESDriverType::SystemEGL:
610                 result = IsSystemEGLConfigSupported(param, osWindow);
611                 break;
612             case GLESDriverType::SystemWGL:
613                 result = IsSystemWGLConfigSupported(param, osWindow);
614                 break;
615         }
616 
617         osWindow->destroy();
618     }
619 
620     OSWindow::Delete(&osWindow);
621     return result;
622 }
623 
IsPlatformAvailable(const PlatformParameters & param)624 bool IsPlatformAvailable(const PlatformParameters &param)
625 {
626     // Disable "null" device when not on ANGLE or in D3D9.
627     if (param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
628     {
629         if (param.driver != GLESDriverType::AngleEGL)
630             return false;
631         if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
632             return false;
633     }
634 
635     switch (param.getRenderer())
636     {
637         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
638             break;
639 
640         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
641 #if !defined(ANGLE_ENABLE_D3D9)
642             return false;
643 #else
644             break;
645 #endif
646 
647         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
648 #if !defined(ANGLE_ENABLE_D3D11)
649             return false;
650 #else
651             break;
652 #endif
653 
654         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
655         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
656 #if !defined(ANGLE_ENABLE_OPENGL)
657             return false;
658 #else
659             break;
660 #endif
661 
662         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
663 #if !defined(ANGLE_ENABLE_VULKAN)
664             return false;
665 #else
666             break;
667 #endif
668 
669         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
670 #if !defined(ANGLE_ENABLE_METAL)
671             return false;
672 #else
673             break;
674 #endif
675 
676         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
677 #ifndef ANGLE_ENABLE_NULL
678             return false;
679 #endif
680             break;
681 
682         default:
683             std::cout << "Unknown test platform: " << param << std::endl;
684             return false;
685     }
686 
687     bool result = false;
688 
689     auto iter = GetAvailabilityCache().find(param);
690     if (iter != GetAvailabilityCache().end())
691     {
692         result = iter->second;
693     }
694     else
695     {
696         if (IsConfigSelected())
697         {
698             std::stringstream strstr;
699             strstr << param;
700             if (strstr.str() == std::string(gSelectedConfig.data()))
701             {
702                 result = true;
703             }
704         }
705         else
706         {
707             const SystemInfo *systemInfo = GetTestSystemInfo();
708 
709             if (systemInfo)
710             {
711                 result = IsConfigAllowlisted(*systemInfo, param);
712             }
713             else
714             {
715                 result = IsConfigSupported(param);
716             }
717         }
718 
719         GetAvailabilityCache()[param] = result;
720 
721         // Enable this unconditionally to print available platforms.
722         if (IsConfigSelected())
723         {
724             if (result)
725             {
726                 std::cout << "Test Config: " << param << "\n";
727             }
728         }
729         else if (!result)
730         {
731             std::cout << "Skipping tests using configuration " << param
732                       << " because it is not available.\n";
733         }
734     }
735     return result;
736 }
737 
GetAvailableTestPlatformNames()738 std::vector<std::string> GetAvailableTestPlatformNames()
739 {
740     std::vector<std::string> platformNames;
741 
742     for (const auto &iter : GetAvailabilityCache())
743     {
744         if (iter.second)
745         {
746             std::stringstream strstr;
747             strstr << iter.first;
748             platformNames.push_back(strstr.str());
749         }
750     }
751 
752     // Keep the list sorted.
753     std::sort(platformNames.begin(), platformNames.end());
754 
755     return platformNames;
756 }
757 
SetSelectedConfig(const char * selectedConfig)758 void SetSelectedConfig(const char *selectedConfig)
759 {
760     gSelectedConfig.fill(0);
761     strncpy(gSelectedConfig.data(), selectedConfig, kMaxConfigNameLen - 1);
762 }
763 }  // namespace angle
764