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