1 /************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * 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 above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* Originally a fake version of the buffer manager so that we can 29 * prototype the changes in a driver fairly quickly, has been fleshed 30 * out to a fully functional interim solution. 31 * 32 * Basically wraps the old style memory management in the new 33 * programming interface, but is more expressive and avoids many of 34 * the bugs in the old texture manager. 35 */ 36 37 #include <stdlib.h> 38 #include <string.h> 39 #include <assert.h> 40 #include <errno.h> 41 #include <strings.h> 42 #include <xf86drm.h> 43 #include <pthread.h> 44 #include "intel_bufmgr.h" 45 #include "intel_bufmgr_priv.h" 46 #include "drm.h" 47 #include "i915_drm.h" 48 #include "mm.h" 49 #include "libdrm_macros.h" 50 #include "libdrm_lists.h" 51 52 #define DBG(...) do { \ 53 if (bufmgr_fake->bufmgr.debug) \ 54 drmMsg(__VA_ARGS__); \ 55 } while (0) 56 57 /* Internal flags: 58 */ 59 #define BM_NO_BACKING_STORE 0x00000001 60 #define BM_NO_FENCE_SUBDATA 0x00000002 61 #define BM_PINNED 0x00000004 62 63 /* Wrapper around mm.c's mem_block, which understands that you must 64 * wait for fences to expire before memory can be freed. This is 65 * specific to our use of memcpy for uploads - an upload that was 66 * processed through the command queue wouldn't need to care about 67 * fences. 68 */ 69 #define MAX_RELOCS 4096 70 71 struct fake_buffer_reloc { 72 /** Buffer object that the relocation points at. */ 73 drm_intel_bo *target_buf; 74 /** Offset of the relocation entry within reloc_buf. */ 75 uint32_t offset; 76 /** 77 * Cached value of the offset when we last performed this relocation. 78 */ 79 uint32_t last_target_offset; 80 /** Value added to target_buf's offset to get the relocation entry. */ 81 uint32_t delta; 82 /** Cache domains the target buffer is read into. */ 83 uint32_t read_domains; 84 /** Cache domain the target buffer will have dirty cachelines in. */ 85 uint32_t write_domain; 86 }; 87 88 struct block { 89 struct block *next, *prev; 90 struct mem_block *mem; /* BM_MEM_AGP */ 91 92 /** 93 * Marks that the block is currently in the aperture and has yet to be 94 * fenced. 95 */ 96 unsigned on_hardware:1; 97 /** 98 * Marks that the block is currently fenced (being used by rendering) 99 * and can't be freed until @fence is passed. 100 */ 101 unsigned fenced:1; 102 103 /** Fence cookie for the block. */ 104 unsigned fence; /* Split to read_fence, write_fence */ 105 106 drm_intel_bo *bo; 107 void *virtual; 108 }; 109 110 typedef struct _bufmgr_fake { 111 drm_intel_bufmgr bufmgr; 112 113 pthread_mutex_t lock; 114 115 unsigned long low_offset; 116 unsigned long size; 117 void *virtual; 118 119 struct mem_block *heap; 120 121 unsigned buf_nr; /* for generating ids */ 122 123 /** 124 * List of blocks which are currently in the GART but haven't been 125 * fenced yet. 126 */ 127 struct block on_hardware; 128 /** 129 * List of blocks which are in the GART and have an active fence on 130 * them. 131 */ 132 struct block fenced; 133 /** 134 * List of blocks which have an expired fence and are ready to be 135 * evicted. 136 */ 137 struct block lru; 138 139 unsigned int last_fence; 140 141 unsigned fail:1; 142 unsigned need_fence:1; 143 int thrashing; 144 145 /** 146 * Driver callback to emit a fence, returning the cookie. 147 * 148 * This allows the driver to hook in a replacement for the DRM usage in 149 * bufmgr_fake. 150 * 151 * Currently, this also requires that a write flush be emitted before 152 * emitting the fence, but this should change. 153 */ 154 unsigned int (*fence_emit) (void *private); 155 /** Driver callback to wait for a fence cookie to have passed. */ 156 void (*fence_wait) (unsigned int fence, void *private); 157 void *fence_priv; 158 159 /** 160 * Driver callback to execute a buffer. 161 * 162 * This allows the driver to hook in a replacement for the DRM usage in 163 * bufmgr_fake. 164 */ 165 int (*exec) (drm_intel_bo *bo, unsigned int used, void *priv); 166 void *exec_priv; 167 168 /** Driver-supplied argument to driver callbacks */ 169 void *driver_priv; 170 /** 171 * Pointer to kernel-updated sarea data for the last completed user irq 172 */ 173 volatile int *last_dispatch; 174 175 int fd; 176 177 int debug; 178 179 int performed_rendering; 180 } drm_intel_bufmgr_fake; 181 182 typedef struct _drm_intel_bo_fake { 183 drm_intel_bo bo; 184 185 unsigned id; /* debug only */ 186 const char *name; 187 188 unsigned dirty:1; 189 /** 190 * has the card written to this buffer - we make need to copy it back 191 */ 192 unsigned card_dirty:1; 193 unsigned int refcount; 194 /* Flags may consist of any of the DRM_BO flags, plus 195 * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the 196 * first two driver private flags. 197 */ 198 uint64_t flags; 199 /** Cache domains the target buffer is read into. */ 200 uint32_t read_domains; 201 /** Cache domain the target buffer will have dirty cachelines in. */ 202 uint32_t write_domain; 203 204 unsigned int alignment; 205 int is_static, validated; 206 unsigned int map_count; 207 208 /** relocation list */ 209 struct fake_buffer_reloc *relocs; 210 int nr_relocs; 211 /** 212 * Total size of the target_bos of this buffer. 213 * 214 * Used for estimation in check_aperture. 215 */ 216 unsigned int child_size; 217 218 struct block *block; 219 void *backing_store; 220 void (*invalidate_cb) (drm_intel_bo *bo, void *ptr); 221 void *invalidate_ptr; 222 } drm_intel_bo_fake; 223 224 static int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, 225 unsigned int fence_cookie); 226 227 #define MAXFENCE 0x7fffffff 228 229 static int 230 FENCE_LTE(unsigned a, unsigned b) 231 { 232 if (a == b) 233 return 1; 234 235 if (a < b && b - a < (1 << 24)) 236 return 1; 237 238 if (a > b && MAXFENCE - a + b < (1 << 24)) 239 return 1; 240 241 return 0; 242 } 243 244 drm_public void 245 drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr, 246 unsigned int (*emit) (void *priv), 247 void (*wait) (unsigned int fence, 248 void *priv), 249 void *priv) 250 { 251 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 252 253 bufmgr_fake->fence_emit = emit; 254 bufmgr_fake->fence_wait = wait; 255 bufmgr_fake->fence_priv = priv; 256 } 257 258 static unsigned int 259 _fence_emit_internal(drm_intel_bufmgr_fake *bufmgr_fake) 260 { 261 struct drm_i915_irq_emit ie; 262 int ret, seq = 1; 263 264 if (bufmgr_fake->fence_emit != NULL) { 265 seq = bufmgr_fake->fence_emit(bufmgr_fake->fence_priv); 266 return seq; 267 } 268 269 ie.irq_seq = &seq; 270 ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT, 271 &ie, sizeof(ie)); 272 if (ret) { 273 drmMsg("%s: drm_i915_irq_emit: %d\n", __func__, ret); 274 abort(); 275 } 276 277 DBG("emit 0x%08x\n", seq); 278 return seq; 279 } 280 281 static void 282 _fence_wait_internal(drm_intel_bufmgr_fake *bufmgr_fake, int seq) 283 { 284 struct drm_i915_irq_wait iw; 285 int hw_seq, busy_count = 0; 286 int ret; 287 int kernel_lied; 288 289 if (bufmgr_fake->fence_wait != NULL) { 290 bufmgr_fake->fence_wait(seq, bufmgr_fake->fence_priv); 291 clear_fenced(bufmgr_fake, seq); 292 return; 293 } 294 295 iw.irq_seq = seq; 296 297 DBG("wait 0x%08x\n", iw.irq_seq); 298 299 /* The kernel IRQ_WAIT implementation is all sorts of broken. 300 * 1) It returns 1 to 0x7fffffff instead of using the full 32-bit 301 * unsigned range. 302 * 2) It returns 0 if hw_seq >= seq, not seq - hw_seq < 0 on the 32-bit 303 * signed range. 304 * 3) It waits if seq < hw_seq, not seq - hw_seq > 0 on the 32-bit 305 * signed range. 306 * 4) It returns -EBUSY in 3 seconds even if the hardware is still 307 * successfully chewing through buffers. 308 * 309 * Assume that in userland we treat sequence numbers as ints, which 310 * makes some of the comparisons convenient, since the sequence 311 * numbers are all positive signed integers. 312 * 313 * From this we get several cases we need to handle. Here's a timeline. 314 * 0x2 0x7 0x7ffffff8 0x7ffffffd 315 * | | | | 316 * ------------------------------------------------------------ 317 * 318 * A) Normal wait for hw to catch up 319 * hw_seq seq 320 * | | 321 * ------------------------------------------------------------ 322 * seq - hw_seq = 5. If we call IRQ_WAIT, it will wait for hw to 323 * catch up. 324 * 325 * B) Normal wait for a sequence number that's already passed. 326 * seq hw_seq 327 * | | 328 * ------------------------------------------------------------ 329 * seq - hw_seq = -5. If we call IRQ_WAIT, it returns 0 quickly. 330 * 331 * C) Hardware has already wrapped around ahead of us 332 * hw_seq seq 333 * | | 334 * ------------------------------------------------------------ 335 * seq - hw_seq = 0x80000000 - 5. If we called IRQ_WAIT, it would wait 336 * for hw_seq >= seq, which may never occur. Thus, we want to catch 337 * this in userland and return 0. 338 * 339 * D) We've wrapped around ahead of the hardware. 340 * seq hw_seq 341 * | | 342 * ------------------------------------------------------------ 343 * seq - hw_seq = -(0x80000000 - 5). If we called IRQ_WAIT, it would 344 * return 0 quickly because hw_seq >= seq, even though the hardware 345 * isn't caught up. Thus, we need to catch this early return in 346 * userland and bother the kernel until the hardware really does 347 * catch up. 348 * 349 * E) Hardware might wrap after we test in userland. 350 * hw_seq seq 351 * | | 352 * ------------------------------------------------------------ 353 * seq - hw_seq = 5. If we call IRQ_WAIT, it will likely see seq >= 354 * hw_seq and wait. However, suppose hw_seq wraps before we make it 355 * into the kernel. The kernel sees hw_seq >= seq and waits for 3 356 * seconds then returns -EBUSY. This is case C). We should catch 357 * this and then return successfully. 358 * 359 * F) Hardware might take a long time on a buffer. 360 * hw_seq seq 361 * | | 362 * ------------------------------------------------------------------- 363 * seq - hw_seq = 5. If we call IRQ_WAIT, if sequence 2 through 5 364 * take too long, it will return -EBUSY. Batchbuffers in the 365 * gltestperf demo were seen to take up to 7 seconds. We should 366 * catch early -EBUSY return and keep trying. 367 */ 368 369 do { 370 /* Keep a copy of last_dispatch so that if the wait -EBUSYs 371 * because the hardware didn't catch up in 3 seconds, we can 372 * see if it at least made progress and retry. 373 */ 374 hw_seq = *bufmgr_fake->last_dispatch; 375 376 /* Catch case C */ 377 if (seq - hw_seq > 0x40000000) 378 return; 379 380 ret = drmCommandWrite(bufmgr_fake->fd, DRM_I915_IRQ_WAIT, 381 &iw, sizeof(iw)); 382 /* Catch case D */ 383 kernel_lied = (ret == 0) && (seq - *bufmgr_fake->last_dispatch < 384 -0x40000000); 385 386 /* Catch case E */ 387 if (ret == -EBUSY 388 && (seq - *bufmgr_fake->last_dispatch > 0x40000000)) 389 ret = 0; 390 391 /* Catch case F: Allow up to 15 seconds chewing on one buffer. */ 392 if ((ret == -EBUSY) && (hw_seq != *bufmgr_fake->last_dispatch)) 393 busy_count = 0; 394 else 395 busy_count++; 396 } while (kernel_lied || ret == -EAGAIN || ret == -EINTR || 397 (ret == -EBUSY && busy_count < 5)); 398 399 if (ret != 0) { 400 drmMsg("%s:%d: Error waiting for fence: %s.\n", __FILE__, 401 __LINE__, strerror(-ret)); 402 abort(); 403 } 404 clear_fenced(bufmgr_fake, seq); 405 } 406 407 static int 408 _fence_test(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence) 409 { 410 /* Slight problem with wrap-around: 411 */ 412 return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence); 413 } 414 415 /** 416 * Allocate a memory manager block for the buffer. 417 */ 418 static int 419 alloc_block(drm_intel_bo *bo) 420 { 421 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 422 drm_intel_bufmgr_fake *bufmgr_fake = 423 (drm_intel_bufmgr_fake *) bo->bufmgr; 424 struct block *block = (struct block *)calloc(sizeof *block, 1); 425 unsigned int align_log2 = ffs(bo_fake->alignment) - 1; 426 unsigned int sz; 427 428 if (!block) 429 return 1; 430 431 sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1); 432 433 block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0); 434 if (!block->mem) { 435 free(block); 436 return 0; 437 } 438 439 DRMINITLISTHEAD(block); 440 441 /* Insert at head or at tail??? */ 442 DRMLISTADDTAIL(block, &bufmgr_fake->lru); 443 444 block->virtual = (uint8_t *) bufmgr_fake->virtual + 445 block->mem->ofs - bufmgr_fake->low_offset; 446 block->bo = bo; 447 448 bo_fake->block = block; 449 450 return 1; 451 } 452 453 /* Release the card storage associated with buf: 454 */ 455 static void 456 free_block(drm_intel_bufmgr_fake *bufmgr_fake, struct block *block, 457 int skip_dirty_copy) 458 { 459 drm_intel_bo_fake *bo_fake; 460 DBG("free block %p %08x %d %d\n", block, block->mem->ofs, 461 block->on_hardware, block->fenced); 462 463 if (!block) 464 return; 465 466 bo_fake = (drm_intel_bo_fake *) block->bo; 467 468 if (bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)) 469 skip_dirty_copy = 1; 470 471 if (!skip_dirty_copy && (bo_fake->card_dirty == 1)) { 472 memcpy(bo_fake->backing_store, block->virtual, block->bo->size); 473 bo_fake->card_dirty = 0; 474 bo_fake->dirty = 1; 475 } 476 477 if (block->on_hardware) { 478 block->bo = NULL; 479 } else if (block->fenced) { 480 block->bo = NULL; 481 } else { 482 DBG(" - free immediately\n"); 483 DRMLISTDEL(block); 484 485 mmFreeMem(block->mem); 486 free(block); 487 } 488 } 489 490 static void 491 alloc_backing_store(drm_intel_bo *bo) 492 { 493 drm_intel_bufmgr_fake *bufmgr_fake = 494 (drm_intel_bufmgr_fake *) bo->bufmgr; 495 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 496 assert(!bo_fake->backing_store); 497 assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))); 498 499 bo_fake->backing_store = malloc(bo->size); 500 501 DBG("alloc_backing - buf %d %p %lu\n", bo_fake->id, 502 bo_fake->backing_store, bo->size); 503 assert(bo_fake->backing_store); 504 } 505 506 static void 507 free_backing_store(drm_intel_bo *bo) 508 { 509 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 510 511 if (bo_fake->backing_store) { 512 assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))); 513 free(bo_fake->backing_store); 514 bo_fake->backing_store = NULL; 515 } 516 } 517 518 static void 519 set_dirty(drm_intel_bo *bo) 520 { 521 drm_intel_bufmgr_fake *bufmgr_fake = 522 (drm_intel_bufmgr_fake *) bo->bufmgr; 523 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 524 525 if (bo_fake->flags & BM_NO_BACKING_STORE 526 && bo_fake->invalidate_cb != NULL) 527 bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr); 528 529 assert(!(bo_fake->flags & BM_PINNED)); 530 531 DBG("set_dirty - buf %d\n", bo_fake->id); 532 bo_fake->dirty = 1; 533 } 534 535 static int 536 evict_lru(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int max_fence) 537 { 538 struct block *block, *tmp; 539 540 DBG("%s\n", __func__); 541 542 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 543 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 544 545 if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA)) 546 continue; 547 548 if (block->fence && max_fence && !FENCE_LTE(block->fence, 549 max_fence)) 550 return 0; 551 552 set_dirty(&bo_fake->bo); 553 bo_fake->block = NULL; 554 555 free_block(bufmgr_fake, block, 0); 556 return 1; 557 } 558 559 return 0; 560 } 561 562 static int 563 evict_mru(drm_intel_bufmgr_fake *bufmgr_fake) 564 { 565 struct block *block, *tmp; 566 567 DBG("%s\n", __func__); 568 569 DRMLISTFOREACHSAFEREVERSE(block, tmp, &bufmgr_fake->lru) { 570 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 571 572 if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA)) 573 continue; 574 575 set_dirty(&bo_fake->bo); 576 bo_fake->block = NULL; 577 578 free_block(bufmgr_fake, block, 0); 579 return 1; 580 } 581 582 return 0; 583 } 584 585 /** 586 * Removes all objects from the fenced list older than the given fence. 587 */ 588 static int 589 clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int fence_cookie) 590 { 591 struct block *block, *tmp; 592 int ret = 0; 593 594 bufmgr_fake->last_fence = fence_cookie; 595 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->fenced) { 596 assert(block->fenced); 597 598 if (_fence_test(bufmgr_fake, block->fence)) { 599 600 block->fenced = 0; 601 602 if (!block->bo) { 603 DBG("delayed free: offset %x sz %x\n", 604 block->mem->ofs, block->mem->size); 605 DRMLISTDEL(block); 606 mmFreeMem(block->mem); 607 free(block); 608 } else { 609 DBG("return to lru: offset %x sz %x\n", 610 block->mem->ofs, block->mem->size); 611 DRMLISTDEL(block); 612 DRMLISTADDTAIL(block, &bufmgr_fake->lru); 613 } 614 615 ret = 1; 616 } else { 617 /* Blocks are ordered by fence, so if one fails, all 618 * from here will fail also: 619 */ 620 DBG("fence not passed: offset %x sz %x %d %d \n", 621 block->mem->ofs, block->mem->size, block->fence, 622 bufmgr_fake->last_fence); 623 break; 624 } 625 } 626 627 DBG("%s: %d\n", __func__, ret); 628 return ret; 629 } 630 631 static void 632 fence_blocks(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence) 633 { 634 struct block *block, *tmp; 635 636 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) { 637 DBG("Fence block %p (sz 0x%x ofs %x buf %p) with fence %d\n", 638 block, block->mem->size, block->mem->ofs, block->bo, fence); 639 block->fence = fence; 640 641 block->on_hardware = 0; 642 block->fenced = 1; 643 644 /* Move to tail of pending list here 645 */ 646 DRMLISTDEL(block); 647 DRMLISTADDTAIL(block, &bufmgr_fake->fenced); 648 } 649 650 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 651 } 652 653 static int 654 evict_and_alloc_block(drm_intel_bo *bo) 655 { 656 drm_intel_bufmgr_fake *bufmgr_fake = 657 (drm_intel_bufmgr_fake *) bo->bufmgr; 658 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 659 660 assert(bo_fake->block == NULL); 661 662 /* Search for already free memory: 663 */ 664 if (alloc_block(bo)) 665 return 1; 666 667 /* If we're not thrashing, allow lru eviction to dig deeper into 668 * recently used textures. We'll probably be thrashing soon: 669 */ 670 if (!bufmgr_fake->thrashing) { 671 while (evict_lru(bufmgr_fake, 0)) 672 if (alloc_block(bo)) 673 return 1; 674 } 675 676 /* Keep thrashing counter alive? 677 */ 678 if (bufmgr_fake->thrashing) 679 bufmgr_fake->thrashing = 20; 680 681 /* Wait on any already pending fences - here we are waiting for any 682 * freed memory that has been submitted to hardware and fenced to 683 * become available: 684 */ 685 while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) { 686 uint32_t fence = bufmgr_fake->fenced.next->fence; 687 _fence_wait_internal(bufmgr_fake, fence); 688 689 if (alloc_block(bo)) 690 return 1; 691 } 692 693 if (!DRMLISTEMPTY(&bufmgr_fake->on_hardware)) { 694 while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) { 695 uint32_t fence = bufmgr_fake->fenced.next->fence; 696 _fence_wait_internal(bufmgr_fake, fence); 697 } 698 699 if (!bufmgr_fake->thrashing) { 700 DBG("thrashing\n"); 701 } 702 bufmgr_fake->thrashing = 20; 703 704 if (alloc_block(bo)) 705 return 1; 706 } 707 708 while (evict_mru(bufmgr_fake)) 709 if (alloc_block(bo)) 710 return 1; 711 712 DBG("%s 0x%lx bytes failed\n", __func__, bo->size); 713 714 return 0; 715 } 716 717 /*********************************************************************** 718 * Public functions 719 */ 720 721 /** 722 * Wait for hardware idle by emitting a fence and waiting for it. 723 */ 724 static void 725 drm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake *bufmgr_fake) 726 { 727 unsigned int cookie; 728 729 cookie = _fence_emit_internal(bufmgr_fake); 730 _fence_wait_internal(bufmgr_fake, cookie); 731 } 732 733 /** 734 * Wait for rendering to a buffer to complete. 735 * 736 * It is assumed that the batchbuffer which performed the rendering included 737 * the necessary flushing. 738 */ 739 static void 740 drm_intel_fake_bo_wait_rendering_locked(drm_intel_bo *bo) 741 { 742 drm_intel_bufmgr_fake *bufmgr_fake = 743 (drm_intel_bufmgr_fake *) bo->bufmgr; 744 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 745 746 if (bo_fake->block == NULL || !bo_fake->block->fenced) 747 return; 748 749 _fence_wait_internal(bufmgr_fake, bo_fake->block->fence); 750 } 751 752 static void 753 drm_intel_fake_bo_wait_rendering(drm_intel_bo *bo) 754 { 755 drm_intel_bufmgr_fake *bufmgr_fake = 756 (drm_intel_bufmgr_fake *) bo->bufmgr; 757 758 pthread_mutex_lock(&bufmgr_fake->lock); 759 drm_intel_fake_bo_wait_rendering_locked(bo); 760 pthread_mutex_unlock(&bufmgr_fake->lock); 761 } 762 763 /* Specifically ignore texture memory sharing. 764 * -- just evict everything 765 * -- and wait for idle 766 */ 767 drm_public void 768 drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr) 769 { 770 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 771 struct block *block, *tmp; 772 773 pthread_mutex_lock(&bufmgr_fake->lock); 774 775 bufmgr_fake->need_fence = 1; 776 bufmgr_fake->fail = 0; 777 778 /* Wait for hardware idle. We don't know where acceleration has been 779 * happening, so we'll need to wait anyway before letting anything get 780 * put on the card again. 781 */ 782 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 783 784 /* Check that we hadn't released the lock without having fenced the last 785 * set of buffers. 786 */ 787 assert(DRMLISTEMPTY(&bufmgr_fake->fenced)); 788 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 789 790 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 791 assert(_fence_test(bufmgr_fake, block->fence)); 792 set_dirty(block->bo); 793 } 794 795 pthread_mutex_unlock(&bufmgr_fake->lock); 796 } 797 798 static drm_intel_bo * 799 drm_intel_fake_bo_alloc(drm_intel_bufmgr *bufmgr, 800 const char *name, 801 unsigned long size, 802 unsigned int alignment) 803 { 804 drm_intel_bufmgr_fake *bufmgr_fake; 805 drm_intel_bo_fake *bo_fake; 806 807 bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 808 809 assert(size != 0); 810 811 bo_fake = calloc(1, sizeof(*bo_fake)); 812 if (!bo_fake) 813 return NULL; 814 815 bo_fake->bo.size = size; 816 bo_fake->bo.offset = -1; 817 bo_fake->bo.virtual = NULL; 818 bo_fake->bo.bufmgr = bufmgr; 819 bo_fake->refcount = 1; 820 821 /* Alignment must be a power of two */ 822 assert((alignment & (alignment - 1)) == 0); 823 if (alignment == 0) 824 alignment = 1; 825 bo_fake->alignment = alignment; 826 bo_fake->id = ++bufmgr_fake->buf_nr; 827 bo_fake->name = name; 828 bo_fake->flags = 0; 829 bo_fake->is_static = 0; 830 831 DBG("drm_bo_alloc: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name, 832 bo_fake->bo.size / 1024); 833 834 return &bo_fake->bo; 835 } 836 837 static drm_intel_bo * 838 drm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr, 839 const char *name, 840 int x, int y, int cpp, 841 uint32_t *tiling_mode, 842 unsigned long *pitch, 843 unsigned long flags) 844 { 845 unsigned long stride, aligned_y; 846 847 /* No runtime tiling support for fake. */ 848 *tiling_mode = I915_TILING_NONE; 849 850 /* Align it for being a render target. Shouldn't need anything else. */ 851 stride = x * cpp; 852 stride = ROUND_UP_TO(stride, 64); 853 854 /* 965 subspan loading alignment */ 855 aligned_y = ALIGN(y, 2); 856 857 *pitch = stride; 858 859 return drm_intel_fake_bo_alloc(bufmgr, name, stride * aligned_y, 860 4096); 861 } 862 863 drm_public drm_intel_bo * 864 drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, 865 const char *name, 866 unsigned long offset, 867 unsigned long size, void *virtual) 868 { 869 drm_intel_bufmgr_fake *bufmgr_fake; 870 drm_intel_bo_fake *bo_fake; 871 872 bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 873 874 assert(size != 0); 875 876 bo_fake = calloc(1, sizeof(*bo_fake)); 877 if (!bo_fake) 878 return NULL; 879 880 bo_fake->bo.size = size; 881 bo_fake->bo.offset = offset; 882 bo_fake->bo.virtual = virtual; 883 bo_fake->bo.bufmgr = bufmgr; 884 bo_fake->refcount = 1; 885 bo_fake->id = ++bufmgr_fake->buf_nr; 886 bo_fake->name = name; 887 bo_fake->flags = BM_PINNED; 888 bo_fake->is_static = 1; 889 890 DBG("drm_bo_alloc_static: (buf %d: %s, %lu kb)\n", bo_fake->id, 891 bo_fake->name, bo_fake->bo.size / 1024); 892 893 return &bo_fake->bo; 894 } 895 896 static void 897 drm_intel_fake_bo_reference(drm_intel_bo *bo) 898 { 899 drm_intel_bufmgr_fake *bufmgr_fake = 900 (drm_intel_bufmgr_fake *) bo->bufmgr; 901 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 902 903 pthread_mutex_lock(&bufmgr_fake->lock); 904 bo_fake->refcount++; 905 pthread_mutex_unlock(&bufmgr_fake->lock); 906 } 907 908 static void 909 drm_intel_fake_bo_reference_locked(drm_intel_bo *bo) 910 { 911 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 912 913 bo_fake->refcount++; 914 } 915 916 static void 917 drm_intel_fake_bo_unreference_locked(drm_intel_bo *bo) 918 { 919 drm_intel_bufmgr_fake *bufmgr_fake = 920 (drm_intel_bufmgr_fake *) bo->bufmgr; 921 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 922 int i; 923 924 if (--bo_fake->refcount == 0) { 925 assert(bo_fake->map_count == 0); 926 /* No remaining references, so free it */ 927 if (bo_fake->block) 928 free_block(bufmgr_fake, bo_fake->block, 1); 929 free_backing_store(bo); 930 931 for (i = 0; i < bo_fake->nr_relocs; i++) 932 drm_intel_fake_bo_unreference_locked(bo_fake->relocs[i]. 933 target_buf); 934 935 DBG("drm_bo_unreference: free buf %d %s\n", bo_fake->id, 936 bo_fake->name); 937 938 free(bo_fake->relocs); 939 free(bo); 940 } 941 } 942 943 static void 944 drm_intel_fake_bo_unreference(drm_intel_bo *bo) 945 { 946 drm_intel_bufmgr_fake *bufmgr_fake = 947 (drm_intel_bufmgr_fake *) bo->bufmgr; 948 949 pthread_mutex_lock(&bufmgr_fake->lock); 950 drm_intel_fake_bo_unreference_locked(bo); 951 pthread_mutex_unlock(&bufmgr_fake->lock); 952 } 953 954 /** 955 * Set the buffer as not requiring backing store, and instead get the callback 956 * invoked whenever it would be set dirty. 957 */ 958 drm_public void 959 drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo, 960 void (*invalidate_cb) (drm_intel_bo *bo, 961 void *ptr), 962 void *ptr) 963 { 964 drm_intel_bufmgr_fake *bufmgr_fake = 965 (drm_intel_bufmgr_fake *) bo->bufmgr; 966 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 967 968 pthread_mutex_lock(&bufmgr_fake->lock); 969 970 if (bo_fake->backing_store) 971 free_backing_store(bo); 972 973 bo_fake->flags |= BM_NO_BACKING_STORE; 974 975 DBG("disable_backing_store set buf %d dirty\n", bo_fake->id); 976 bo_fake->dirty = 1; 977 bo_fake->invalidate_cb = invalidate_cb; 978 bo_fake->invalidate_ptr = ptr; 979 980 /* Note that it is invalid right from the start. Also note 981 * invalidate_cb is called with the bufmgr locked, so cannot 982 * itself make bufmgr calls. 983 */ 984 if (invalidate_cb != NULL) 985 invalidate_cb(bo, ptr); 986 987 pthread_mutex_unlock(&bufmgr_fake->lock); 988 } 989 990 /** 991 * Map a buffer into bo->virtual, allocating either card memory space (If 992 * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary. 993 */ 994 static int 995 drm_intel_fake_bo_map_locked(drm_intel_bo *bo, int write_enable) 996 { 997 drm_intel_bufmgr_fake *bufmgr_fake = 998 (drm_intel_bufmgr_fake *) bo->bufmgr; 999 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1000 1001 /* Static buffers are always mapped. */ 1002 if (bo_fake->is_static) { 1003 if (bo_fake->card_dirty) { 1004 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1005 bo_fake->card_dirty = 0; 1006 } 1007 return 0; 1008 } 1009 1010 /* Allow recursive mapping. Mesa may recursively map buffers with 1011 * nested display loops, and it is used internally in bufmgr_fake 1012 * for relocation. 1013 */ 1014 if (bo_fake->map_count++ != 0) 1015 return 0; 1016 1017 { 1018 DBG("drm_bo_map: (buf %d: %s, %lu kb)\n", bo_fake->id, 1019 bo_fake->name, bo_fake->bo.size / 1024); 1020 1021 if (bo->virtual != NULL) { 1022 drmMsg("%s: already mapped\n", __func__); 1023 abort(); 1024 } else if (bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)) { 1025 1026 if (!bo_fake->block && !evict_and_alloc_block(bo)) { 1027 DBG("%s: alloc failed\n", __func__); 1028 bufmgr_fake->fail = 1; 1029 return 1; 1030 } else { 1031 assert(bo_fake->block); 1032 bo_fake->dirty = 0; 1033 1034 if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA) && 1035 bo_fake->block->fenced) { 1036 drm_intel_fake_bo_wait_rendering_locked 1037 (bo); 1038 } 1039 1040 bo->virtual = bo_fake->block->virtual; 1041 } 1042 } else { 1043 if (write_enable) 1044 set_dirty(bo); 1045 1046 if (bo_fake->backing_store == 0) 1047 alloc_backing_store(bo); 1048 1049 if ((bo_fake->card_dirty == 1) && bo_fake->block) { 1050 if (bo_fake->block->fenced) 1051 drm_intel_fake_bo_wait_rendering_locked 1052 (bo); 1053 1054 memcpy(bo_fake->backing_store, 1055 bo_fake->block->virtual, 1056 bo_fake->block->bo->size); 1057 bo_fake->card_dirty = 0; 1058 } 1059 1060 bo->virtual = bo_fake->backing_store; 1061 } 1062 } 1063 1064 return 0; 1065 } 1066 1067 static int 1068 drm_intel_fake_bo_map(drm_intel_bo *bo, int write_enable) 1069 { 1070 drm_intel_bufmgr_fake *bufmgr_fake = 1071 (drm_intel_bufmgr_fake *) bo->bufmgr; 1072 int ret; 1073 1074 pthread_mutex_lock(&bufmgr_fake->lock); 1075 ret = drm_intel_fake_bo_map_locked(bo, write_enable); 1076 pthread_mutex_unlock(&bufmgr_fake->lock); 1077 1078 return ret; 1079 } 1080 1081 static int 1082 drm_intel_fake_bo_unmap_locked(drm_intel_bo *bo) 1083 { 1084 drm_intel_bufmgr_fake *bufmgr_fake = 1085 (drm_intel_bufmgr_fake *) bo->bufmgr; 1086 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1087 1088 /* Static buffers are always mapped. */ 1089 if (bo_fake->is_static) 1090 return 0; 1091 1092 assert(bo_fake->map_count != 0); 1093 if (--bo_fake->map_count != 0) 1094 return 0; 1095 1096 DBG("drm_bo_unmap: (buf %d: %s, %lu kb)\n", bo_fake->id, bo_fake->name, 1097 bo_fake->bo.size / 1024); 1098 1099 bo->virtual = NULL; 1100 1101 return 0; 1102 } 1103 1104 static int drm_intel_fake_bo_unmap(drm_intel_bo *bo) 1105 { 1106 drm_intel_bufmgr_fake *bufmgr_fake = 1107 (drm_intel_bufmgr_fake *) bo->bufmgr; 1108 int ret; 1109 1110 pthread_mutex_lock(&bufmgr_fake->lock); 1111 ret = drm_intel_fake_bo_unmap_locked(bo); 1112 pthread_mutex_unlock(&bufmgr_fake->lock); 1113 1114 return ret; 1115 } 1116 1117 static int 1118 drm_intel_fake_bo_subdata(drm_intel_bo *bo, unsigned long offset, 1119 unsigned long size, const void *data) 1120 { 1121 int ret; 1122 1123 if (size == 0 || data == NULL) 1124 return 0; 1125 1126 ret = drm_intel_bo_map(bo, 1); 1127 if (ret) 1128 return ret; 1129 memcpy((unsigned char *)bo->virtual + offset, data, size); 1130 drm_intel_bo_unmap(bo); 1131 return 0; 1132 } 1133 1134 static void 1135 drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake) 1136 { 1137 struct block *block, *tmp; 1138 1139 bufmgr_fake->performed_rendering = 0; 1140 /* okay for ever BO that is on the HW kick it off. 1141 seriously not afraid of the POLICE right now */ 1142 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) { 1143 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 1144 1145 block->on_hardware = 0; 1146 free_block(bufmgr_fake, block, 0); 1147 bo_fake->block = NULL; 1148 bo_fake->validated = 0; 1149 if (!(bo_fake->flags & BM_NO_BACKING_STORE)) 1150 bo_fake->dirty = 1; 1151 } 1152 1153 } 1154 1155 static int 1156 drm_intel_fake_bo_validate(drm_intel_bo *bo) 1157 { 1158 drm_intel_bufmgr_fake *bufmgr_fake; 1159 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1160 1161 bufmgr_fake = (drm_intel_bufmgr_fake *) bo->bufmgr; 1162 1163 DBG("drm_bo_validate: (buf %d: %s, %lu kb)\n", bo_fake->id, 1164 bo_fake->name, bo_fake->bo.size / 1024); 1165 1166 /* Sanity check: Buffers should be unmapped before being validated. 1167 * This is not so much of a problem for bufmgr_fake, but TTM refuses, 1168 * and the problem is harder to debug there. 1169 */ 1170 assert(bo_fake->map_count == 0); 1171 1172 if (bo_fake->is_static) { 1173 /* Add it to the needs-fence list */ 1174 bufmgr_fake->need_fence = 1; 1175 return 0; 1176 } 1177 1178 /* Allocate the card memory */ 1179 if (!bo_fake->block && !evict_and_alloc_block(bo)) { 1180 bufmgr_fake->fail = 1; 1181 DBG("Failed to validate buf %d:%s\n", bo_fake->id, 1182 bo_fake->name); 1183 return -1; 1184 } 1185 1186 assert(bo_fake->block); 1187 assert(bo_fake->block->bo == &bo_fake->bo); 1188 1189 bo->offset = bo_fake->block->mem->ofs; 1190 1191 /* Upload the buffer contents if necessary */ 1192 if (bo_fake->dirty) { 1193 DBG("Upload dirty buf %d:%s, sz %lu offset 0x%x\n", bo_fake->id, 1194 bo_fake->name, bo->size, bo_fake->block->mem->ofs); 1195 1196 assert(!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))); 1197 1198 /* Actually, should be able to just wait for a fence on the 1199 * memory, which we would be tracking when we free it. Waiting 1200 * for idle is a sufficiently large hammer for now. 1201 */ 1202 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1203 1204 /* we may never have mapped this BO so it might not have any 1205 * backing store if this happens it should be rare, but 0 the 1206 * card memory in any case */ 1207 if (bo_fake->backing_store) 1208 memcpy(bo_fake->block->virtual, bo_fake->backing_store, 1209 bo->size); 1210 else 1211 memset(bo_fake->block->virtual, 0, bo->size); 1212 1213 bo_fake->dirty = 0; 1214 } 1215 1216 bo_fake->block->fenced = 0; 1217 bo_fake->block->on_hardware = 1; 1218 DRMLISTDEL(bo_fake->block); 1219 DRMLISTADDTAIL(bo_fake->block, &bufmgr_fake->on_hardware); 1220 1221 bo_fake->validated = 1; 1222 bufmgr_fake->need_fence = 1; 1223 1224 return 0; 1225 } 1226 1227 static void 1228 drm_intel_fake_fence_validated(drm_intel_bufmgr *bufmgr) 1229 { 1230 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1231 unsigned int cookie; 1232 1233 cookie = _fence_emit_internal(bufmgr_fake); 1234 fence_blocks(bufmgr_fake, cookie); 1235 1236 DBG("drm_fence_validated: 0x%08x cookie\n", cookie); 1237 } 1238 1239 static void 1240 drm_intel_fake_destroy(drm_intel_bufmgr *bufmgr) 1241 { 1242 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1243 1244 pthread_mutex_destroy(&bufmgr_fake->lock); 1245 mmDestroy(bufmgr_fake->heap); 1246 free(bufmgr); 1247 } 1248 1249 static int 1250 drm_intel_fake_emit_reloc(drm_intel_bo *bo, uint32_t offset, 1251 drm_intel_bo *target_bo, uint32_t target_offset, 1252 uint32_t read_domains, uint32_t write_domain) 1253 { 1254 drm_intel_bufmgr_fake *bufmgr_fake = 1255 (drm_intel_bufmgr_fake *) bo->bufmgr; 1256 struct fake_buffer_reloc *r; 1257 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1258 drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *) target_bo; 1259 int i; 1260 1261 pthread_mutex_lock(&bufmgr_fake->lock); 1262 1263 assert(bo); 1264 assert(target_bo); 1265 1266 if (bo_fake->relocs == NULL) { 1267 bo_fake->relocs = 1268 malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS); 1269 } 1270 1271 r = &bo_fake->relocs[bo_fake->nr_relocs++]; 1272 1273 assert(bo_fake->nr_relocs <= MAX_RELOCS); 1274 1275 drm_intel_fake_bo_reference_locked(target_bo); 1276 1277 if (!target_fake->is_static) { 1278 bo_fake->child_size += 1279 ALIGN(target_bo->size, target_fake->alignment); 1280 bo_fake->child_size += target_fake->child_size; 1281 } 1282 r->target_buf = target_bo; 1283 r->offset = offset; 1284 r->last_target_offset = target_bo->offset; 1285 r->delta = target_offset; 1286 r->read_domains = read_domains; 1287 r->write_domain = write_domain; 1288 1289 if (bufmgr_fake->debug) { 1290 /* Check that a conflicting relocation hasn't already been 1291 * emitted. 1292 */ 1293 for (i = 0; i < bo_fake->nr_relocs - 1; i++) { 1294 struct fake_buffer_reloc *r2 = &bo_fake->relocs[i]; 1295 1296 assert(r->offset != r2->offset); 1297 } 1298 } 1299 1300 pthread_mutex_unlock(&bufmgr_fake->lock); 1301 1302 return 0; 1303 } 1304 1305 /** 1306 * Incorporates the validation flags associated with each relocation into 1307 * the combined validation flags for the buffer on this batchbuffer submission. 1308 */ 1309 static void 1310 drm_intel_fake_calculate_domains(drm_intel_bo *bo) 1311 { 1312 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1313 int i; 1314 1315 for (i = 0; i < bo_fake->nr_relocs; i++) { 1316 struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1317 drm_intel_bo_fake *target_fake = 1318 (drm_intel_bo_fake *) r->target_buf; 1319 1320 /* Do the same for the tree of buffers we depend on */ 1321 drm_intel_fake_calculate_domains(r->target_buf); 1322 1323 target_fake->read_domains |= r->read_domains; 1324 target_fake->write_domain |= r->write_domain; 1325 } 1326 } 1327 1328 static int 1329 drm_intel_fake_reloc_and_validate_buffer(drm_intel_bo *bo) 1330 { 1331 drm_intel_bufmgr_fake *bufmgr_fake = 1332 (drm_intel_bufmgr_fake *) bo->bufmgr; 1333 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1334 int i, ret; 1335 1336 assert(bo_fake->map_count == 0); 1337 1338 for (i = 0; i < bo_fake->nr_relocs; i++) { 1339 struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1340 drm_intel_bo_fake *target_fake = 1341 (drm_intel_bo_fake *) r->target_buf; 1342 uint32_t reloc_data; 1343 1344 /* Validate the target buffer if that hasn't been done. */ 1345 if (!target_fake->validated) { 1346 ret = 1347 drm_intel_fake_reloc_and_validate_buffer(r->target_buf); 1348 if (ret != 0) { 1349 if (bo->virtual != NULL) 1350 drm_intel_fake_bo_unmap_locked(bo); 1351 return ret; 1352 } 1353 } 1354 1355 /* Calculate the value of the relocation entry. */ 1356 if (r->target_buf->offset != r->last_target_offset) { 1357 reloc_data = r->target_buf->offset + r->delta; 1358 1359 if (bo->virtual == NULL) 1360 drm_intel_fake_bo_map_locked(bo, 1); 1361 1362 *(uint32_t *) ((uint8_t *) bo->virtual + r->offset) = 1363 reloc_data; 1364 1365 r->last_target_offset = r->target_buf->offset; 1366 } 1367 } 1368 1369 if (bo->virtual != NULL) 1370 drm_intel_fake_bo_unmap_locked(bo); 1371 1372 if (bo_fake->write_domain != 0) { 1373 if (!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))) { 1374 if (bo_fake->backing_store == 0) 1375 alloc_backing_store(bo); 1376 } 1377 bo_fake->card_dirty = 1; 1378 bufmgr_fake->performed_rendering = 1; 1379 } 1380 1381 return drm_intel_fake_bo_validate(bo); 1382 } 1383 1384 static void 1385 drm_intel_bo_fake_post_submit(drm_intel_bo *bo) 1386 { 1387 drm_intel_bufmgr_fake *bufmgr_fake = 1388 (drm_intel_bufmgr_fake *) bo->bufmgr; 1389 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo; 1390 int i; 1391 1392 for (i = 0; i < bo_fake->nr_relocs; i++) { 1393 struct fake_buffer_reloc *r = &bo_fake->relocs[i]; 1394 drm_intel_bo_fake *target_fake = 1395 (drm_intel_bo_fake *) r->target_buf; 1396 1397 if (target_fake->validated) 1398 drm_intel_bo_fake_post_submit(r->target_buf); 1399 1400 DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n", 1401 bo_fake->name, (uint32_t) bo->offset, r->offset, 1402 target_fake->name, (uint32_t) r->target_buf->offset, 1403 r->delta); 1404 } 1405 1406 assert(bo_fake->map_count == 0); 1407 bo_fake->validated = 0; 1408 bo_fake->read_domains = 0; 1409 bo_fake->write_domain = 0; 1410 } 1411 1412 drm_public void 1413 drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr, 1414 int (*exec) (drm_intel_bo *bo, 1415 unsigned int used, 1416 void *priv), 1417 void *priv) 1418 { 1419 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1420 1421 bufmgr_fake->exec = exec; 1422 bufmgr_fake->exec_priv = priv; 1423 } 1424 1425 static int 1426 drm_intel_fake_bo_exec(drm_intel_bo *bo, int used, 1427 drm_clip_rect_t * cliprects, int num_cliprects, int DR4) 1428 { 1429 drm_intel_bufmgr_fake *bufmgr_fake = 1430 (drm_intel_bufmgr_fake *) bo->bufmgr; 1431 drm_intel_bo_fake *batch_fake = (drm_intel_bo_fake *) bo; 1432 struct drm_i915_batchbuffer batch; 1433 int ret; 1434 int retry_count = 0; 1435 1436 pthread_mutex_lock(&bufmgr_fake->lock); 1437 1438 bufmgr_fake->performed_rendering = 0; 1439 1440 drm_intel_fake_calculate_domains(bo); 1441 1442 batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND; 1443 1444 /* we've ran out of RAM so blow the whole lot away and retry */ 1445 restart: 1446 ret = drm_intel_fake_reloc_and_validate_buffer(bo); 1447 if (bufmgr_fake->fail == 1) { 1448 if (retry_count == 0) { 1449 retry_count++; 1450 drm_intel_fake_kick_all_locked(bufmgr_fake); 1451 bufmgr_fake->fail = 0; 1452 goto restart; 1453 } else /* dump out the memory here */ 1454 mmDumpMemInfo(bufmgr_fake->heap); 1455 } 1456 1457 assert(ret == 0); 1458 1459 if (bufmgr_fake->exec != NULL) { 1460 ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv); 1461 if (ret != 0) { 1462 pthread_mutex_unlock(&bufmgr_fake->lock); 1463 return ret; 1464 } 1465 } else { 1466 batch.start = bo->offset; 1467 batch.used = used; 1468 batch.cliprects = cliprects; 1469 batch.num_cliprects = num_cliprects; 1470 batch.DR1 = 0; 1471 batch.DR4 = DR4; 1472 1473 if (drmCommandWrite 1474 (bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch, 1475 sizeof(batch))) { 1476 drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno); 1477 pthread_mutex_unlock(&bufmgr_fake->lock); 1478 return -errno; 1479 } 1480 } 1481 1482 drm_intel_fake_fence_validated(bo->bufmgr); 1483 1484 drm_intel_bo_fake_post_submit(bo); 1485 1486 pthread_mutex_unlock(&bufmgr_fake->lock); 1487 1488 return 0; 1489 } 1490 1491 /** 1492 * Return an error if the list of BOs will exceed the aperture size. 1493 * 1494 * This is a rough guess and likely to fail, as during the validate sequence we 1495 * may place a buffer in an inopportune spot early on and then fail to fit 1496 * a set smaller than the aperture. 1497 */ 1498 static int 1499 drm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array, int count) 1500 { 1501 drm_intel_bufmgr_fake *bufmgr_fake = 1502 (drm_intel_bufmgr_fake *) bo_array[0]->bufmgr; 1503 unsigned int sz = 0; 1504 int i; 1505 1506 for (i = 0; i < count; i++) { 1507 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo_array[i]; 1508 1509 if (bo_fake == NULL) 1510 continue; 1511 1512 if (!bo_fake->is_static) 1513 sz += ALIGN(bo_array[i]->size, bo_fake->alignment); 1514 sz += bo_fake->child_size; 1515 } 1516 1517 if (sz > bufmgr_fake->size) { 1518 DBG("check_space: overflowed bufmgr size, %ukb vs %lukb\n", 1519 sz / 1024, bufmgr_fake->size / 1024); 1520 return -1; 1521 } 1522 1523 DBG("drm_check_space: sz %ukb vs bufgr %lukb\n", sz / 1024, 1524 bufmgr_fake->size / 1024); 1525 return 0; 1526 } 1527 1528 /** 1529 * Evicts all buffers, waiting for fences to pass and copying contents out 1530 * as necessary. 1531 * 1532 * Used by the X Server on LeaveVT, when the card memory is no longer our 1533 * own. 1534 */ 1535 drm_public void 1536 drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr) 1537 { 1538 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1539 struct block *block, *tmp; 1540 1541 pthread_mutex_lock(&bufmgr_fake->lock); 1542 1543 bufmgr_fake->need_fence = 1; 1544 bufmgr_fake->fail = 0; 1545 1546 /* Wait for hardware idle. We don't know where acceleration has been 1547 * happening, so we'll need to wait anyway before letting anything get 1548 * put on the card again. 1549 */ 1550 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake); 1551 1552 /* Check that we hadn't released the lock without having fenced the last 1553 * set of buffers. 1554 */ 1555 assert(DRMLISTEMPTY(&bufmgr_fake->fenced)); 1556 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware)); 1557 1558 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) { 1559 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo; 1560 /* Releases the memory, and memcpys dirty contents out if 1561 * necessary. 1562 */ 1563 free_block(bufmgr_fake, block, 0); 1564 bo_fake->block = NULL; 1565 } 1566 1567 pthread_mutex_unlock(&bufmgr_fake->lock); 1568 } 1569 1570 drm_public void 1571 drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr, 1572 volatile unsigned int 1573 *last_dispatch) 1574 { 1575 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr; 1576 1577 bufmgr_fake->last_dispatch = (volatile int *)last_dispatch; 1578 } 1579 1580 drm_public drm_intel_bufmgr * 1581 drm_intel_bufmgr_fake_init(int fd, unsigned long low_offset, 1582 void *low_virtual, unsigned long size, 1583 volatile unsigned int *last_dispatch) 1584 { 1585 drm_intel_bufmgr_fake *bufmgr_fake; 1586 1587 bufmgr_fake = calloc(1, sizeof(*bufmgr_fake)); 1588 1589 if (pthread_mutex_init(&bufmgr_fake->lock, NULL) != 0) { 1590 free(bufmgr_fake); 1591 return NULL; 1592 } 1593 1594 /* Initialize allocator */ 1595 DRMINITLISTHEAD(&bufmgr_fake->fenced); 1596 DRMINITLISTHEAD(&bufmgr_fake->on_hardware); 1597 DRMINITLISTHEAD(&bufmgr_fake->lru); 1598 1599 bufmgr_fake->low_offset = low_offset; 1600 bufmgr_fake->virtual = low_virtual; 1601 bufmgr_fake->size = size; 1602 bufmgr_fake->heap = mmInit(low_offset, size); 1603 1604 /* Hook in methods */ 1605 bufmgr_fake->bufmgr.bo_alloc = drm_intel_fake_bo_alloc; 1606 bufmgr_fake->bufmgr.bo_alloc_for_render = drm_intel_fake_bo_alloc; 1607 bufmgr_fake->bufmgr.bo_alloc_tiled = drm_intel_fake_bo_alloc_tiled; 1608 bufmgr_fake->bufmgr.bo_reference = drm_intel_fake_bo_reference; 1609 bufmgr_fake->bufmgr.bo_unreference = drm_intel_fake_bo_unreference; 1610 bufmgr_fake->bufmgr.bo_map = drm_intel_fake_bo_map; 1611 bufmgr_fake->bufmgr.bo_unmap = drm_intel_fake_bo_unmap; 1612 bufmgr_fake->bufmgr.bo_subdata = drm_intel_fake_bo_subdata; 1613 bufmgr_fake->bufmgr.bo_wait_rendering = 1614 drm_intel_fake_bo_wait_rendering; 1615 bufmgr_fake->bufmgr.bo_emit_reloc = drm_intel_fake_emit_reloc; 1616 bufmgr_fake->bufmgr.destroy = drm_intel_fake_destroy; 1617 bufmgr_fake->bufmgr.bo_exec = drm_intel_fake_bo_exec; 1618 bufmgr_fake->bufmgr.check_aperture_space = 1619 drm_intel_fake_check_aperture_space; 1620 bufmgr_fake->bufmgr.debug = 0; 1621 1622 bufmgr_fake->fd = fd; 1623 bufmgr_fake->last_dispatch = (volatile int *)last_dispatch; 1624 1625 return &bufmgr_fake->bufmgr; 1626 } 1627