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 ¶m,
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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m, 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 ¶m)
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 ¶m)
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 ¶m)
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