From f673e2bf688173bb9069bcb13aac5b70330d561c Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 16 Jul 2024 15:55:24 -0400 Subject: [PATCH] winsys/radeon: switch to rendernode when card node doesn't work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit initializing the winsys from a /dev/dri/cardX node (as discovered by gbm) doesn't work, as the kernel abi expects a render node thus, the winsys needs to open the card's rendernode and use that everywhere except when importing buffers, where it has to explicitly export from the card node and import to the rendernode Acked-by: Daniel Stone Reviewed-by: Marek Olšák Part-of: --- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 11 ++++++++++- src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 13 +++++++++++++ src/gallium/winsys/radeon/drm/radeon_drm_winsys.h | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index 94e8e8b6c43..7f4b9a3f1b6 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -1179,7 +1179,16 @@ static struct pb_buffer_lean *radeon_winsys_bo_from_handle(struct radeon_winsys bo = util_hash_table_get(ws->bo_names, (void*)(uintptr_t)whandle->handle); } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) { /* We must first get the GEM handle, as fds are unreliable keys */ - r = drmPrimeFDToHandle(ws->fd, whandle->handle, &handle); + if (ws->rendernode_fd != -1) { + int handle2; + r = drmPrimeHandleToFD(ws->rendernode_fd, whandle->handle, DRM_CLOEXEC, &handle2); + if (r) + goto fail; + r = drmPrimeFDToHandle(ws->fd, handle2, &handle); + close(handle2); + } else { + r = drmPrimeFDToHandle(ws->fd, whandle->handle, &handle); + } if (r) goto fail; bo = util_hash_table_get(ws->bo_handles, (void*)(uintptr_t)handle); diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index db0a1781cad..8a8764d2759 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -96,6 +96,14 @@ static bool radeon_get_drm_value(struct radeon_drm_winsys *ws, unsigned request, retval = drmCommandWriteRead(radeon_drm_winsys_fd(ws), DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { + /* try switching over to a render node */ + if (retval == -EACCES && ws->rendernode_fd == -1) { + ws->rendernode_fd = open(drmGetRenderDeviceNameFromFd(ws->fd), O_RDWR); + if (ws->rendernode_fd != -1) + return radeon_get_drm_value(ws, request, errname, out); + } + } + if (retval && ws->rendernode_fd == -1) { if (errname) { fprintf(stderr, "radeon: Failed to get %s, error number %d\n", errname, retval); @@ -676,6 +684,8 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) if (ws->fd >= 0) close(ws->fd); + if (ws->rendernode_fd >= 0) + close(ws->rendernode_fd); FREE(rws); } @@ -883,6 +893,7 @@ radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, } ws->fd = os_dupfd_cloexec(fd); + ws->rendernode_fd = -1; if (!do_winsys_init(ws)) goto fail1; @@ -1005,6 +1016,8 @@ fail1: radeon_surface_manager_free(ws->surf_man); if (ws->fd >= 0) close(ws->fd); + if (ws->rendernode_fd >= 0) + close(ws->rendernode_fd); FREE(ws); return NULL; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index 9ef84a07f21..b12343e1b7c 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -93,7 +93,7 @@ static inline struct radeon_drm_winsys *radeon_drm_winsys(struct radeon_winsys * ALWAYS_INLINE static int radeon_drm_winsys_fd(const struct radeon_drm_winsys *ws) { - return ws->fd; + return ws->rendernode_fd == -1 ? ws->fd : ws->rendernode_fd; } uint32_t radeon_drm_get_gpu_reset_counter(struct radeon_drm_winsys *ws);