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 <jiangfeng@kylinos.cn>
Reviewed-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16738>
This commit is contained in:
Feng Jiang 2022-05-27 16:24:11 +08:00 committed by Marge Bot
parent 883acc4150
commit 2926a1aa76

View file

@ -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;
}