From 29c25a541c8a8d642766e63aba12d263843c6de4 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 17 May 2022 11:52:19 +0200 Subject: [PATCH] egl: Add egl-device-index config var for selecting EGL device Fixes #1306 --- panda/src/egldisplay/eglGraphicsPipe.cxx | 113 +++++++++++++++++------ 1 file changed, 83 insertions(+), 30 deletions(-) diff --git a/panda/src/egldisplay/eglGraphicsPipe.cxx b/panda/src/egldisplay/eglGraphicsPipe.cxx index a75aec5170..6d4a58adc5 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.cxx +++ b/panda/src/egldisplay/eglGraphicsPipe.cxx @@ -21,6 +21,12 @@ #include +static ConfigVariableInt egl_device_index +("egl-device-index", -1, + PRC_DESC("Selects which EGL device index is used to create the EGL display in " + "a headless configuration. The special value -1 selects the default " + "device.")); + TypeHandle eglGraphicsPipe::_type_handle; /** @@ -30,6 +36,8 @@ eglGraphicsPipe:: eglGraphicsPipe() { // Check for client extensions. vector_string extensions; + bool supports_platform_device = false; + bool supports_device_enumeration = false; const char *ext_ptr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (ext_ptr != nullptr) { extract_words(ext_ptr, extensions); @@ -42,6 +50,13 @@ eglGraphicsPipe() { out << " " << extension << "\n"; } } + + if (std::find(extensions.begin(), extensions.end(), "EGL_EXT_platform_device") != extensions.end()) { + supports_platform_device = true; + } + if (std::find(extensions.begin(), extensions.end(), "EGL_EXT_device_enumeration") != extensions.end()) { + supports_device_enumeration = true; + } } else if (egldisplay_cat.is_debug()) { eglGetError(); @@ -51,23 +66,10 @@ eglGraphicsPipe() { EGLint major, minor; - //NB. if the X11 display failed to open, _display will be 0, which is a valid - // input to eglGetDisplay - it means to open the default display. -#ifdef USE_X11 - _egl_display = eglGetDisplay((NativeDisplayType) _display); -#else - _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); -#endif - if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) { - egldisplay_cat.warning() - << "Couldn't initialize the default EGL display: " - << get_egl_error_string(eglGetError()) << "\n"; - _egl_display = EGL_NO_DISPLAY; - } - - if (!_egl_display && - std::find(extensions.begin(), extensions.end(), "EGL_EXT_platform_device") != extensions.end() && - std::find(extensions.begin(), extensions.end(), "EGL_EXT_device_enumeration") != extensions.end()) { + int index = egl_device_index.get_value(); + if (index >= 0 && supports_platform_device && supports_device_enumeration) { + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = + (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT"); @@ -79,23 +81,74 @@ eglGraphicsPipe() { EGLDeviceEXT *devices = (EGLDeviceEXT *)alloca(sizeof(EGLDeviceEXT) * num_devices); eglQueryDevicesEXT(num_devices, devices, &num_devices); - if (egldisplay_cat.is_debug()) { - egldisplay_cat.debug() - << "Found " << num_devices << " EGL devices.\n"; + if (index >= num_devices) { + egldisplay_cat.error() + << "Requested EGL device index " << index << " does not exist (" + << "there are only " << num_devices << " devices)\n"; + _is_valid = false; + return; } - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = - (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); + if (egldisplay_cat.is_debug()) { + egldisplay_cat.debug() + << "Found " << num_devices << " EGL devices, using device index " + << index << ".\n"; + } - if (eglGetPlatformDisplayEXT != nullptr) { - for (EGLint i = 0; i < num_devices && !_egl_display; ++i) { - _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[i], nullptr); + _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[index], nullptr); - if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) { - egldisplay_cat.warning() - << "Couldn't initialize EGL platform display " << i << ": " - << get_egl_error_string(eglGetError()) << "\n"; - _egl_display = EGL_NO_DISPLAY; + if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) { + egldisplay_cat.error() + << "Couldn't initialize EGL platform display " << index << ": " + << get_egl_error_string(eglGetError()) << "\n"; + _egl_display = EGL_NO_DISPLAY; + } + } + } + else { + //NB. if the X11 display failed to open, _display will be 0, which is a valid + // input to eglGetDisplay - it means to open the default display. + #ifdef USE_X11 + _egl_display = eglGetDisplay((NativeDisplayType) _display); + #else + _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + #endif + if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) { + egldisplay_cat.warning() + << "Couldn't initialize the default EGL display: " + << get_egl_error_string(eglGetError()) << "\n"; + _egl_display = EGL_NO_DISPLAY; + } + + if (!_egl_display && supports_platform_device && supports_device_enumeration) { + PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = + (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT"); + + EGLint num_devices = 0; + if (eglQueryDevicesEXT != nullptr && + eglQueryDevicesEXT(0, nullptr, &num_devices) && + num_devices > 0) { + EGLDeviceEXT *devices = (EGLDeviceEXT *)alloca(sizeof(EGLDeviceEXT) * num_devices); + eglQueryDevicesEXT(num_devices, devices, &num_devices); + + if (egldisplay_cat.is_debug()) { + egldisplay_cat.debug() + << "Found " << num_devices << " EGL devices.\n"; + } + + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = + (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); + + if (eglGetPlatformDisplayEXT != nullptr) { + for (EGLint i = 0; i < num_devices && !_egl_display; ++i) { + _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[i], nullptr); + + if (_egl_display && !eglInitialize(_egl_display, &major, &minor)) { + egldisplay_cat.warning() + << "Couldn't initialize EGL platform display " << i << ": " + << get_egl_error_string(eglGetError()) << "\n"; + _egl_display = EGL_NO_DISPLAY; + } } } }