Skip to content

Commit

Permalink
Automatically pick a suitable DRI3 render node
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
CendioOssman committed Jun 19, 2024
1 parent deea617 commit 54e4e8f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
3 changes: 2 additions & 1 deletion unix/xserver/hw/vnc/Xvnc.man
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
38 changes: 35 additions & 3 deletions unix/xserver/hw/vnc/vncDRI3.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <unistd.h>

#ifdef HAVE_GBM
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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) {
Expand Down

0 comments on commit 54e4e8f

Please sign in to comment.