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