xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLDisplaySelectionTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 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 // EGLDisplaySelectionTest.cpp:
7 //   Checks display selection and caching with EGL extensions EGL_ANGLE_display_power_preference,
8 //   EGL_ANGLE_platform_angle, and EGL_ANGLE_device_id
9 //
10 
11 #include <gtest/gtest.h>
12 
13 #include "common/debug.h"
14 #include "common/string_utils.h"
15 #include "gpu_info_util/SystemInfo.h"
16 #include "test_utils/ANGLETest.h"
17 #include "test_utils/system_info_util.h"
18 #include "util/OSWindow.h"
19 
20 using namespace angle;
21 
22 class EGLDisplaySelectionTest : public ANGLETest<>
23 {
24   public:
testSetUp()25     void testSetUp() override { (void)GetSystemInfo(&mSystemInfo); }
26 
27   protected:
28     // Returns the index of the low or high power GPU in SystemInfo depending on the argument.
findGPU(bool lowPower) const29     int findGPU(bool lowPower) const
30     {
31         if (lowPower)
32             return FindLowPowerGPU(mSystemInfo);
33         return FindHighPowerGPU(mSystemInfo);
34     }
35 
36     // Returns the index of the active GPU in SystemInfo based on the renderer string.
findActiveGPU() const37     int findActiveGPU() const { return FindActiveOpenGLGPU(mSystemInfo); }
38 
39     SystemInfo mSystemInfo;
40 };
41 
42 class EGLDisplaySelectionTestNoFixture : public EGLDisplaySelectionTest
43 {
44   protected:
terminateWindow()45     void terminateWindow()
46     {
47         if (mOSWindow)
48         {
49             OSWindow::Delete(&mOSWindow);
50         }
51     }
52 
terminateDisplay(EGLDisplay display)53     void terminateDisplay(EGLDisplay display)
54     {
55         EXPECT_EGL_TRUE(eglTerminate(display));
56         EXPECT_EGL_SUCCESS();
57     }
58 
terminateContext(EGLDisplay display,EGLContext context)59     void terminateContext(EGLDisplay display, EGLContext context)
60     {
61         if (context != EGL_NO_CONTEXT)
62         {
63             eglDestroyContext(display, context);
64             ASSERT_EGL_SUCCESS();
65         }
66     }
67 
initializeWindow()68     void initializeWindow()
69     {
70         mOSWindow = OSWindow::New();
71         mOSWindow->initialize("EGLDisplaySelectionTestMultiDisplay", kWindowWidth, kWindowHeight);
72         setWindowVisible(mOSWindow, true);
73     }
74 
initializeContextForDisplay(EGLDisplay display,EGLContext * context)75     void initializeContextForDisplay(EGLDisplay display, EGLContext *context)
76     {
77         // Find a default config.
78         const EGLint configAttributes[] = {
79             EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE,     EGL_DONT_CARE,  EGL_GREEN_SIZE,
80             EGL_DONT_CARE,    EGL_BLUE_SIZE,  EGL_DONT_CARE,    EGL_ALPHA_SIZE, EGL_DONT_CARE,
81             EGL_DEPTH_SIZE,   EGL_DONT_CARE,  EGL_STENCIL_SIZE, EGL_DONT_CARE,  EGL_NONE};
82 
83         EGLint configCount;
84         EGLConfig config;
85         EGLint ret = eglChooseConfig(display, configAttributes, &config, 1, &configCount);
86 
87         if (!ret || configCount == 0)
88         {
89             return;
90         }
91 
92         EGLint contextAttributes[] = {
93             EGL_CONTEXT_MAJOR_VERSION_KHR,
94             GetParam().majorVersion,
95             EGL_CONTEXT_MINOR_VERSION_KHR,
96             GetParam().minorVersion,
97             EGL_NONE,
98         };
99 
100         *context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
101         ASSERT_TRUE(*context != EGL_NO_CONTEXT);
102     }
103 
104     static constexpr int kWindowWidth  = 16;
105     static constexpr int kWindowHeight = 8;
106 
107     OSWindow *mOSWindow = nullptr;
108 };
109 
110 class EGLDisplaySelectionTestMultiDisplay : public EGLDisplaySelectionTestNoFixture
111 {
112 
113   protected:
initializeDisplayWithPowerPreference(EGLDisplay * display,EGLAttrib powerPreference)114     void initializeDisplayWithPowerPreference(EGLDisplay *display, EGLAttrib powerPreference)
115     {
116         GLenum platformType = GetParam().getRenderer();
117         GLenum deviceType   = GetParam().getDeviceType();
118 
119         std::vector<EGLint> displayAttributes;
120         displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
121         displayAttributes.push_back(platformType);
122         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
123         displayAttributes.push_back(EGL_DONT_CARE);
124         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
125         displayAttributes.push_back(EGL_DONT_CARE);
126         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
127         displayAttributes.push_back(deviceType);
128         displayAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
129         displayAttributes.push_back(powerPreference);
130         displayAttributes.push_back(EGL_NONE);
131 
132         *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
133                                             reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
134                                             displayAttributes.data());
135         ASSERT_TRUE(*display != EGL_NO_DISPLAY);
136 
137         EGLint majorVersion, minorVersion;
138         ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);
139 
140         eglBindAPI(EGL_OPENGL_ES_API);
141         ASSERT_EGL_SUCCESS();
142     }
143 
initializeDisplayWithBackend(EGLDisplay * display,EGLAttrib platformType)144     void initializeDisplayWithBackend(EGLDisplay *display, EGLAttrib platformType)
145     {
146         GLenum deviceType = GetParam().getDeviceType();
147 
148         std::vector<EGLint> displayAttributes;
149         displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
150         displayAttributes.push_back(platformType);
151         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
152         displayAttributes.push_back(EGL_DONT_CARE);
153         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
154         displayAttributes.push_back(EGL_DONT_CARE);
155         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
156         displayAttributes.push_back(deviceType);
157         displayAttributes.push_back(EGL_NONE);
158 
159         *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
160                                             reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
161                                             displayAttributes.data());
162         ASSERT_TRUE(*display != EGL_NO_DISPLAY);
163 
164         EGLint majorVersion, minorVersion;
165         ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);
166 
167         eglBindAPI(EGL_OPENGL_ES_API);
168         ASSERT_EGL_SUCCESS();
169     }
170 
runReinitializeDisplayPowerPreference(EGLAttrib powerPreference)171     void runReinitializeDisplayPowerPreference(EGLAttrib powerPreference)
172     {
173         initializeWindow();
174 
175         // Initialize the display with the selected power preference
176         EGLDisplay display;
177         EGLContext context;
178         initializeDisplayWithPowerPreference(&display, powerPreference);
179         initializeContextForDisplay(display, &context);
180         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
181 
182         bool lowPower = (powerPreference == EGL_LOW_POWER_ANGLE);
183         ASSERT_EQ(findGPU(lowPower), findActiveGPU());
184 
185         // Terminate the display
186         terminateContext(display, context);
187         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
188         terminateDisplay(display);
189 
190         // Change the power preference
191         if (powerPreference == EGL_LOW_POWER_ANGLE)
192         {
193             powerPreference = EGL_HIGH_POWER_ANGLE;
194         }
195         else
196         {
197             powerPreference = EGL_LOW_POWER_ANGLE;
198         }
199 
200         // Reinitialize the display with a new power preference
201         initializeDisplayWithPowerPreference(&display, powerPreference);
202         initializeContextForDisplay(display, &context);
203         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
204 
205         // Expect that the power preference has changed
206         lowPower = (powerPreference == EGL_LOW_POWER_ANGLE);
207         ASSERT_EQ(findGPU(lowPower), findActiveGPU());
208 
209         // Terminate the display
210         terminateContext(display, context);
211         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
212         terminateDisplay(display);
213 
214         terminateWindow();
215     }
216 
runMultiDisplayBackend(EGLAttrib backend1,bool (checkFunc1)(void),EGLAttrib backend2,bool (checkFunc2)(void))217     void runMultiDisplayBackend(EGLAttrib backend1,
218                                 bool(checkFunc1)(void),
219                                 EGLAttrib backend2,
220                                 bool(checkFunc2)(void))
221     {
222         initializeWindow();
223 
224         // Initialize the display with the selected backend
225         EGLDisplay display1;
226         EGLContext context1;
227         initializeDisplayWithBackend(&display1, backend1);
228         initializeContextForDisplay(display1, &context1);
229         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
230 
231         // Check that the correct backend is chosen
232         ASSERT_TRUE(checkFunc1());
233 
234         // Initialize the second display with the second backend
235         EGLDisplay display2;
236         EGLContext context2;
237         initializeDisplayWithBackend(&display2, backend2);
238         initializeContextForDisplay(display2, &context2);
239         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);
240 
241         // Check that the correct backend is chosen
242         ASSERT_TRUE(checkFunc2());
243 
244         // Switch back to the first display to verify
245         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
246         ASSERT_TRUE(checkFunc1());
247 
248         // Terminate the displays
249         terminateContext(display1, context1);
250         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
251         terminateDisplay(display1);
252         terminateContext(display2, context2);
253         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
254         terminateDisplay(display2);
255 
256         terminateWindow();
257     }
258 
runMultiDisplayBackendDefault(EGLAttrib backend,bool (checkFunc)(void))259     void runMultiDisplayBackendDefault(EGLAttrib backend, bool(checkFunc)(void))
260     {
261         initializeWindow();
262 
263         // Initialize the display with the selected backend
264         EGLDisplay display1;
265         EGLContext context1;
266         initializeDisplayWithBackend(&display1, backend);
267         initializeContextForDisplay(display1, &context1);
268         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
269 
270         // Check that the correct backend is chosen
271         ASSERT_TRUE(checkFunc());
272 
273         // Initialize the second display with the second backend
274         EGLDisplay display2;
275         EGLContext context2;
276         initializeDisplayWithBackend(&display2, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
277         initializeContextForDisplay(display2, &context2);
278         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);
279 
280         bool sameDisplay = false;
281         // If this backend is the same as the first display, check that the display is cached
282         if (checkFunc())
283         {
284             ASSERT_EQ(display1, display2);
285             sameDisplay = true;
286         }
287         // If this backend is not the same, check that this is a different display
288         else
289         {
290             ASSERT_NE(display1, display2);
291         }
292 
293         // Switch back to the first display to verify
294         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
295         ASSERT_TRUE(checkFunc());
296 
297         // Terminate the displays
298         terminateContext(display1, context1);
299         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
300         if (!sameDisplay)
301         {
302             terminateDisplay(display1);
303         }
304         terminateContext(display2, context2);
305         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
306         terminateDisplay(display2);
307 
308         terminateWindow();
309     }
310 
runMultiDisplayPowerPreference()311     void runMultiDisplayPowerPreference()
312     {
313         initializeWindow();
314 
315         // Initialize the first display with low power
316         EGLDisplay display1;
317         EGLContext context1;
318         initializeDisplayWithPowerPreference(&display1, EGL_LOW_POWER_ANGLE);
319         initializeContextForDisplay(display1, &context1);
320         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
321 
322         ASSERT_EQ(findGPU(true), findActiveGPU());
323 
324         // Initialize the second display with high power
325         EGLDisplay display2;
326         EGLContext context2;
327         initializeDisplayWithPowerPreference(&display2, EGL_HIGH_POWER_ANGLE);
328         initializeContextForDisplay(display2, &context2);
329         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, context2);
330 
331         ASSERT_EQ(findGPU(false), findActiveGPU());
332 
333         // Switch back to the first display to verify
334         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, context1);
335         ASSERT_EQ(findGPU(true), findActiveGPU());
336 
337         // Terminate the displays
338         terminateContext(display1, context1);
339         eglMakeCurrent(display1, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
340         terminateDisplay(display1);
341         terminateContext(display2, context2);
342         eglMakeCurrent(display2, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
343         terminateDisplay(display2);
344 
345         terminateWindow();
346     }
347 };
348 
TEST_P(EGLDisplaySelectionTest,SelectGPU)349 TEST_P(EGLDisplaySelectionTest, SelectGPU)
350 {
351     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));
352     ASSERT_NE(GetParam().eglParameters.displayPowerPreference, EGL_DONT_CARE);
353 
354     bool lowPower = (GetParam().eglParameters.displayPowerPreference == EGL_LOW_POWER_ANGLE);
355     ASSERT_EQ(findGPU(lowPower), findActiveGPU());
356 }
357 
TEST_P(EGLDisplaySelectionTestMultiDisplay,ReInitializePowerPreferenceLowToHigh)358 TEST_P(EGLDisplaySelectionTestMultiDisplay, ReInitializePowerPreferenceLowToHigh)
359 {
360     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));
361 
362     runReinitializeDisplayPowerPreference(EGL_LOW_POWER_ANGLE);
363 }
364 
TEST_P(EGLDisplaySelectionTestMultiDisplay,ReInitializePowerPreferenceHighToLow)365 TEST_P(EGLDisplaySelectionTestMultiDisplay, ReInitializePowerPreferenceHighToLow)
366 {
367     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));
368 
369     runReinitializeDisplayPowerPreference(EGL_HIGH_POWER_ANGLE);
370 }
371 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendMetalOpenGL)372 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendMetalOpenGL)
373 {
374     bool missingBackends = true;
375 #if defined(ANGLE_ENABLE_METAL) && defined(ANGLE_ENABLE_OPENGL)
376     missingBackends = false;
377 #endif
378     ANGLE_SKIP_TEST_IF(missingBackends);
379 
380     runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal,
381                            EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL);
382 }
383 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendOpenGLMetal)384 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendOpenGLMetal)
385 {
386     bool missingBackends = true;
387 #if defined(ANGLE_ENABLE_METAL) && defined(ANGLE_ENABLE_OPENGL)
388     missingBackends = false;
389 #endif
390     ANGLE_SKIP_TEST_IF(missingBackends);
391 
392     runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL,
393                            EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal);
394 }
395 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendVulkanD3D11)396 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendVulkanD3D11)
397 {
398     bool missingBackends = true;
399 #if defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_ENABLE_D3D11)
400     missingBackends = false;
401 #endif
402     ANGLE_SKIP_TEST_IF(missingBackends);
403 
404     runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan,
405                            EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11);
406 }
407 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendD3D11Vulkan)408 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendD3D11Vulkan)
409 {
410     bool missingBackends = true;
411 #if defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_ENABLE_D3D11)
412     missingBackends = false;
413 #endif
414     ANGLE_SKIP_TEST_IF(missingBackends);
415 
416     runMultiDisplayBackend(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11,
417                            EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan);
418 }
419 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendDefaultMetal)420 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultMetal)
421 {
422     bool missingBackends = true;
423 #if defined(ANGLE_ENABLE_METAL)
424     missingBackends = false;
425 #endif
426     ANGLE_SKIP_TEST_IF(missingBackends);
427 
428     runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, IsMetal);
429 }
430 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendDefaultOpenGL)431 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultOpenGL)
432 {
433     bool missingBackends = true;
434 #if defined(ANGLE_ENABLE_OPENGL)
435     missingBackends = false;
436 #endif
437     ANGLE_SKIP_TEST_IF(missingBackends);
438 
439     runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, IsOpenGL);
440 }
441 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendDefaultD3D11)442 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultD3D11)
443 {
444     bool missingBackends = true;
445 #if defined(ANGLE_ENABLE_D3D11)
446     missingBackends = false;
447 #endif
448     ANGLE_SKIP_TEST_IF(missingBackends);
449 
450     runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, IsD3D11);
451 }
452 
TEST_P(EGLDisplaySelectionTestMultiDisplay,BackendDefaultVulkan)453 TEST_P(EGLDisplaySelectionTestMultiDisplay, BackendDefaultVulkan)
454 {
455     bool missingBackends = true;
456 #if defined(ANGLE_ENABLE_VULKAN)
457     missingBackends = false;
458 #endif
459     ANGLE_SKIP_TEST_IF(missingBackends);
460 
461     // http://anglebug.com/42265471
462     ANGLE_SKIP_TEST_IF(IsMac());
463 
464     runMultiDisplayBackendDefault(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, IsVulkan);
465 }
466 
TEST_P(EGLDisplaySelectionTestMultiDisplay,PowerPreference)467 TEST_P(EGLDisplaySelectionTestMultiDisplay, PowerPreference)
468 {
469     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference"));
470 
471     runMultiDisplayPowerPreference();
472 }
473 
474 class EGLDisplaySelectionTestDeviceId : public EGLDisplaySelectionTestNoFixture
475 {
476 
477   protected:
initializeDisplayWithDeviceId(EGLDisplay * display,uint64_t deviceId)478     void initializeDisplayWithDeviceId(EGLDisplay *display, uint64_t deviceId)
479     {
480         GLenum platformType          = GetParam().getRenderer();
481         GLenum deviceType            = GetParam().getDeviceType();
482         GLint displayPowerPreference = GetParam().eglParameters.displayPowerPreference;
483 
484         EGLAttrib high = ((deviceId >> 32) & 0xFFFFFFFF);
485         EGLAttrib low  = (deviceId & 0xFFFFFFFF);
486 
487         std::vector<EGLint> displayAttributes;
488         displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
489         displayAttributes.push_back(platformType);
490         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
491         displayAttributes.push_back(EGL_DONT_CARE);
492         displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
493         displayAttributes.push_back(EGL_DONT_CARE);
494         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
495         displayAttributes.push_back(deviceType);
496         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE);
497         displayAttributes.push_back(high);
498         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE);
499         displayAttributes.push_back(low);
500         if (displayPowerPreference != EGL_DONT_CARE)
501         {
502             displayAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
503             displayAttributes.push_back(displayPowerPreference);
504         }
505         displayAttributes.push_back(EGL_NONE);
506 
507         *display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
508                                             reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),
509                                             displayAttributes.data());
510         ASSERT_TRUE(*display != EGL_NO_DISPLAY);
511 
512         EGLint majorVersion, minorVersion;
513         ASSERT_TRUE(eglInitialize(*display, &majorVersion, &minorVersion) == EGL_TRUE);
514 
515         eglBindAPI(EGL_OPENGL_ES_API);
516         ASSERT_EGL_SUCCESS();
517     }
518 };
519 
TEST_P(EGLDisplaySelectionTestDeviceId,DeviceId)520 TEST_P(EGLDisplaySelectionTestDeviceId, DeviceId)
521 {
522     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_device_id"));
523     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference") &&
524                        GetParam().eglParameters.displayPowerPreference != EGL_DONT_CARE);
525 
526     initializeWindow();
527 
528     for (size_t i = 0; i < mSystemInfo.gpus.size(); i++)
529     {
530         // Initialize the display with device id for each GPU
531         EGLDisplay display;
532         EGLContext context;
533         initializeDisplayWithDeviceId(&display, mSystemInfo.gpus[i].systemDeviceId);
534         initializeContextForDisplay(display, &context);
535         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
536 
537         ASSERT_EQ(static_cast<int>(i), findActiveGPU());
538 
539         // Terminate the displays
540         terminateContext(display, context);
541         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
542         terminateDisplay(display);
543     }
544 
545     terminateWindow();
546 }
547 
TEST_P(EGLDisplaySelectionTestDeviceId,DeviceIdConcurrently)548 TEST_P(EGLDisplaySelectionTestDeviceId, DeviceIdConcurrently)
549 {
550     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_device_id"));
551     ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_display_power_preference") &&
552                        GetParam().eglParameters.displayPowerPreference != EGL_DONT_CARE);
553 
554     initializeWindow();
555     struct ContextForDevice
556     {
557         EGLDisplay display{};
558         EGLContext context{};
559     };
560     std::vector<ContextForDevice> contexts(mSystemInfo.gpus.size());
561 
562     for (size_t i = 0; i < contexts.size(); i++)
563     {
564         auto &display = contexts[i].display;
565         auto &context = contexts[i].context;
566         initializeDisplayWithDeviceId(&display, mSystemInfo.gpus[i].systemDeviceId);
567         initializeContextForDisplay(display, &context);
568         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
569         ASSERT_EQ(static_cast<int>(i), findActiveGPU());
570     }
571     for (auto &context : contexts)
572     {
573         // Terminate the displays
574         terminateContext(context.display, context.context);
575         eglMakeCurrent(context.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
576         terminateDisplay(context.display);
577     }
578 
579     terminateWindow();
580 }
581 
582 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTest);
583 ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTest,
584                        WithLowPowerGPU(ES2_METAL()),
585                        WithLowPowerGPU(ES3_METAL()),
586                        WithHighPowerGPU(ES2_METAL()),
587                        WithHighPowerGPU(ES3_METAL()));
588 
589 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestMultiDisplay);
590 ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestMultiDisplay,
591                        WithNoFixture(ES2_METAL()),
592                        WithNoFixture(ES3_METAL()));
593 
594 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDisplaySelectionTestDeviceId);
595 ANGLE_INSTANTIATE_TEST(EGLDisplaySelectionTestDeviceId,
596                        WithNoFixture(ES2_D3D11()),
597                        WithNoFixture(ES3_D3D11()),
598                        WithNoFixture(ES2_METAL()),
599                        WithNoFixture(ES3_METAL()),
600                        WithNoFixture(WithLowPowerGPU(ES2_METAL())),
601                        WithNoFixture(WithLowPowerGPU(ES3_METAL())),
602                        WithNoFixture(WithHighPowerGPU(ES2_METAL())),
603                        WithNoFixture(WithHighPowerGPU(ES3_METAL())));
604