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