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