1 /********************************************************** 2 * Copyright 2009-2015 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26 27 #include "vmw_screen.h" 28 #include "vmw_fence.h" 29 #include "vmw_context.h" 30 31 #include "util/u_memory.h" 32 #include "pipe/p_compiler.h" 33 #include "util/u_hash_table.h" 34 #ifdef MAJOR_IN_MKDEV 35 #include <sys/mkdev.h> 36 #endif 37 #ifdef MAJOR_IN_SYSMACROS 38 #include <sys/sysmacros.h> 39 #endif 40 #include <sys/stat.h> 41 #include <unistd.h> 42 #include <fcntl.h> 43 44 static struct util_hash_table *dev_hash = NULL; 45 46 static int vmw_dev_compare(void *key1, void *key2) 47 { 48 return (major(*(dev_t *)key1) == major(*(dev_t *)key2) && 49 minor(*(dev_t *)key1) == minor(*(dev_t *)key2)) ? 0 : 1; 50 } 51 52 static unsigned vmw_dev_hash(void *key) 53 { 54 return (major(*(dev_t *) key) << 16) | minor(*(dev_t *) key); 55 } 56 57 /* Called from vmw_drm_create_screen(), creates and initializes the 58 * vmw_winsys_screen structure, which is the main entity in this 59 * module. 60 * First, check whether a vmw_winsys_screen object already exists for 61 * this device, and in that case return that one, making sure that we 62 * have our own file descriptor open to DRM. 63 */ 64 65 struct vmw_winsys_screen * 66 vmw_winsys_create( int fd ) 67 { 68 struct vmw_winsys_screen *vws; 69 struct stat stat_buf; 70 71 if (dev_hash == NULL) { 72 dev_hash = util_hash_table_create(vmw_dev_hash, vmw_dev_compare); 73 if (dev_hash == NULL) 74 return NULL; 75 } 76 77 if (fstat(fd, &stat_buf)) 78 return NULL; 79 80 vws = util_hash_table_get(dev_hash, &stat_buf.st_rdev); 81 if (vws) { 82 vws->open_count++; 83 return vws; 84 } 85 86 vws = CALLOC_STRUCT(vmw_winsys_screen); 87 if (!vws) 88 goto out_no_vws; 89 90 vws->device = stat_buf.st_rdev; 91 vws->open_count = 1; 92 vws->ioctl.drm_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 93 vws->base.have_gb_dma = TRUE; 94 vws->base.need_to_rebind_resources = FALSE; 95 96 if (!vmw_ioctl_init(vws)) 97 goto out_no_ioctl; 98 99 vws->fence_ops = vmw_fence_ops_create(vws); 100 if (!vws->fence_ops) 101 goto out_no_fence_ops; 102 103 if(!vmw_pools_init(vws)) 104 goto out_no_pools; 105 106 if (!vmw_winsys_screen_init_svga(vws)) 107 goto out_no_svga; 108 109 if (util_hash_table_set(dev_hash, &vws->device, vws) != PIPE_OK) 110 goto out_no_hash_insert; 111 112 return vws; 113 out_no_hash_insert: 114 out_no_svga: 115 vmw_pools_cleanup(vws); 116 out_no_pools: 117 vws->fence_ops->destroy(vws->fence_ops); 118 out_no_fence_ops: 119 vmw_ioctl_cleanup(vws); 120 out_no_ioctl: 121 close(vws->ioctl.drm_fd); 122 FREE(vws); 123 out_no_vws: 124 return NULL; 125 } 126 127 void 128 vmw_winsys_destroy(struct vmw_winsys_screen *vws) 129 { 130 if (--vws->open_count == 0) { 131 util_hash_table_remove(dev_hash, &vws->device); 132 vmw_pools_cleanup(vws); 133 vws->fence_ops->destroy(vws->fence_ops); 134 vmw_ioctl_cleanup(vws); 135 close(vws->ioctl.drm_fd); 136 FREE(vws); 137 } 138 } 139