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