Forráskód Böngészése

egl: Add egl-device-index config var for selecting EGL device

Fixes #1306
rdb 3 éve
szülő
commit
29c25a541c
1 módosított fájl, 81 hozzáadás és 28 törlés
  1. 81 28
      panda/src/egldisplay/eglGraphicsPipe.cxx

+ 81 - 28
panda/src/egldisplay/eglGraphicsPipe.cxx

@@ -21,6 +21,12 @@
 
 #include <EGL/eglext.h>
 
+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 (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;
+      }
+
       if (egldisplay_cat.is_debug()) {
         egldisplay_cat.debug()
-          << "Found " << num_devices << " EGL devices.\n";
+          << "Found " << num_devices << " EGL devices, using device index "
+          << index << ".\n";
       }
 
-      PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
-        (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
+      _egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devices[index], nullptr);
+
+      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 (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;
+            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;
+            }
           }
         }
       }