radeon_drm_bo.c revision 93f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633
1/* 2 * Copyright © 2011 Marek Olšák <maraeo@gmail.com> 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS 17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 */ 26 27#define _FILE_OFFSET_BITS 64 28#include "radeon_drm_cs.h" 29 30#include "util/u_hash_table.h" 31#include "util/u_memory.h" 32#include "util/u_simple_list.h" 33#include "os/os_thread.h" 34#include "os/os_mman.h" 35 36#include "state_tracker/drm_driver.h" 37 38#include <sys/ioctl.h> 39#include <xf86drm.h> 40#include <errno.h> 41 42#define RADEON_BO_FLAGS_MACRO_TILE 1 43#define RADEON_BO_FLAGS_MICRO_TILE 2 44#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20 45 46#ifndef DRM_RADEON_GEM_WAIT 47#define DRM_RADEON_GEM_WAIT 0x2b 48 49#define RADEON_GEM_NO_WAIT 0x1 50#define RADEON_GEM_USAGE_READ 0x2 51#define RADEON_GEM_USAGE_WRITE 0x4 52 53struct drm_radeon_gem_wait { 54 uint32_t handle; 55 uint32_t flags; /* one of RADEON_GEM_* */ 56}; 57 58#endif 59 60 61extern const struct pb_vtbl radeon_bo_vtbl; 62 63 64static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo) 65{ 66 assert(bo->vtbl == &radeon_bo_vtbl); 67 return (struct radeon_bo *)bo; 68} 69 70struct radeon_bomgr { 71 /* Base class. */ 72 struct pb_manager base; 73 74 /* Winsys. */ 75 struct radeon_drm_winsys *rws; 76 77 /* List of buffer handles and its mutex. */ 78 struct util_hash_table *bo_handles; 79 pipe_mutex bo_handles_mutex; 80}; 81 82static INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr) 83{ 84 return (struct radeon_bomgr *)mgr; 85} 86 87static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf) 88{ 89 struct radeon_bo *bo = NULL; 90 91 if (_buf->vtbl == &radeon_bo_vtbl) { 92 bo = radeon_bo(_buf); 93 } else { 94 struct pb_buffer *base_buf; 95 pb_size offset; 96 pb_get_base_buffer(_buf, &base_buf, &offset); 97 98 if (base_buf->vtbl == &radeon_bo_vtbl) 99 bo = radeon_bo(base_buf); 100 } 101 102 return bo; 103} 104 105static void radeon_bo_wait(struct pb_buffer *_buf, enum radeon_bo_usage usage) 106{ 107 struct radeon_bo *bo = get_radeon_bo(_buf); 108 109 while (p_atomic_read(&bo->num_active_ioctls)) { 110 sched_yield(); 111 } 112 113 /* XXX use this when it's ready */ 114 /*if (bo->rws->info.drm_minor >= 12) { 115 struct drm_radeon_gem_wait args = {}; 116 args.handle = bo->handle; 117 args.flags = usage; 118 while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT, 119 &args, sizeof(args)) == -EBUSY); 120 } else*/ { 121 struct drm_radeon_gem_wait_idle args; 122 memset(&args, 0, sizeof(args)); 123 args.handle = bo->handle; 124 while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE, 125 &args, sizeof(args)) == -EBUSY); 126 } 127} 128 129static boolean radeon_bo_is_busy(struct pb_buffer *_buf, 130 enum radeon_bo_usage usage) 131{ 132 struct radeon_bo *bo = get_radeon_bo(_buf); 133 134 if (p_atomic_read(&bo->num_active_ioctls)) { 135 return TRUE; 136 } 137 138 /* XXX use this when it's ready */ 139 /*if (bo->rws->info.drm_minor >= 12) { 140 struct drm_radeon_gem_wait args = {}; 141 args.handle = bo->handle; 142 args.flags = usage | RADEON_GEM_NO_WAIT; 143 return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT, 144 &args, sizeof(args)) != 0; 145 } else*/ { 146 struct drm_radeon_gem_busy args; 147 memset(&args, 0, sizeof(args)); 148 args.handle = bo->handle; 149 return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY, 150 &args, sizeof(args)) != 0; 151 } 152} 153 154static void radeon_bo_destroy(struct pb_buffer *_buf) 155{ 156 struct radeon_bo *bo = radeon_bo(_buf); 157 struct drm_gem_close args; 158 159 memset(&args, 0, sizeof(args)); 160 161 if (bo->name) { 162 pipe_mutex_lock(bo->mgr->bo_handles_mutex); 163 util_hash_table_remove(bo->mgr->bo_handles, 164 (void*)(uintptr_t)bo->name); 165 pipe_mutex_unlock(bo->mgr->bo_handles_mutex); 166 } 167 168 if (bo->ptr) 169 os_munmap(bo->ptr, bo->base.size); 170 171 /* Close object. */ 172 args.handle = bo->handle; 173 drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args); 174 pipe_mutex_destroy(bo->map_mutex); 175 FREE(bo); 176} 177 178static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage) 179{ 180 unsigned res = 0; 181 182 if (usage & PIPE_TRANSFER_WRITE) 183 res |= PB_USAGE_CPU_WRITE; 184 185 if (usage & PIPE_TRANSFER_DONTBLOCK) 186 res |= PB_USAGE_DONTBLOCK; 187 188 if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) 189 res |= PB_USAGE_UNSYNCHRONIZED; 190 191 return res; 192} 193 194static void *radeon_bo_map_internal(struct pb_buffer *_buf, 195 unsigned flags, void *flush_ctx) 196{ 197 struct radeon_bo *bo = radeon_bo(_buf); 198 struct radeon_drm_cs *cs = flush_ctx; 199 struct drm_radeon_gem_mmap args; 200 void *ptr; 201 202 memset(&args, 0, sizeof(args)); 203 204 /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ 205 if (!(flags & PB_USAGE_UNSYNCHRONIZED)) { 206 /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */ 207 if (flags & PB_USAGE_DONTBLOCK) { 208 if (!(flags & PB_USAGE_CPU_WRITE)) { 209 /* Mapping for read. 210 * 211 * Since we are mapping for read, we don't need to wait 212 * if the GPU is using the buffer for read too 213 * (neither one is changing it). 214 * 215 * Only check whether the buffer is being used for write. */ 216 if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) { 217 cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC); 218 return NULL; 219 } 220 221 if (radeon_bo_is_busy((struct pb_buffer*)bo, 222 RADEON_USAGE_WRITE)) { 223 return NULL; 224 } 225 } else { 226 if (radeon_bo_is_referenced_by_cs(cs, bo)) { 227 cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC); 228 return NULL; 229 } 230 231 if (radeon_bo_is_busy((struct pb_buffer*)bo, 232 RADEON_USAGE_READWRITE)) { 233 return NULL; 234 } 235 } 236 } else { 237 if (!(flags & PB_USAGE_CPU_WRITE)) { 238 /* Mapping for read. 239 * 240 * Since we are mapping for read, we don't need to wait 241 * if the GPU is using the buffer for read too 242 * (neither one is changing it). 243 * 244 * Only check whether the buffer is being used for write. */ 245 if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) { 246 cs->flush_cs(cs->flush_data, 0); 247 } 248 radeon_bo_wait((struct pb_buffer*)bo, 249 RADEON_USAGE_WRITE); 250 } else { 251 /* Mapping for write. */ 252 if (radeon_bo_is_referenced_by_cs(cs, bo)) { 253 cs->flush_cs(cs->flush_data, 0); 254 } else { 255 /* Try to avoid busy-waiting in radeon_bo_wait. */ 256 if (p_atomic_read(&bo->num_active_ioctls)) 257 radeon_drm_cs_sync_flush(cs); 258 } 259 260 radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE); 261 } 262 } 263 } 264 265 /* Return the pointer if it's already mapped. */ 266 if (bo->ptr) 267 return bo->ptr; 268 269 /* Map the buffer. */ 270 pipe_mutex_lock(bo->map_mutex); 271 /* Return the pointer if it's already mapped (in case of a race). */ 272 if (bo->ptr) { 273 pipe_mutex_unlock(bo->map_mutex); 274 return bo->ptr; 275 } 276 args.handle = bo->handle; 277 args.offset = 0; 278 args.size = (uint64_t)bo->base.size; 279 if (drmCommandWriteRead(bo->rws->fd, 280 DRM_RADEON_GEM_MMAP, 281 &args, 282 sizeof(args))) { 283 pipe_mutex_unlock(bo->map_mutex); 284 fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", 285 bo, bo->handle); 286 return NULL; 287 } 288 289 ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, 290 bo->rws->fd, args.addr_ptr); 291 if (ptr == MAP_FAILED) { 292 pipe_mutex_unlock(bo->map_mutex); 293 fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); 294 return NULL; 295 } 296 bo->ptr = ptr; 297 pipe_mutex_unlock(bo->map_mutex); 298 299 return bo->ptr; 300} 301 302static void radeon_bo_unmap_internal(struct pb_buffer *_buf) 303{ 304 /* NOP */ 305} 306 307static void radeon_bo_get_base_buffer(struct pb_buffer *buf, 308 struct pb_buffer **base_buf, 309 unsigned *offset) 310{ 311 *base_buf = buf; 312 *offset = 0; 313} 314 315static enum pipe_error radeon_bo_validate(struct pb_buffer *_buf, 316 struct pb_validate *vl, 317 unsigned flags) 318{ 319 /* Always pinned */ 320 return PIPE_OK; 321} 322 323static void radeon_bo_fence(struct pb_buffer *buf, 324 struct pipe_fence_handle *fence) 325{ 326} 327 328const struct pb_vtbl radeon_bo_vtbl = { 329 radeon_bo_destroy, 330 radeon_bo_map_internal, 331 radeon_bo_unmap_internal, 332 radeon_bo_validate, 333 radeon_bo_fence, 334 radeon_bo_get_base_buffer, 335}; 336 337static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr, 338 pb_size size, 339 const struct pb_desc *desc) 340{ 341 struct radeon_bomgr *mgr = radeon_bomgr(_mgr); 342 struct radeon_drm_winsys *rws = mgr->rws; 343 struct radeon_bo *bo; 344 struct drm_radeon_gem_create args; 345 struct radeon_bo_desc *rdesc = (struct radeon_bo_desc*)desc; 346 347 memset(&args, 0, sizeof(args)); 348 349 assert(rdesc->initial_domains); 350 assert((rdesc->initial_domains & 351 ~(RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 0); 352 353 args.size = size; 354 args.alignment = desc->alignment; 355 args.initial_domain = rdesc->initial_domains; 356 357 if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE, 358 &args, sizeof(args))) { 359 fprintf(stderr, "radeon: Failed to allocate a buffer:\n"); 360 fprintf(stderr, "radeon: size : %d bytes\n", size); 361 fprintf(stderr, "radeon: alignment : %d bytes\n", desc->alignment); 362 fprintf(stderr, "radeon: domains : %d\n", args.initial_domain); 363 return NULL; 364 } 365 366 bo = CALLOC_STRUCT(radeon_bo); 367 if (!bo) 368 return NULL; 369 370 pipe_reference_init(&bo->base.reference, 1); 371 bo->base.alignment = desc->alignment; 372 bo->base.usage = desc->usage; 373 bo->base.size = size; 374 bo->base.vtbl = &radeon_bo_vtbl; 375 bo->mgr = mgr; 376 bo->rws = mgr->rws; 377 bo->handle = args.handle; 378 pipe_mutex_init(bo->map_mutex); 379 380 return &bo->base; 381} 382 383static void radeon_bomgr_flush(struct pb_manager *mgr) 384{ 385 /* NOP */ 386} 387 388/* This is for the cache bufmgr. */ 389static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr, 390 struct pb_buffer *_buf) 391{ 392 struct radeon_bo *bo = radeon_bo(_buf); 393 394 if (radeon_bo_is_referenced_by_any_cs(bo)) { 395 return TRUE; 396 } 397 398 if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) { 399 return TRUE; 400 } 401 402 return FALSE; 403} 404 405static void radeon_bomgr_destroy(struct pb_manager *_mgr) 406{ 407 struct radeon_bomgr *mgr = radeon_bomgr(_mgr); 408 util_hash_table_destroy(mgr->bo_handles); 409 pipe_mutex_destroy(mgr->bo_handles_mutex); 410 FREE(mgr); 411} 412 413#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) 414 415static unsigned handle_hash(void *key) 416{ 417 return PTR_TO_UINT(key); 418} 419 420static int handle_compare(void *key1, void *key2) 421{ 422 return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); 423} 424 425struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws) 426{ 427 struct radeon_bomgr *mgr; 428 429 mgr = CALLOC_STRUCT(radeon_bomgr); 430 if (!mgr) 431 return NULL; 432 433 mgr->base.destroy = radeon_bomgr_destroy; 434 mgr->base.create_buffer = radeon_bomgr_create_bo; 435 mgr->base.flush = radeon_bomgr_flush; 436 mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy; 437 438 mgr->rws = rws; 439 mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare); 440 pipe_mutex_init(mgr->bo_handles_mutex); 441 return &mgr->base; 442} 443 444static void *radeon_bo_map(struct pb_buffer *buf, 445 struct radeon_winsys_cs *cs, 446 enum pipe_transfer_usage usage) 447{ 448 return pb_map(buf, get_pb_usage_from_transfer_flags(usage), cs); 449} 450 451static void radeon_bo_get_tiling(struct pb_buffer *_buf, 452 enum radeon_bo_layout *microtiled, 453 enum radeon_bo_layout *macrotiled) 454{ 455 struct radeon_bo *bo = get_radeon_bo(_buf); 456 struct drm_radeon_gem_set_tiling args; 457 458 memset(&args, 0, sizeof(args)); 459 460 args.handle = bo->handle; 461 462 drmCommandWriteRead(bo->rws->fd, 463 DRM_RADEON_GEM_GET_TILING, 464 &args, 465 sizeof(args)); 466 467 *microtiled = RADEON_LAYOUT_LINEAR; 468 *macrotiled = RADEON_LAYOUT_LINEAR; 469 if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE) 470 *microtiled = RADEON_LAYOUT_TILED; 471 472 if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE) 473 *macrotiled = RADEON_LAYOUT_TILED; 474} 475 476static void radeon_bo_set_tiling(struct pb_buffer *_buf, 477 struct radeon_winsys_cs *rcs, 478 enum radeon_bo_layout microtiled, 479 enum radeon_bo_layout macrotiled, 480 uint32_t pitch) 481{ 482 struct radeon_bo *bo = get_radeon_bo(_buf); 483 struct radeon_drm_cs *cs = radeon_drm_cs(rcs); 484 struct drm_radeon_gem_set_tiling args; 485 486 memset(&args, 0, sizeof(args)); 487 488 /* Tiling determines how DRM treats the buffer data. 489 * We must flush CS when changing it if the buffer is referenced. */ 490 if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) { 491 cs->flush_cs(cs->flush_data, 0); 492 } 493 494 while (p_atomic_read(&bo->num_active_ioctls)) { 495 sched_yield(); 496 } 497 498 if (microtiled == RADEON_LAYOUT_TILED) 499 args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE; 500 else if (microtiled == RADEON_LAYOUT_SQUARETILED) 501 args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; 502 503 if (macrotiled == RADEON_LAYOUT_TILED) 504 args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE; 505 506 args.handle = bo->handle; 507 args.pitch = pitch; 508 509 drmCommandWriteRead(bo->rws->fd, 510 DRM_RADEON_GEM_SET_TILING, 511 &args, 512 sizeof(args)); 513} 514 515static struct radeon_winsys_cs_handle *radeon_drm_get_cs_handle( 516 struct pb_buffer *_buf) 517{ 518 /* return radeon_bo. */ 519 return (struct radeon_winsys_cs_handle*)get_radeon_bo(_buf); 520} 521 522static struct pb_buffer * 523radeon_winsys_bo_create(struct radeon_winsys *rws, 524 unsigned size, 525 unsigned alignment, 526 unsigned bind, 527 enum radeon_bo_domain domain) 528{ 529 struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); 530 struct radeon_bo_desc desc; 531 struct pb_manager *provider; 532 struct pb_buffer *buffer; 533 534 memset(&desc, 0, sizeof(desc)); 535 desc.base.alignment = alignment; 536 537 /* Additional criteria for the cache manager. */ 538 desc.base.usage = domain; 539 desc.initial_domains = domain; 540 541 /* Assign a buffer manager. */ 542 if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | 543 PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_CUSTOM)) 544 provider = ws->cman; 545 else 546 provider = ws->kman; 547 548 buffer = provider->create_buffer(provider, size, &desc.base); 549 if (!buffer) 550 return NULL; 551 552 return (struct pb_buffer*)buffer; 553} 554 555static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, 556 struct winsys_handle *whandle, 557 unsigned *stride) 558{ 559 struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); 560 struct radeon_bo *bo; 561 struct radeon_bomgr *mgr = radeon_bomgr(ws->kman); 562 struct drm_gem_open open_arg = {}; 563 564 memset(&open_arg, 0, sizeof(open_arg)); 565 566 /* We must maintain a list of pairs <handle, bo>, so that we always return 567 * the same BO for one particular handle. If we didn't do that and created 568 * more than one BO for the same handle and then relocated them in a CS, 569 * we would hit a deadlock in the kernel. 570 * 571 * The list of pairs is guarded by a mutex, of course. */ 572 pipe_mutex_lock(mgr->bo_handles_mutex); 573 574 /* First check if there already is an existing bo for the handle. */ 575 bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle); 576 if (bo) { 577 /* Increase the refcount. */ 578 struct pb_buffer *b = NULL; 579 pb_reference(&b, &bo->base); 580 goto done; 581 } 582 583 /* There isn't, create a new one. */ 584 bo = CALLOC_STRUCT(radeon_bo); 585 if (!bo) { 586 goto fail; 587 } 588 589 /* Open the BO. */ 590 open_arg.name = whandle->handle; 591 if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { 592 FREE(bo); 593 goto fail; 594 } 595 bo->handle = open_arg.handle; 596 bo->name = whandle->handle; 597 598 /* Initialize it. */ 599 pipe_reference_init(&bo->base.reference, 1); 600 bo->base.alignment = 0; 601 bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; 602 bo->base.size = open_arg.size; 603 bo->base.vtbl = &radeon_bo_vtbl; 604 bo->mgr = mgr; 605 bo->rws = mgr->rws; 606 pipe_mutex_init(bo->map_mutex); 607 608 util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo); 609 610done: 611 pipe_mutex_unlock(mgr->bo_handles_mutex); 612 613 if (stride) 614 *stride = whandle->stride; 615 616 return (struct pb_buffer*)bo; 617 618fail: 619 pipe_mutex_unlock(mgr->bo_handles_mutex); 620 return NULL; 621} 622 623static boolean radeon_winsys_bo_get_handle(struct pb_buffer *buffer, 624 unsigned stride, 625 struct winsys_handle *whandle) 626{ 627 struct drm_gem_flink flink; 628 struct radeon_bo *bo = get_radeon_bo(buffer); 629 630 memset(&flink, 0, sizeof(flink)); 631 632 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { 633 if (!bo->flinked) { 634 flink.handle = bo->handle; 635 636 if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { 637 return FALSE; 638 } 639 640 bo->flinked = TRUE; 641 bo->flink = flink.name; 642 } 643 whandle->handle = bo->flink; 644 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { 645 whandle->handle = bo->handle; 646 } 647 648 whandle->stride = stride; 649 return TRUE; 650} 651 652void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws) 653{ 654 ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle; 655 ws->base.buffer_set_tiling = radeon_bo_set_tiling; 656 ws->base.buffer_get_tiling = radeon_bo_get_tiling; 657 ws->base.buffer_map = radeon_bo_map; 658 ws->base.buffer_unmap = pb_unmap; 659 ws->base.buffer_wait = radeon_bo_wait; 660 ws->base.buffer_is_busy = radeon_bo_is_busy; 661 ws->base.buffer_create = radeon_winsys_bo_create; 662 ws->base.buffer_from_handle = radeon_winsys_bo_from_handle; 663 ws->base.buffer_get_handle = radeon_winsys_bo_get_handle; 664} 665