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