1 /* 2 * Copyright © 2008 Dave Airlie 3 * Copyright © 2008 Jérôme 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 * Jérôme Glisse <glisse@freedesktop.org> 31 */ 32 #include <stdio.h> 33 #include <stdint.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <errno.h> 37 #include "libdrm_macros.h" 38 #include "xf86drm.h" 39 #include "xf86atomic.h" 40 #include "drm.h" 41 #include "radeon_drm.h" 42 #include "radeon_bo.h" 43 #include "radeon_bo_int.h" 44 #include "radeon_bo_gem.h" 45 #include <fcntl.h> 46 struct radeon_bo_gem { 47 struct radeon_bo_int base; 48 uint32_t name; 49 int map_count; 50 atomic_t reloc_in_cs; 51 void *priv_ptr; 52 }; 53 54 struct bo_manager_gem { 55 struct radeon_bo_manager base; 56 }; 57 58 static int bo_wait(struct radeon_bo_int *boi); 59 60 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom, 61 uint32_t handle, 62 uint32_t size, 63 uint32_t alignment, 64 uint32_t domains, 65 uint32_t flags) 66 { 67 struct radeon_bo_gem *bo; 68 int r; 69 70 bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem)); 71 if (bo == NULL) { 72 return NULL; 73 } 74 75 bo->base.bom = bom; 76 bo->base.handle = 0; 77 bo->base.size = size; 78 bo->base.alignment = alignment; 79 bo->base.domains = domains; 80 bo->base.flags = flags; 81 bo->base.ptr = NULL; 82 atomic_set(&bo->reloc_in_cs, 0); 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 = drmIoctl(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 = flags; 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_int *boi) 122 { 123 } 124 125 static struct radeon_bo *bo_unref(struct radeon_bo_int *boi) 126 { 127 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi; 128 129 if (boi->cref) { 130 return (struct radeon_bo *)boi; 131 } 132 if (bo_gem->priv_ptr) { 133 drm_munmap(bo_gem->priv_ptr, boi->size); 134 } 135 136 /* close object */ 137 drmCloseBufferHandle(boi->bom->fd, boi->handle); 138 memset(bo_gem, 0, sizeof(struct radeon_bo_gem)); 139 free(bo_gem); 140 return NULL; 141 } 142 143 static int bo_map(struct radeon_bo_int *boi, int write) 144 { 145 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi; 146 struct drm_radeon_gem_mmap args; 147 int r; 148 void *ptr; 149 150 if (bo_gem->map_count++ != 0) { 151 return 0; 152 } 153 if (bo_gem->priv_ptr) { 154 goto wait; 155 } 156 157 boi->ptr = NULL; 158 159 /* Zero out args to make valgrind happy */ 160 memset(&args, 0, sizeof(args)); 161 args.handle = boi->handle; 162 args.offset = 0; 163 args.size = (uint64_t)boi->size; 164 r = drmCommandWriteRead(boi->bom->fd, 165 DRM_RADEON_GEM_MMAP, 166 &args, 167 sizeof(args)); 168 if (r) { 169 fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n", 170 boi, boi->handle, r); 171 return r; 172 } 173 ptr = drm_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, boi->bom->fd, args.addr_ptr); 174 if (ptr == MAP_FAILED) 175 return -errno; 176 bo_gem->priv_ptr = ptr; 177 wait: 178 boi->ptr = bo_gem->priv_ptr; 179 r = bo_wait(boi); 180 if (r) 181 return r; 182 return 0; 183 } 184 185 static int bo_unmap(struct radeon_bo_int *boi) 186 { 187 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)boi; 188 189 if (--bo_gem->map_count > 0) { 190 return 0; 191 } 192 //drm_munmap(bo->ptr, bo->size); 193 boi->ptr = NULL; 194 return 0; 195 } 196 197 static int bo_wait(struct radeon_bo_int *boi) 198 { 199 struct drm_radeon_gem_wait_idle args; 200 int ret; 201 202 /* Zero out args to make valgrind happy */ 203 memset(&args, 0, sizeof(args)); 204 args.handle = boi->handle; 205 do { 206 ret = drmCommandWrite(boi->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_int *boi, uint32_t *domain) 213 { 214 struct drm_radeon_gem_busy args; 215 int ret; 216 217 args.handle = boi->handle; 218 args.domain = 0; 219 220 ret = drmCommandWriteRead(boi->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_int *boi, uint32_t tiling_flags, 228 uint32_t pitch) 229 { 230 struct drm_radeon_gem_set_tiling args; 231 int r; 232 233 args.handle = boi->handle; 234 args.tiling_flags = tiling_flags; 235 args.pitch = pitch; 236 237 r = drmCommandWriteRead(boi->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_int *boi, uint32_t *tiling_flags, 245 uint32_t *pitch) 246 { 247 struct drm_radeon_gem_set_tiling args = {}; 248 int r; 249 250 args.handle = boi->handle; 251 252 r = drmCommandWriteRead(boi->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 const struct radeon_bo_funcs bo_gem_funcs = { 266 .bo_open = bo_open, 267 .bo_ref = bo_ref, 268 .bo_unref = bo_unref, 269 .bo_map = bo_map, 270 .bo_unmap = bo_unmap, 271 .bo_wait = bo_wait, 272 .bo_is_static = NULL, 273 .bo_set_tiling = bo_set_tiling, 274 .bo_get_tiling = bo_get_tiling, 275 .bo_is_busy = bo_is_busy, 276 .bo_is_referenced_by_cs = NULL, 277 }; 278 279 drm_public struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) 280 { 281 struct bo_manager_gem *bomg; 282 283 bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem)); 284 if (bomg == NULL) { 285 return NULL; 286 } 287 bomg->base.funcs = &bo_gem_funcs; 288 bomg->base.fd = fd; 289 return (struct radeon_bo_manager*)bomg; 290 } 291 292 drm_public void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom) 293 { 294 struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom; 295 296 if (bom == NULL) { 297 return; 298 } 299 free(bomg); 300 } 301 302 drm_public uint32_t 303 radeon_gem_name_bo(struct radeon_bo *bo) 304 { 305 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 306 return bo_gem->name; 307 } 308 309 drm_public void * 310 radeon_gem_get_reloc_in_cs(struct radeon_bo *bo) 311 { 312 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 313 return &bo_gem->reloc_in_cs; 314 } 315 316 drm_public int 317 radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name) 318 { 319 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 320 struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; 321 struct drm_gem_flink flink; 322 int r; 323 324 if (bo_gem->name) { 325 *name = bo_gem->name; 326 return 0; 327 } 328 flink.handle = bo->handle; 329 r = drmIoctl(boi->bom->fd, DRM_IOCTL_GEM_FLINK, &flink); 330 if (r) { 331 return r; 332 } 333 bo_gem->name = flink.name; 334 *name = flink.name; 335 return 0; 336 } 337 338 drm_public int 339 radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) 340 { 341 struct radeon_bo_int *boi = (struct radeon_bo_int *)bo; 342 struct drm_radeon_gem_set_domain args; 343 int r; 344 345 args.handle = bo->handle; 346 args.read_domains = read_domains; 347 args.write_domain = write_domain; 348 349 r = drmCommandWriteRead(boi->bom->fd, 350 DRM_RADEON_GEM_SET_DOMAIN, 351 &args, 352 sizeof(args)); 353 return r; 354 } 355 356 drm_public int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle) 357 { 358 struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; 359 int ret; 360 361 ret = drmPrimeHandleToFD(bo_gem->base.bom->fd, bo->handle, DRM_CLOEXEC, handle); 362 return ret; 363 } 364 365 drm_public struct radeon_bo * 366 radeon_gem_bo_open_prime(struct radeon_bo_manager *bom, int fd_handle, uint32_t size) 367 { 368 struct radeon_bo_gem *bo; 369 int r; 370 uint32_t handle; 371 372 bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem)); 373 if (bo == NULL) { 374 return NULL; 375 } 376 377 bo->base.bom = bom; 378 bo->base.handle = 0; 379 bo->base.size = size; 380 bo->base.alignment = 0; 381 bo->base.domains = RADEON_GEM_DOMAIN_GTT; 382 bo->base.flags = 0; 383 bo->base.ptr = NULL; 384 atomic_set(&bo->reloc_in_cs, 0); 385 bo->map_count = 0; 386 387 r = drmPrimeFDToHandle(bom->fd, fd_handle, &handle); 388 if (r != 0) { 389 free(bo); 390 return NULL; 391 } 392 393 bo->base.handle = handle; 394 bo->name = handle; 395 396 radeon_bo_ref((struct radeon_bo *)bo); 397 return (struct radeon_bo *)bo; 398 399 } 400