1 /* 2 * Copyright 2008 Dave Airlie 3 * Copyright 2008 Jrme Glisse 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 18 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * The above copyright notice and this permission notice (including the 24 * next paragraph) shall be included in all copies or substantial portions 25 * of the Software. 26 */ 27 /* 28 * Authors: 29 * Dave Airlie 30 * Jrme Glisse <glisse (at) freedesktop.org> 31 */ 32 #ifdef HAVE_CONFIG_H 33 #include <config.h> 34 #endif 35 #include <stdio.h> 36 #include <stdint.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <sys/mman.h> 40 #include <sys/ioctl.h> 41 #include <errno.h> 42 #include "xf86drm.h" 43 #include "drm.h" 44 #include "radeon_drm.h" 45 #include "radeon_bo.h" 46 #include "radeon_bo_gem.h" 47 48 struct radeon_bo_gem { 49 struct radeon_bo base; 50 uint32_t name; 51 int map_count; 52 void *priv_ptr; 53 }; 54 55 struct bo_manager_gem { 56 struct radeon_bo_manager base; 57 }; 58 59 static int bo_wait(struct radeon_bo *bo); 60 61 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom, 62 uint32_t handle, 63 uint32_t size, 64 uint32_t alignment, 65 uint32_t domains, 66 uint32_t flags) 67 { 68 struct radeon_bo_gem *bo; 69 int r; 70 71 bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem)); 72 if (bo == NULL) { 73 return NULL; 74 } 75 76 bo->base.bom = bom; 77 bo->base.handle = 0; 78 bo->base.size = size; 79 bo->base.alignment = alignment; 80 bo->base.domains = domains; 81 bo->base.flags = flags; 82 bo->base.ptr = NULL; 83 bo->map_count = 0; 84 if (handle) { 85 struct drm_gem_open open_arg; 86 87 memset(&open_arg, 0, sizeof(open_arg)); 88 open_arg.name = handle; 89 r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg); 90 if (r != 0) { 91 free(bo); 92 return NULL; 93 } 94 bo->base.handle = open_arg.handle; 95 bo->base.size = open_arg.size; 96 bo->name = handle; 97 } else { 98 struct drm_radeon_gem_create args; 99 100 args.size = size; 101 args.alignment = alignment; 102 args.initial_domain = bo->base.domains; 103 args.flags = 0; 104 args.handle = 0; 105 r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE, 106 &args, sizeof(args)); 107 bo->base.handle = args.handle; 108 if (r) { 109 fprintf(stderr, "Failed to allocate :\n"); 110 fprintf(stderr, " size : %d bytes\n", size); 111 fprintf(stderr, " alignment : %d bytes\n", alignment); 112 fprintf(stderr, " domains : %d\n", bo->base.domains); 113 free(bo); 114 return NULL; 115 } 116 } 117 radeon_bo_ref((struct radeon_bo*)bo); 118 return (struct radeon_bo*)bo; 119 } 120 121 static void bo_ref(struct radeon_bo *bo) 122 { 123 } 124 125 static struct radeon_bo *bo_unref(struct radeon_bo *bo) 126 { 127 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 128 struct drm_gem_close args; 129 130 if (bo == NULL) { 131 return NULL; 132 } 133 if (bo->cref) { 134 return bo; 135 } 136 if (bo_gem->priv_ptr) { 137 munmap(bo_gem->priv_ptr, bo->size); 138 } 139 140 /* close object */ 141 args.handle = bo->handle; 142 ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args); 143 memset(bo_gem, 0, sizeof(struct radeon_bo_gem)); 144 free(bo_gem); 145 return NULL; 146 } 147 148 static int bo_map(struct radeon_bo *bo, int write) 149 { 150 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 151 struct drm_radeon_gem_mmap args; 152 int r; 153 void *ptr; 154 155 if (bo_gem->map_count++ != 0) { 156 return 0; 157 } 158 if (bo_gem->priv_ptr) { 159 goto wait; 160 } 161 162 bo->ptr = NULL; 163 args.handle = bo->handle; 164 args.offset = 0; 165 args.size = (uint64_t)bo->size; 166 r = drmCommandWriteRead(bo->bom->fd, 167 DRM_RADEON_GEM_MMAP, 168 &args, 169 sizeof(args)); 170 if (r) { 171 fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n", 172 bo, bo->handle, r); 173 return r; 174 } 175 ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->bom->fd, args.addr_ptr); 176 if (ptr == MAP_FAILED) 177 return -errno; 178 bo_gem->priv_ptr = ptr; 179 wait: 180 bo->ptr = bo_gem->priv_ptr; 181 r = bo_wait(bo); 182 if (r) 183 return r; 184 return 0; 185 } 186 187 static int bo_unmap(struct radeon_bo *bo) 188 { 189 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 190 191 if (--bo_gem->map_count > 0) { 192 return 0; 193 } 194 //munmap(bo->ptr, bo->size); 195 bo->ptr = NULL; 196 return 0; 197 } 198 199 static int bo_wait(struct radeon_bo *bo) 200 { 201 struct drm_radeon_gem_wait_idle args; 202 int ret; 203 204 args.handle = bo->handle; 205 do { 206 ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_WAIT_IDLE, 207 &args, sizeof(args)); 208 } while (ret == -EBUSY); 209 return ret; 210 } 211 212 static int bo_is_busy(struct radeon_bo *bo, uint32_t *domain) 213 { 214 struct drm_radeon_gem_busy args; 215 int ret; 216 217 args.handle = bo->handle; 218 args.domain = 0; 219 220 ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_BUSY, 221 &args, sizeof(args)); 222 223 *domain = args.domain; 224 return ret; 225 } 226 227 static int bo_set_tiling(struct radeon_bo *bo, uint32_t tiling_flags, 228 uint32_t pitch) 229 { 230 struct drm_radeon_gem_set_tiling args; 231 int r; 232 233 args.handle = bo->handle; 234 args.tiling_flags = tiling_flags; 235 args.pitch = pitch; 236 237 r = drmCommandWriteRead(bo->bom->fd, 238 DRM_RADEON_GEM_SET_TILING, 239 &args, 240 sizeof(args)); 241 return r; 242 } 243 244 static int bo_get_tiling(struct radeon_bo *bo, uint32_t *tiling_flags, 245 uint32_t *pitch) 246 { 247 struct drm_radeon_gem_set_tiling args; 248 int r; 249 250 args.handle = bo->handle; 251 252 r = drmCommandWriteRead(bo->bom->fd, 253 DRM_RADEON_GEM_GET_TILING, 254 &args, 255 sizeof(args)); 256 257 if (r) 258 return r; 259 260 *tiling_flags = args.tiling_flags; 261 *pitch = args.pitch; 262 return r; 263 } 264 265 static struct radeon_bo_funcs bo_gem_funcs = { 266 bo_open, 267 bo_ref, 268 bo_unref, 269 bo_map, 270 bo_unmap, 271 bo_wait, 272 NULL, 273 bo_set_tiling, 274 bo_get_tiling, 275 bo_is_busy, 276 }; 277 278 struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) 279 { 280 struct bo_manager_gem *bomg; 281 282 bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem)); 283 if (bomg == NULL) { 284 return NULL; 285 } 286 bomg->base.funcs = &bo_gem_funcs; 287 bomg->base.fd = fd; 288 return (struct radeon_bo_manager*)bomg; 289 } 290 291 void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom) 292 { 293 struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom; 294 295 if (bom == NULL) { 296 return; 297 } 298 free(bomg); 299 } 300 301 uint32_t radeon_gem_name_bo(struct radeon_bo *bo) 302 { 303 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 304 return bo_gem->name; 305 } 306 307 int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name) 308 { 309 struct drm_gem_flink flink; 310 int r; 311 312 flink.handle = bo->handle; 313 r = ioctl(bo->bom->fd, DRM_IOCTL_GEM_FLINK, &flink); 314 if (r) { 315 return r; 316 } 317 *name = flink.name; 318 return 0; 319 } 320 321 int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) 322 { 323 struct drm_radeon_gem_set_domain args; 324 int r; 325 326 args.handle = bo->handle; 327 args.read_domains = read_domains; 328 args.write_domain = write_domain; 329 330 r = drmCommandWriteRead(bo->bom->fd, 331 DRM_RADEON_GEM_SET_DOMAIN, 332 &args, 333 sizeof(args)); 334 return r; 335 } 336