]> source.dussan.org Git - tigervnc.git/commitdiff
Automatically pick a suitable DRI3 render node 1771/head
authorPierre Ossman <ossman@cendio.se>
Thu, 6 Jun 2024 12:51:52 +0000 (14:51 +0200)
committerPierre Ossman <ossman@cendio.se>
Thu, 20 Jun 2024 12:41:48 +0000 (14:41 +0200)
Lay the groundwork for a more intelligent selection of GPU in systems
that have multiple cards. This initial implementation simply picks the
first GPU that we have permission to open.

unix/xserver/hw/vnc/Xvnc.man
unix/xserver/hw/vnc/vncDRI3.c

index 05d34e815c455c75e3aa7a22ac597667fca5b9e9..fadf9d20a4b28204912801a3d54b4b3dc24621d7 100644 (file)
@@ -48,7 +48,8 @@ depth 16 is RGB565 and for depth 24 and 32 is RGB888.
 .TP
 .B \-rendernode \fIpath\fP
 DRM render node to use for DRI3 GPU acceleration. Specify an empty path to
-disable DRI3. Default is /dev/dri/renderD128.
+disable DRI3. Default is \fBauto\fP which makes \fBXvnc\fP pick a suitable
+available render node.
 .
 .TP
 .B \-interface \fIIP address\fP
index 1e643ece560ff2cf5a2589c00e6e31d07f527cc3..79b56f10dd434d7b86f92686bf2bd5bcf06e2286 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <glob.h>
 #include <unistd.h>
 
 #ifdef HAVE_GBM
@@ -37,7 +38,7 @@
 #error "This code is not compatible with accessors"
 #endif
 
-const char *renderNode = "/dev/dri/renderD128";
+const char *renderNode = "auto";
 
 static DevPrivateKeyRec vncDRI3ScreenPrivateKey;
 static DevPrivateKeyRec vncDRI3PixmapPrivateKey;
@@ -458,7 +459,8 @@ Bool vncDRI3Init(ScreenPtr screen)
   if (renderNode[0] == '\0')
     return TRUE;
 
-  if (renderNode[0] != '/') {
+  if ((renderNode[0] != '/') &&
+      (strcasecmp(renderNode, "auto") != 0)) {
     ErrorF("Invalid render node path \"%s\"\n", renderNode);
     return FALSE;
   }
@@ -476,7 +478,37 @@ Bool vncDRI3Init(ScreenPtr screen)
 #ifdef HAVE_GBM
   screenPriv = vncDRI3ScreenPrivate(screen);
 
-  screenPriv->devicePath = renderNode;
+  if (strcasecmp(renderNode, "auto") == 0) {
+    glob_t globbuf;
+    int ret;
+
+    ret = glob("/dev/dri/renderD*", 0, NULL, &globbuf);
+    if (ret == GLOB_NOMATCH) {
+      ErrorF("Could not find any render nodes\n");
+      return FALSE;
+    }
+    if (ret != 0) {
+      ErrorF("Failure enumerating render nodes\n");
+      return FALSE;
+    }
+
+    screenPriv->devicePath = NULL;
+    for (size_t i = 0;i < globbuf.gl_pathc;i++) {
+      if (access(globbuf.gl_pathv[i], R_OK|W_OK) == 0) {
+        screenPriv->devicePath = strdup(globbuf.gl_pathv[i]);
+        break;
+      }
+    }
+
+    globfree(&globbuf);
+
+    if (screenPriv->devicePath == NULL) {
+      ErrorF("Could not find any available render nodes\n");
+      return FALSE;
+    }
+  } else {
+    screenPriv->devicePath = renderNode;
+  }
 
   screenPriv->fd = open(screenPriv->devicePath, O_RDWR|O_CLOEXEC);
   if (screenPriv->fd < 0) {