diff options
author | Brian Paul <brianp@vmware.com> | 2014-02-08 09:51:15 -0800 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2014-02-14 08:21:44 -0700 |
commit | fe6a854477c2ed30c37c200668a4dc86512120f7 (patch) | |
tree | 9ad955f1e6c293bb28082f9d9dc1de9cf328dbad /src/gallium/winsys/svga/drm/vmw_screen.c | |
parent | 59e7c596215155b556ba8cf06233b621b88f49c6 (diff) |
svga/winsys: implement GBS support
This is a squash commit of many commits by Thomas Hellstrom.
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Cc: "10.1" <mesa-stable@lists.freedesktop.org>
Diffstat (limited to 'src/gallium/winsys/svga/drm/vmw_screen.c')
-rw-r--r-- | src/gallium/winsys/svga/drm/vmw_screen.c | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/src/gallium/winsys/svga/drm/vmw_screen.c b/src/gallium/winsys/svga/drm/vmw_screen.c index f7799cec32d..0c343cc7bdd 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen.c +++ b/src/gallium/winsys/svga/drm/vmw_screen.c @@ -25,42 +25,94 @@ #include "vmw_screen.h" - +#include "vmw_fence.h" #include "vmw_context.h" #include "util/u_memory.h" #include "pipe/p_compiler.h" +#include "util/u_hash_table.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +static struct util_hash_table *dev_hash = NULL; + +static int vmw_dev_compare(void *key1, void *key2) +{ + return (major(*(dev_t *)key1) == major(*(dev_t *)key2) && + minor(*(dev_t *)key1) == minor(*(dev_t *)key2)) ? 0 : 1; +} + +static unsigned vmw_dev_hash(void *key) +{ + return (major(*(dev_t *) key) << 16) | minor(*(dev_t *) key); +} /* Called from vmw_drm_create_screen(), creates and initializes the * vmw_winsys_screen structure, which is the main entity in this * module. + * First, check whether a vmw_winsys_screen object already exists for + * this device, and in that case return that one, making sure that we + * have our own file descriptor open to DRM. */ + struct vmw_winsys_screen * vmw_winsys_create( int fd, boolean use_old_scanout_flag ) { - struct vmw_winsys_screen *vws = CALLOC_STRUCT(vmw_winsys_screen); + struct vmw_winsys_screen *vws; + struct stat stat_buf; + + if (dev_hash == NULL) { + dev_hash = util_hash_table_create(vmw_dev_hash, vmw_dev_compare); + if (dev_hash == NULL) + return NULL; + } + + if (fstat(fd, &stat_buf)) + return NULL; + + vws = util_hash_table_get(dev_hash, &stat_buf.st_rdev); + if (vws) { + vws->open_count++; + return vws; + } + + vws = CALLOC_STRUCT(vmw_winsys_screen); if (!vws) goto out_no_vws; - vws->ioctl.drm_fd = fd; + vws->device = stat_buf.st_rdev; + vws->open_count = 1; + vws->ioctl.drm_fd = dup(fd); vws->use_old_scanout_flag = use_old_scanout_flag; + vws->base.have_gb_dma = TRUE; if (!vmw_ioctl_init(vws)) goto out_no_ioctl; + vws->fence_ops = vmw_fence_ops_create(vws); + if (!vws->fence_ops) + goto out_no_fence_ops; + if(!vmw_pools_init(vws)) goto out_no_pools; if (!vmw_winsys_screen_init_svga(vws)) goto out_no_svga; + if (util_hash_table_set(dev_hash, &vws->device, vws) != PIPE_OK) + goto out_no_hash_insert; + return vws; +out_no_hash_insert: out_no_svga: vmw_pools_cleanup(vws); out_no_pools: + vws->fence_ops->destroy(vws->fence_ops); +out_no_fence_ops: vmw_ioctl_cleanup(vws); out_no_ioctl: + close(vws->ioctl.drm_fd); FREE(vws); out_no_vws: return NULL; @@ -69,7 +121,12 @@ out_no_vws: void vmw_winsys_destroy(struct vmw_winsys_screen *vws) { - vmw_pools_cleanup(vws); - vmw_ioctl_cleanup(vws); - FREE(vws); + if (--vws->open_count == 0) { + util_hash_table_remove(dev_hash, &vws->device); + vmw_pools_cleanup(vws); + vws->fence_ops->destroy(vws->fence_ops); + vmw_ioctl_cleanup(vws); + close(vws->ioctl.drm_fd); + FREE(vws); + } } |