summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/svga/drm/vmw_screen.c
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2014-02-08 09:51:15 -0800
committerBrian Paul <brianp@vmware.com>2014-02-14 08:21:44 -0700
commitfe6a854477c2ed30c37c200668a4dc86512120f7 (patch)
tree9ad955f1e6c293bb28082f9d9dc1de9cf328dbad /src/gallium/winsys/svga/drm/vmw_screen.c
parent59e7c596215155b556ba8cf06233b621b88f49c6 (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.c69
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);
+ }
}