mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 04:30:10 +01:00
virgl: reuse screen when fd is already open
It is necessary to share the screen between mesa and gralloc to properly ref count resources. This implements a hash lookup on the file description to re-use an already created screen. This is a similar implementation as freedreno and radeon. Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
6711592c2f
commit
f87330dbce
5 changed files with 97 additions and 8 deletions
|
|
@ -226,14 +226,9 @@ pipe_freedreno_create_screen(int fd)
|
|||
struct pipe_screen *
|
||||
pipe_virgl_create_screen(int fd)
|
||||
{
|
||||
struct virgl_winsys *vws;
|
||||
struct pipe_screen *screen;
|
||||
|
||||
vws = virgl_drm_winsys_create(fd);
|
||||
if (!vws)
|
||||
return NULL;
|
||||
|
||||
screen = virgl_create_screen(vws);
|
||||
screen = virgl_drm_screen_create(fd);
|
||||
return screen ? debug_screen_wrap(screen) : NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -557,6 +557,7 @@ virgl_create_screen(struct virgl_winsys *vws)
|
|||
|
||||
vws->get_caps(vws, &screen->caps);
|
||||
|
||||
screen->refcnt = 1;
|
||||
|
||||
util_format_s3tc_init();
|
||||
return &screen->base;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@
|
|||
|
||||
struct virgl_screen {
|
||||
struct pipe_screen base;
|
||||
|
||||
int refcnt;
|
||||
|
||||
/* place for winsys to stash it's own stuff: */
|
||||
void *winsys_priv;
|
||||
|
||||
struct virgl_winsys *vws;
|
||||
|
||||
struct virgl_drm_caps caps;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
#ifndef VIRGL_DRM_PUBLIC_H
|
||||
#define VIRGL_DRM_PUBLIC_H
|
||||
|
||||
struct virgl_winsys;
|
||||
struct pipe_screen;
|
||||
|
||||
struct virgl_winsys *virgl_drm_winsys_create(int drmFD);
|
||||
struct pipe_screen *virgl_drm_screen_create(int fd);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "os/os_mman.h"
|
||||
#include "os/os_time.h"
|
||||
|
|
@ -33,6 +34,8 @@
|
|||
#include "util/u_hash_table.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "state_tracker/drm_driver.h"
|
||||
#include "virgl/virgl_screen.h"
|
||||
#include "virgl/virgl_public.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include "virtgpu_drm.h"
|
||||
|
|
@ -772,3 +775,87 @@ virgl_drm_winsys_create(int drmFD)
|
|||
return &qdws->base;
|
||||
|
||||
}
|
||||
|
||||
static struct util_hash_table *fd_tab = NULL;
|
||||
pipe_static_mutex(virgl_screen_mutex);
|
||||
|
||||
static void
|
||||
virgl_drm_screen_destroy(struct pipe_screen *pscreen)
|
||||
{
|
||||
struct virgl_screen *screen = virgl_screen(pscreen);
|
||||
boolean destroy;
|
||||
|
||||
pipe_mutex_lock(virgl_screen_mutex);
|
||||
destroy = --screen->refcnt == 0;
|
||||
if (destroy) {
|
||||
int fd = virgl_drm_winsys(screen->vws)->fd;
|
||||
util_hash_table_remove(fd_tab, intptr_to_pointer(fd));
|
||||
}
|
||||
pipe_mutex_unlock(virgl_screen_mutex);
|
||||
|
||||
if (destroy) {
|
||||
pscreen->destroy = screen->winsys_priv;
|
||||
pscreen->destroy(pscreen);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned hash_fd(void *key)
|
||||
{
|
||||
int fd = pointer_to_intptr(key);
|
||||
struct stat stat;
|
||||
fstat(fd, &stat);
|
||||
|
||||
return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
|
||||
}
|
||||
|
||||
static int compare_fd(void *key1, void *key2)
|
||||
{
|
||||
int fd1 = pointer_to_intptr(key1);
|
||||
int fd2 = pointer_to_intptr(key2);
|
||||
struct stat stat1, stat2;
|
||||
fstat(fd1, &stat1);
|
||||
fstat(fd2, &stat2);
|
||||
|
||||
return stat1.st_dev != stat2.st_dev ||
|
||||
stat1.st_ino != stat2.st_ino ||
|
||||
stat1.st_rdev != stat2.st_rdev;
|
||||
}
|
||||
|
||||
struct pipe_screen *
|
||||
virgl_drm_screen_create(int fd)
|
||||
{
|
||||
struct pipe_screen *pscreen = NULL;
|
||||
|
||||
pipe_mutex_lock(virgl_screen_mutex);
|
||||
if (!fd_tab) {
|
||||
fd_tab = util_hash_table_create(hash_fd, compare_fd);
|
||||
if (!fd_tab)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
pscreen = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
|
||||
if (pscreen) {
|
||||
virgl_screen(pscreen)->refcnt++;
|
||||
} else {
|
||||
struct virgl_winsys *vws;
|
||||
int dup_fd = dup(fd);
|
||||
|
||||
vws = virgl_drm_winsys_create(dup_fd);
|
||||
|
||||
pscreen = virgl_create_screen(vws);
|
||||
if (pscreen) {
|
||||
util_hash_table_set(fd_tab, intptr_to_pointer(dup_fd), pscreen);
|
||||
|
||||
/* Bit of a hack, to avoid circular linkage dependency,
|
||||
* ie. pipe driver having to call in to winsys, we
|
||||
* override the pipe drivers screen->destroy():
|
||||
*/
|
||||
virgl_screen(pscreen)->winsys_priv = pscreen->destroy;
|
||||
pscreen->destroy = virgl_drm_screen_destroy;
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
pipe_mutex_unlock(virgl_screen_mutex);
|
||||
return pscreen;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue