From 2926a1aa76d4008bbb53f7a0ed9cb497b4923f01 Mon Sep 17 00:00:00 2001 From: Feng Jiang Date: Fri, 27 May 2022 16:24:11 +0800 Subject: [PATCH] virgl: do not share virgl_screen between different drm_files Now, only one instance of virgl_screen exists for a device (/dev/dri/cardX), and it is shared by different frontends (eg GLX, GBM, etc.). There is a problem with this, as follows: /* Init GLX */ ... glXCreateContext(...); ... /* GBM */ gbm_fd = open("/dev/dri/card0", O_RDWR); dev = gbm_create_device(gbm_fd); bo = gbm_bo_create(dev, ...); plane_handle = gbm_bo_get_handle_for_plane(bo, ...); drmPrimeHandleToFD(gbm_fd, handle.u32, flags, &plane_fd); The above drmPrimeHandleToFD() call will fail with ENOENT. The reason is that GBM and GLX share the same virgl_screen (file descriptor), and it is not gbm_fd that is used to create gbm_bo, but other fd (opened during GLX initialization). Since the scope of prime handle is limited to drm_file, the above plane_handle is invalid under gbm_fd. By canceling the sharing of virgl_screen between different drm_files, GBM can use the correct fd to create resources, thereby avoiding the problem of invalid prime handle. Signed-off-by: Feng Jiang Reviewed-by: Gert Wollny Part-of: --- .../winsys/virgl/drm/virgl_drm_winsys.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c index 38b0c94be01..4d7fb144496 100644 --- a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -1298,6 +1298,43 @@ virgl_drm_screen_destroy(struct pipe_screen *pscreen) } } +static uint32_t +hash_fd(const void *key) +{ + int fd = pointer_to_intptr(key); + + return _mesa_hash_int(&fd); +} + +static bool +equal_fd(const void *key1, const void *key2) +{ + int ret; + int fd1 = pointer_to_intptr(key1); + int fd2 = pointer_to_intptr(key2); + + /* Since the scope of prime handle is limited to drm_file, + * virgl_screen is only shared at the drm_file level, + * not at the device (/dev/dri/cardX) level. + */ + ret = os_same_file_description(fd1, fd2); + if (ret == 0) { + return true; + } else if (ret < 0) { + static bool logged; + + if (!logged) { + _debug_printf("virgl: os_same_file_description couldn't " + "determine if two DRM fds reference the same " + "file description.\n" + "If they do, bad things may happen!\n"); + logged = true; + } + } + + return false; +} + struct pipe_screen * virgl_drm_screen_create(int fd, const struct pipe_screen_config *config) { @@ -1305,7 +1342,7 @@ virgl_drm_screen_create(int fd, const struct pipe_screen_config *config) mtx_lock(&virgl_screen_mutex); if (!fd_tab) { - fd_tab = util_hash_table_create_fd_keys(); + fd_tab = _mesa_hash_table_create(NULL, hash_fd, equal_fd); if (!fd_tab) goto unlock; }