1 /**************************************************************************
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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.
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.
47 #include "intel_bufmgr.h"
48 #include "intel_bufmgr_priv.h"
52 #include "libdrm_lists.h"
54 /* Support gcc's __FUNCTION__ for people using other compilers */
55 #if !defined(__GNUC__) && !defined(__FUNCTION__)
56 # define __FUNCTION__ __func__ /* C99 */
59 #define DBG(...) do { \
60 if (bufmgr_fake->bufmgr.debug) \
61 drmMsg(__VA_ARGS__); \
66 #define BM_NO_BACKING_STORE 0x00000001
67 #define BM_NO_FENCE_SUBDATA 0x00000002
68 #define BM_PINNED 0x00000004
70 /* Wrapper around mm.c's mem_block, which understands that you must
71 * wait for fences to expire before memory can be freed. This is
72 * specific to our use of memcpy for uploads - an upload that was
73 * processed through the command queue wouldn't need to care about
76 #define MAX_RELOCS 4096
78 struct fake_buffer_reloc {
79 /** Buffer object that the relocation points at. */
80 drm_intel_bo *target_buf;
81 /** Offset of the relocation entry within reloc_buf. */
84 * Cached value of the offset when we last performed this relocation.
86 uint32_t last_target_offset;
87 /** Value added to target_buf's offset to get the relocation entry. */
89 /** Cache domains the target buffer is read into. */
90 uint32_t read_domains;
91 /** Cache domain the target buffer will have dirty cachelines in. */
92 uint32_t write_domain;
96 struct block *next, *prev;
97 struct mem_block *mem; /* BM_MEM_AGP */
100 * Marks that the block is currently in the aperture and has yet to be
103 unsigned on_hardware:1;
105 * Marks that the block is currently fenced (being used by rendering)
106 * and can't be freed until @fence is passed.
110 /** Fence cookie for the block. */
111 unsigned fence; /* Split to read_fence, write_fence */
117 typedef struct _bufmgr_fake {
118 drm_intel_bufmgr bufmgr;
120 pthread_mutex_t lock;
122 unsigned long low_offset;
126 struct mem_block *heap;
128 unsigned buf_nr; /* for generating ids */
131 * List of blocks which are currently in the GART but haven't been
134 struct block on_hardware;
136 * List of blocks which are in the GART and have an active fence on
141 * List of blocks which have an expired fence and are ready to be
146 unsigned int last_fence;
149 unsigned need_fence:1;
153 * Driver callback to emit a fence, returning the cookie.
155 * This allows the driver to hook in a replacement for the DRM usage in
158 * Currently, this also requires that a write flush be emitted before
159 * emitting the fence, but this should change.
161 unsigned int (*fence_emit) (void *private);
162 /** Driver callback to wait for a fence cookie to have passed. */
163 void (*fence_wait) (unsigned int fence, void *private);
167 * Driver callback to execute a buffer.
169 * This allows the driver to hook in a replacement for the DRM usage in
172 int (*exec) (drm_intel_bo *bo, unsigned int used, void *priv);
175 /** Driver-supplied argument to driver callbacks */
178 * Pointer to kernel-updated sarea data for the last completed user irq
180 volatile int *last_dispatch;
186 int performed_rendering;
187 } drm_intel_bufmgr_fake;
189 typedef struct _drm_intel_bo_fake {
192 unsigned id; /* debug only */
197 * has the card written to this buffer - we make need to copy it back
199 unsigned card_dirty:1;
200 unsigned int refcount;
201 /* Flags may consist of any of the DRM_BO flags, plus
202 * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the
203 * first two driver private flags.
206 /** Cache domains the target buffer is read into. */
207 uint32_t read_domains;
208 /** Cache domain the target buffer will have dirty cachelines in. */
209 uint32_t write_domain;
211 unsigned int alignment;
212 int is_static, validated;
213 unsigned int map_count;
215 /** relocation list */
216 struct fake_buffer_reloc *relocs;
219 * Total size of the target_bos of this buffer.
221 * Used for estimation in check_aperture.
223 unsigned int child_size;
227 void (*invalidate_cb) (drm_intel_bo *bo, void *ptr);
228 void *invalidate_ptr;
231 static int clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake,
232 unsigned int fence_cookie);
234 #define MAXFENCE 0x7fffffff
237 FENCE_LTE(unsigned a, unsigned b)
242 if (a < b && b - a < (1 << 24))
245 if (a > b && MAXFENCE - a + b < (1 << 24))
252 drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr,
253 unsigned int (*emit) (void *priv),
254 void (*wait) (unsigned int fence,
258 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
260 bufmgr_fake->fence_emit = emit;
261 bufmgr_fake->fence_wait = wait;
262 bufmgr_fake->fence_priv = priv;
266 _fence_emit_internal(drm_intel_bufmgr_fake *bufmgr_fake)
268 struct drm_i915_irq_emit ie;
271 if (bufmgr_fake->fence_emit != NULL) {
272 seq = bufmgr_fake->fence_emit(bufmgr_fake->fence_priv);
277 ret = drmCommandWriteRead(bufmgr_fake->fd, DRM_I915_IRQ_EMIT,
280 drmMsg("%s: drm_i915_irq_emit: %d\n", __FUNCTION__, ret);
284 DBG("emit 0x%08x\n", seq);
289 _fence_wait_internal(drm_intel_bufmgr_fake *bufmgr_fake, int seq)
291 struct drm_i915_irq_wait iw;
292 int hw_seq, busy_count = 0;
296 if (bufmgr_fake->fence_wait != NULL) {
297 bufmgr_fake->fence_wait(seq, bufmgr_fake->fence_priv);
298 clear_fenced(bufmgr_fake, seq);
304 DBG("wait 0x%08x\n", iw.irq_seq);
306 /* The kernel IRQ_WAIT implementation is all sorts of broken.
307 * 1) It returns 1 to 0x7fffffff instead of using the full 32-bit
309 * 2) It returns 0 if hw_seq >= seq, not seq - hw_seq < 0 on the 32-bit
311 * 3) It waits if seq < hw_seq, not seq - hw_seq > 0 on the 32-bit
313 * 4) It returns -EBUSY in 3 seconds even if the hardware is still
314 * successfully chewing through buffers.
316 * Assume that in userland we treat sequence numbers as ints, which
317 * makes some of the comparisons convenient, since the sequence
318 * numbers are all postive signed integers.
320 * From this we get several cases we need to handle. Here's a timeline.
321 * 0x2 0x7 0x7ffffff8 0x7ffffffd
323 * ------------------------------------------------------------
325 * A) Normal wait for hw to catch up
328 * ------------------------------------------------------------
329 * seq - hw_seq = 5. If we call IRQ_WAIT, it will wait for hw to
332 * B) Normal wait for a sequence number that's already passed.
335 * ------------------------------------------------------------
336 * seq - hw_seq = -5. If we call IRQ_WAIT, it returns 0 quickly.
338 * C) Hardware has already wrapped around ahead of us
341 * ------------------------------------------------------------
342 * seq - hw_seq = 0x80000000 - 5. If we called IRQ_WAIT, it would wait
343 * for hw_seq >= seq, which may never occur. Thus, we want to catch
344 * this in userland and return 0.
346 * D) We've wrapped around ahead of the hardware.
349 * ------------------------------------------------------------
350 * seq - hw_seq = -(0x80000000 - 5). If we called IRQ_WAIT, it would
351 * return 0 quickly because hw_seq >= seq, even though the hardware
352 * isn't caught up. Thus, we need to catch this early return in
353 * userland and bother the kernel until the hardware really does
356 * E) Hardware might wrap after we test in userland.
359 * ------------------------------------------------------------
360 * seq - hw_seq = 5. If we call IRQ_WAIT, it will likely see seq >=
361 * hw_seq and wait. However, suppose hw_seq wraps before we make it
362 * into the kernel. The kernel sees hw_seq >= seq and waits for 3
363 * seconds then returns -EBUSY. This is case C). We should catch
364 * this and then return successfully.
366 * F) Hardware might take a long time on a buffer.
369 * -------------------------------------------------------------------
370 * seq - hw_seq = 5. If we call IRQ_WAIT, if sequence 2 through 5
371 * take too long, it will return -EBUSY. Batchbuffers in the
372 * gltestperf demo were seen to take up to 7 seconds. We should
373 * catch early -EBUSY return and keep trying.
377 /* Keep a copy of last_dispatch so that if the wait -EBUSYs
378 * because the hardware didn't catch up in 3 seconds, we can
379 * see if it at least made progress and retry.
381 hw_seq = *bufmgr_fake->last_dispatch;
384 if (seq - hw_seq > 0x40000000)
387 ret = drmCommandWrite(bufmgr_fake->fd, DRM_I915_IRQ_WAIT,
390 kernel_lied = (ret == 0) && (seq - *bufmgr_fake->last_dispatch <
395 && (seq - *bufmgr_fake->last_dispatch > 0x40000000))
398 /* Catch case F: Allow up to 15 seconds chewing on one buffer. */
399 if ((ret == -EBUSY) && (hw_seq != *bufmgr_fake->last_dispatch))
403 } while (kernel_lied || ret == -EAGAIN || ret == -EINTR ||
404 (ret == -EBUSY && busy_count < 5));
407 drmMsg("%s:%d: Error waiting for fence: %s.\n", __FILE__,
408 __LINE__, strerror(-ret));
411 clear_fenced(bufmgr_fake, seq);
415 _fence_test(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)
417 /* Slight problem with wrap-around:
419 return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence);
423 * Allocate a memory manager block for the buffer.
426 alloc_block(drm_intel_bo *bo)
428 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
429 drm_intel_bufmgr_fake *bufmgr_fake =
430 (drm_intel_bufmgr_fake *) bo->bufmgr;
431 struct block *block = (struct block *)calloc(sizeof *block, 1);
432 unsigned int align_log2 = ffs(bo_fake->alignment) - 1;
438 sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1);
440 block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0);
446 DRMINITLISTHEAD(block);
448 /* Insert at head or at tail??? */
449 DRMLISTADDTAIL(block, &bufmgr_fake->lru);
451 block->virtual = (uint8_t *) bufmgr_fake->virtual +
452 block->mem->ofs - bufmgr_fake->low_offset;
455 bo_fake->block = block;
460 /* Release the card storage associated with buf:
463 free_block(drm_intel_bufmgr_fake *bufmgr_fake, struct block *block,
466 drm_intel_bo_fake *bo_fake;
467 DBG("free block %p %08x %d %d\n", block, block->mem->ofs,
468 block->on_hardware, block->fenced);
473 bo_fake = (drm_intel_bo_fake *) block->bo;
475 if (bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE))
478 if (!skip_dirty_copy && (bo_fake->card_dirty == 1)) {
479 memcpy(bo_fake->backing_store, block->virtual, block->bo->size);
480 bo_fake->card_dirty = 0;
484 if (block->on_hardware) {
486 } else if (block->fenced) {
489 DBG(" - free immediately\n");
492 mmFreeMem(block->mem);
498 alloc_backing_store(drm_intel_bo *bo)
500 drm_intel_bufmgr_fake *bufmgr_fake =
501 (drm_intel_bufmgr_fake *) bo->bufmgr;
502 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
503 assert(!bo_fake->backing_store);
504 assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)));
506 bo_fake->backing_store = malloc(bo->size);
508 DBG("alloc_backing - buf %d %p %d\n", bo_fake->id,
509 bo_fake->backing_store, bo->size);
510 assert(bo_fake->backing_store);
514 free_backing_store(drm_intel_bo *bo)
516 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
518 if (bo_fake->backing_store) {
519 assert(!(bo_fake->flags & (BM_PINNED | BM_NO_BACKING_STORE)));
520 free(bo_fake->backing_store);
521 bo_fake->backing_store = NULL;
526 set_dirty(drm_intel_bo *bo)
528 drm_intel_bufmgr_fake *bufmgr_fake =
529 (drm_intel_bufmgr_fake *) bo->bufmgr;
530 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
532 if (bo_fake->flags & BM_NO_BACKING_STORE
533 && bo_fake->invalidate_cb != NULL)
534 bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr);
536 assert(!(bo_fake->flags & BM_PINNED));
538 DBG("set_dirty - buf %d\n", bo_fake->id);
543 evict_lru(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int max_fence)
545 struct block *block, *tmp;
547 DBG("%s\n", __FUNCTION__);
549 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
550 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
552 if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
555 if (block->fence && max_fence && !FENCE_LTE(block->fence,
559 set_dirty(&bo_fake->bo);
560 bo_fake->block = NULL;
562 free_block(bufmgr_fake, block, 0);
570 evict_mru(drm_intel_bufmgr_fake *bufmgr_fake)
572 struct block *block, *tmp;
574 DBG("%s\n", __FUNCTION__);
576 DRMLISTFOREACHSAFEREVERSE(block, tmp, &bufmgr_fake->lru) {
577 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
579 if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA))
582 set_dirty(&bo_fake->bo);
583 bo_fake->block = NULL;
585 free_block(bufmgr_fake, block, 0);
593 * Removes all objects from the fenced list older than the given fence.
596 clear_fenced(drm_intel_bufmgr_fake *bufmgr_fake, unsigned int fence_cookie)
598 struct block *block, *tmp;
601 bufmgr_fake->last_fence = fence_cookie;
602 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->fenced) {
603 assert(block->fenced);
605 if (_fence_test(bufmgr_fake, block->fence)) {
610 DBG("delayed free: offset %x sz %x\n",
611 block->mem->ofs, block->mem->size);
613 mmFreeMem(block->mem);
616 DBG("return to lru: offset %x sz %x\n",
617 block->mem->ofs, block->mem->size);
619 DRMLISTADDTAIL(block, &bufmgr_fake->lru);
624 /* Blocks are ordered by fence, so if one fails, all
625 * from here will fail also:
627 DBG("fence not passed: offset %x sz %x %d %d \n",
628 block->mem->ofs, block->mem->size, block->fence,
629 bufmgr_fake->last_fence);
634 DBG("%s: %d\n", __FUNCTION__, ret);
639 fence_blocks(drm_intel_bufmgr_fake *bufmgr_fake, unsigned fence)
641 struct block *block, *tmp;
643 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) {
644 DBG("Fence block %p (sz 0x%x ofs %x buf %p) with fence %d\n",
645 block, block->mem->size, block->mem->ofs, block->bo, fence);
646 block->fence = fence;
648 block->on_hardware = 0;
651 /* Move to tail of pending list here
654 DRMLISTADDTAIL(block, &bufmgr_fake->fenced);
657 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
661 evict_and_alloc_block(drm_intel_bo *bo)
663 drm_intel_bufmgr_fake *bufmgr_fake =
664 (drm_intel_bufmgr_fake *) bo->bufmgr;
665 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
667 assert(bo_fake->block == NULL);
669 /* Search for already free memory:
674 /* If we're not thrashing, allow lru eviction to dig deeper into
675 * recently used textures. We'll probably be thrashing soon:
677 if (!bufmgr_fake->thrashing) {
678 while (evict_lru(bufmgr_fake, 0))
683 /* Keep thrashing counter alive?
685 if (bufmgr_fake->thrashing)
686 bufmgr_fake->thrashing = 20;
688 /* Wait on any already pending fences - here we are waiting for any
689 * freed memory that has been submitted to hardware and fenced to
692 while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) {
693 uint32_t fence = bufmgr_fake->fenced.next->fence;
694 _fence_wait_internal(bufmgr_fake, fence);
700 if (!DRMLISTEMPTY(&bufmgr_fake->on_hardware)) {
701 while (!DRMLISTEMPTY(&bufmgr_fake->fenced)) {
702 uint32_t fence = bufmgr_fake->fenced.next->fence;
703 _fence_wait_internal(bufmgr_fake, fence);
706 if (!bufmgr_fake->thrashing) {
709 bufmgr_fake->thrashing = 20;
715 while (evict_mru(bufmgr_fake))
719 DBG("%s 0x%x bytes failed\n", __FUNCTION__, bo->size);
724 /***********************************************************************
729 * Wait for hardware idle by emitting a fence and waiting for it.
732 drm_intel_bufmgr_fake_wait_idle(drm_intel_bufmgr_fake *bufmgr_fake)
736 cookie = _fence_emit_internal(bufmgr_fake);
737 _fence_wait_internal(bufmgr_fake, cookie);
741 * Wait for rendering to a buffer to complete.
743 * It is assumed that the bathcbuffer which performed the rendering included
744 * the necessary flushing.
747 drm_intel_fake_bo_wait_rendering_locked(drm_intel_bo *bo)
749 drm_intel_bufmgr_fake *bufmgr_fake =
750 (drm_intel_bufmgr_fake *) bo->bufmgr;
751 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
753 if (bo_fake->block == NULL || !bo_fake->block->fenced)
756 _fence_wait_internal(bufmgr_fake, bo_fake->block->fence);
760 drm_intel_fake_bo_wait_rendering(drm_intel_bo *bo)
762 drm_intel_bufmgr_fake *bufmgr_fake =
763 (drm_intel_bufmgr_fake *) bo->bufmgr;
765 pthread_mutex_lock(&bufmgr_fake->lock);
766 drm_intel_fake_bo_wait_rendering_locked(bo);
767 pthread_mutex_unlock(&bufmgr_fake->lock);
770 /* Specifically ignore texture memory sharing.
771 * -- just evict everything
772 * -- and wait for idle
775 drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr)
777 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
778 struct block *block, *tmp;
780 pthread_mutex_lock(&bufmgr_fake->lock);
782 bufmgr_fake->need_fence = 1;
783 bufmgr_fake->fail = 0;
785 /* Wait for hardware idle. We don't know where acceleration has been
786 * happening, so we'll need to wait anyway before letting anything get
787 * put on the card again.
789 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
791 /* Check that we hadn't released the lock without having fenced the last
794 assert(DRMLISTEMPTY(&bufmgr_fake->fenced));
795 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
797 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
798 assert(_fence_test(bufmgr_fake, block->fence));
799 set_dirty(block->bo);
802 pthread_mutex_unlock(&bufmgr_fake->lock);
805 static drm_intel_bo *
806 drm_intel_fake_bo_alloc(drm_intel_bufmgr *bufmgr,
809 unsigned int alignment)
811 drm_intel_bufmgr_fake *bufmgr_fake;
812 drm_intel_bo_fake *bo_fake;
814 bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
818 bo_fake = calloc(1, sizeof(*bo_fake));
822 bo_fake->bo.size = size;
823 bo_fake->bo.offset = -1;
824 bo_fake->bo.virtual = NULL;
825 bo_fake->bo.bufmgr = bufmgr;
826 bo_fake->refcount = 1;
828 /* Alignment must be a power of two */
829 assert((alignment & (alignment - 1)) == 0);
832 bo_fake->alignment = alignment;
833 bo_fake->id = ++bufmgr_fake->buf_nr;
834 bo_fake->name = name;
836 bo_fake->is_static = 0;
838 DBG("drm_bo_alloc: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
839 bo_fake->bo.size / 1024);
844 static drm_intel_bo *
845 drm_intel_fake_bo_alloc_tiled(drm_intel_bufmgr * bufmgr,
847 int x, int y, int cpp,
848 uint32_t *tiling_mode,
849 unsigned long *pitch,
852 unsigned long stride, aligned_y;
854 /* No runtime tiling support for fake. */
855 *tiling_mode = I915_TILING_NONE;
857 /* Align it for being a render target. Shouldn't need anything else. */
859 stride = ROUND_UP_TO(stride, 64);
861 /* 965 subspan loading alignment */
862 aligned_y = ALIGN(y, 2);
866 return drm_intel_fake_bo_alloc(bufmgr, name, stride * aligned_y,
871 drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr,
873 unsigned long offset,
874 unsigned long size, void *virtual)
876 drm_intel_bufmgr_fake *bufmgr_fake;
877 drm_intel_bo_fake *bo_fake;
879 bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
883 bo_fake = calloc(1, sizeof(*bo_fake));
887 bo_fake->bo.size = size;
888 bo_fake->bo.offset = offset;
889 bo_fake->bo.virtual = virtual;
890 bo_fake->bo.bufmgr = bufmgr;
891 bo_fake->refcount = 1;
892 bo_fake->id = ++bufmgr_fake->buf_nr;
893 bo_fake->name = name;
894 bo_fake->flags = BM_PINNED;
895 bo_fake->is_static = 1;
897 DBG("drm_bo_alloc_static: (buf %d: %s, %d kb)\n", bo_fake->id,
898 bo_fake->name, bo_fake->bo.size / 1024);
904 drm_intel_fake_bo_reference(drm_intel_bo *bo)
906 drm_intel_bufmgr_fake *bufmgr_fake =
907 (drm_intel_bufmgr_fake *) bo->bufmgr;
908 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
910 pthread_mutex_lock(&bufmgr_fake->lock);
912 pthread_mutex_unlock(&bufmgr_fake->lock);
916 drm_intel_fake_bo_reference_locked(drm_intel_bo *bo)
918 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
924 drm_intel_fake_bo_unreference_locked(drm_intel_bo *bo)
926 drm_intel_bufmgr_fake *bufmgr_fake =
927 (drm_intel_bufmgr_fake *) bo->bufmgr;
928 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
931 if (--bo_fake->refcount == 0) {
932 assert(bo_fake->map_count == 0);
933 /* No remaining references, so free it */
935 free_block(bufmgr_fake, bo_fake->block, 1);
936 free_backing_store(bo);
938 for (i = 0; i < bo_fake->nr_relocs; i++)
939 drm_intel_fake_bo_unreference_locked(bo_fake->relocs[i].
942 DBG("drm_bo_unreference: free buf %d %s\n", bo_fake->id,
945 free(bo_fake->relocs);
951 drm_intel_fake_bo_unreference(drm_intel_bo *bo)
953 drm_intel_bufmgr_fake *bufmgr_fake =
954 (drm_intel_bufmgr_fake *) bo->bufmgr;
956 pthread_mutex_lock(&bufmgr_fake->lock);
957 drm_intel_fake_bo_unreference_locked(bo);
958 pthread_mutex_unlock(&bufmgr_fake->lock);
962 * Set the buffer as not requiring backing store, and instead get the callback
963 * invoked whenever it would be set dirty.
966 drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo,
967 void (*invalidate_cb) (drm_intel_bo *bo,
971 drm_intel_bufmgr_fake *bufmgr_fake =
972 (drm_intel_bufmgr_fake *) bo->bufmgr;
973 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
975 pthread_mutex_lock(&bufmgr_fake->lock);
977 if (bo_fake->backing_store)
978 free_backing_store(bo);
980 bo_fake->flags |= BM_NO_BACKING_STORE;
982 DBG("disable_backing_store set buf %d dirty\n", bo_fake->id);
984 bo_fake->invalidate_cb = invalidate_cb;
985 bo_fake->invalidate_ptr = ptr;
987 /* Note that it is invalid right from the start. Also note
988 * invalidate_cb is called with the bufmgr locked, so cannot
989 * itself make bufmgr calls.
991 if (invalidate_cb != NULL)
992 invalidate_cb(bo, ptr);
994 pthread_mutex_unlock(&bufmgr_fake->lock);
998 * Map a buffer into bo->virtual, allocating either card memory space (If
999 * BM_NO_BACKING_STORE or BM_PINNED) or backing store, as necessary.
1002 drm_intel_fake_bo_map_locked(drm_intel_bo *bo, int write_enable)
1004 drm_intel_bufmgr_fake *bufmgr_fake =
1005 (drm_intel_bufmgr_fake *) bo->bufmgr;
1006 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1008 /* Static buffers are always mapped. */
1009 if (bo_fake->is_static) {
1010 if (bo_fake->card_dirty) {
1011 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1012 bo_fake->card_dirty = 0;
1017 /* Allow recursive mapping. Mesa may recursively map buffers with
1018 * nested display loops, and it is used internally in bufmgr_fake
1021 if (bo_fake->map_count++ != 0)
1025 DBG("drm_bo_map: (buf %d: %s, %d kb)\n", bo_fake->id,
1026 bo_fake->name, bo_fake->bo.size / 1024);
1028 if (bo->virtual != NULL) {
1029 drmMsg("%s: already mapped\n", __FUNCTION__);
1031 } else if (bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)) {
1033 if (!bo_fake->block && !evict_and_alloc_block(bo)) {
1034 DBG("%s: alloc failed\n", __FUNCTION__);
1035 bufmgr_fake->fail = 1;
1038 assert(bo_fake->block);
1041 if (!(bo_fake->flags & BM_NO_FENCE_SUBDATA) &&
1042 bo_fake->block->fenced) {
1043 drm_intel_fake_bo_wait_rendering_locked
1047 bo->virtual = bo_fake->block->virtual;
1053 if (bo_fake->backing_store == 0)
1054 alloc_backing_store(bo);
1056 if ((bo_fake->card_dirty == 1) && bo_fake->block) {
1057 if (bo_fake->block->fenced)
1058 drm_intel_fake_bo_wait_rendering_locked
1061 memcpy(bo_fake->backing_store,
1062 bo_fake->block->virtual,
1063 bo_fake->block->bo->size);
1064 bo_fake->card_dirty = 0;
1067 bo->virtual = bo_fake->backing_store;
1075 drm_intel_fake_bo_map(drm_intel_bo *bo, int write_enable)
1077 drm_intel_bufmgr_fake *bufmgr_fake =
1078 (drm_intel_bufmgr_fake *) bo->bufmgr;
1081 pthread_mutex_lock(&bufmgr_fake->lock);
1082 ret = drm_intel_fake_bo_map_locked(bo, write_enable);
1083 pthread_mutex_unlock(&bufmgr_fake->lock);
1089 drm_intel_fake_bo_unmap_locked(drm_intel_bo *bo)
1091 drm_intel_bufmgr_fake *bufmgr_fake =
1092 (drm_intel_bufmgr_fake *) bo->bufmgr;
1093 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1095 /* Static buffers are always mapped. */
1096 if (bo_fake->is_static)
1099 assert(bo_fake->map_count != 0);
1100 if (--bo_fake->map_count != 0)
1103 DBG("drm_bo_unmap: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
1104 bo_fake->bo.size / 1024);
1111 static int drm_intel_fake_bo_unmap(drm_intel_bo *bo)
1113 drm_intel_bufmgr_fake *bufmgr_fake =
1114 (drm_intel_bufmgr_fake *) bo->bufmgr;
1117 pthread_mutex_lock(&bufmgr_fake->lock);
1118 ret = drm_intel_fake_bo_unmap_locked(bo);
1119 pthread_mutex_unlock(&bufmgr_fake->lock);
1125 drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake)
1127 struct block *block, *tmp;
1129 bufmgr_fake->performed_rendering = 0;
1130 /* okay for ever BO that is on the HW kick it off.
1131 seriously not afraid of the POLICE right now */
1132 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->on_hardware) {
1133 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
1135 block->on_hardware = 0;
1136 free_block(bufmgr_fake, block, 0);
1137 bo_fake->block = NULL;
1138 bo_fake->validated = 0;
1139 if (!(bo_fake->flags & BM_NO_BACKING_STORE))
1146 drm_intel_fake_bo_validate(drm_intel_bo *bo)
1148 drm_intel_bufmgr_fake *bufmgr_fake;
1149 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1151 bufmgr_fake = (drm_intel_bufmgr_fake *) bo->bufmgr;
1153 DBG("drm_bo_validate: (buf %d: %s, %d kb)\n", bo_fake->id,
1154 bo_fake->name, bo_fake->bo.size / 1024);
1156 /* Sanity check: Buffers should be unmapped before being validated.
1157 * This is not so much of a problem for bufmgr_fake, but TTM refuses,
1158 * and the problem is harder to debug there.
1160 assert(bo_fake->map_count == 0);
1162 if (bo_fake->is_static) {
1163 /* Add it to the needs-fence list */
1164 bufmgr_fake->need_fence = 1;
1168 /* Allocate the card memory */
1169 if (!bo_fake->block && !evict_and_alloc_block(bo)) {
1170 bufmgr_fake->fail = 1;
1171 DBG("Failed to validate buf %d:%s\n", bo_fake->id,
1176 assert(bo_fake->block);
1177 assert(bo_fake->block->bo == &bo_fake->bo);
1179 bo->offset = bo_fake->block->mem->ofs;
1181 /* Upload the buffer contents if necessary */
1182 if (bo_fake->dirty) {
1183 DBG("Upload dirty buf %d:%s, sz %d offset 0x%x\n", bo_fake->id,
1184 bo_fake->name, bo->size, bo_fake->block->mem->ofs);
1186 assert(!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED)));
1188 /* Actually, should be able to just wait for a fence on the
1189 * mmory, hich we would be tracking when we free it. Waiting
1190 * for idle is a sufficiently large hammer for now.
1192 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1194 /* we may never have mapped this BO so it might not have any
1195 * backing store if this happens it should be rare, but 0 the
1196 * card memory in any case */
1197 if (bo_fake->backing_store)
1198 memcpy(bo_fake->block->virtual, bo_fake->backing_store,
1201 memset(bo_fake->block->virtual, 0, bo->size);
1206 bo_fake->block->fenced = 0;
1207 bo_fake->block->on_hardware = 1;
1208 DRMLISTDEL(bo_fake->block);
1209 DRMLISTADDTAIL(bo_fake->block, &bufmgr_fake->on_hardware);
1211 bo_fake->validated = 1;
1212 bufmgr_fake->need_fence = 1;
1218 drm_intel_fake_fence_validated(drm_intel_bufmgr *bufmgr)
1220 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1221 unsigned int cookie;
1223 cookie = _fence_emit_internal(bufmgr_fake);
1224 fence_blocks(bufmgr_fake, cookie);
1226 DBG("drm_fence_validated: 0x%08x cookie\n", cookie);
1230 drm_intel_fake_destroy(drm_intel_bufmgr *bufmgr)
1232 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1234 pthread_mutex_destroy(&bufmgr_fake->lock);
1235 mmDestroy(bufmgr_fake->heap);
1240 drm_intel_fake_emit_reloc(drm_intel_bo *bo, uint32_t offset,
1241 drm_intel_bo *target_bo, uint32_t target_offset,
1242 uint32_t read_domains, uint32_t write_domain)
1244 drm_intel_bufmgr_fake *bufmgr_fake =
1245 (drm_intel_bufmgr_fake *) bo->bufmgr;
1246 struct fake_buffer_reloc *r;
1247 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1248 drm_intel_bo_fake *target_fake = (drm_intel_bo_fake *) target_bo;
1251 pthread_mutex_lock(&bufmgr_fake->lock);
1256 if (bo_fake->relocs == NULL) {
1258 malloc(sizeof(struct fake_buffer_reloc) * MAX_RELOCS);
1261 r = &bo_fake->relocs[bo_fake->nr_relocs++];
1263 assert(bo_fake->nr_relocs <= MAX_RELOCS);
1265 drm_intel_fake_bo_reference_locked(target_bo);
1267 if (!target_fake->is_static) {
1268 bo_fake->child_size +=
1269 ALIGN(target_bo->size, target_fake->alignment);
1270 bo_fake->child_size += target_fake->child_size;
1272 r->target_buf = target_bo;
1274 r->last_target_offset = target_bo->offset;
1275 r->delta = target_offset;
1276 r->read_domains = read_domains;
1277 r->write_domain = write_domain;
1279 if (bufmgr_fake->debug) {
1280 /* Check that a conflicting relocation hasn't already been
1283 for (i = 0; i < bo_fake->nr_relocs - 1; i++) {
1284 struct fake_buffer_reloc *r2 = &bo_fake->relocs[i];
1286 assert(r->offset != r2->offset);
1290 pthread_mutex_unlock(&bufmgr_fake->lock);
1296 * Incorporates the validation flags associated with each relocation into
1297 * the combined validation flags for the buffer on this batchbuffer submission.
1300 drm_intel_fake_calculate_domains(drm_intel_bo *bo)
1302 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1305 for (i = 0; i < bo_fake->nr_relocs; i++) {
1306 struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1307 drm_intel_bo_fake *target_fake =
1308 (drm_intel_bo_fake *) r->target_buf;
1310 /* Do the same for the tree of buffers we depend on */
1311 drm_intel_fake_calculate_domains(r->target_buf);
1313 target_fake->read_domains |= r->read_domains;
1314 target_fake->write_domain |= r->write_domain;
1319 drm_intel_fake_reloc_and_validate_buffer(drm_intel_bo *bo)
1321 drm_intel_bufmgr_fake *bufmgr_fake =
1322 (drm_intel_bufmgr_fake *) bo->bufmgr;
1323 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1326 assert(bo_fake->map_count == 0);
1328 for (i = 0; i < bo_fake->nr_relocs; i++) {
1329 struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1330 drm_intel_bo_fake *target_fake =
1331 (drm_intel_bo_fake *) r->target_buf;
1332 uint32_t reloc_data;
1334 /* Validate the target buffer if that hasn't been done. */
1335 if (!target_fake->validated) {
1337 drm_intel_fake_reloc_and_validate_buffer(r->target_buf);
1339 if (bo->virtual != NULL)
1340 drm_intel_fake_bo_unmap_locked(bo);
1345 /* Calculate the value of the relocation entry. */
1346 if (r->target_buf->offset != r->last_target_offset) {
1347 reloc_data = r->target_buf->offset + r->delta;
1349 if (bo->virtual == NULL)
1350 drm_intel_fake_bo_map_locked(bo, 1);
1352 *(uint32_t *) ((uint8_t *) bo->virtual + r->offset) =
1355 r->last_target_offset = r->target_buf->offset;
1359 if (bo->virtual != NULL)
1360 drm_intel_fake_bo_unmap_locked(bo);
1362 if (bo_fake->write_domain != 0) {
1363 if (!(bo_fake->flags & (BM_NO_BACKING_STORE | BM_PINNED))) {
1364 if (bo_fake->backing_store == 0)
1365 alloc_backing_store(bo);
1367 bo_fake->card_dirty = 1;
1368 bufmgr_fake->performed_rendering = 1;
1371 return drm_intel_fake_bo_validate(bo);
1375 drm_intel_bo_fake_post_submit(drm_intel_bo *bo)
1377 drm_intel_bufmgr_fake *bufmgr_fake =
1378 (drm_intel_bufmgr_fake *) bo->bufmgr;
1379 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo;
1382 for (i = 0; i < bo_fake->nr_relocs; i++) {
1383 struct fake_buffer_reloc *r = &bo_fake->relocs[i];
1384 drm_intel_bo_fake *target_fake =
1385 (drm_intel_bo_fake *) r->target_buf;
1387 if (target_fake->validated)
1388 drm_intel_bo_fake_post_submit(r->target_buf);
1390 DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n",
1391 bo_fake->name, (uint32_t) bo->offset, r->offset,
1392 target_fake->name, (uint32_t) r->target_buf->offset,
1396 assert(bo_fake->map_count == 0);
1397 bo_fake->validated = 0;
1398 bo_fake->read_domains = 0;
1399 bo_fake->write_domain = 0;
1403 drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr,
1404 int (*exec) (drm_intel_bo *bo,
1409 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1411 bufmgr_fake->exec = exec;
1412 bufmgr_fake->exec_priv = priv;
1416 drm_intel_fake_bo_exec(drm_intel_bo *bo, int used,
1417 drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
1419 drm_intel_bufmgr_fake *bufmgr_fake =
1420 (drm_intel_bufmgr_fake *) bo->bufmgr;
1421 drm_intel_bo_fake *batch_fake = (drm_intel_bo_fake *) bo;
1422 struct drm_i915_batchbuffer batch;
1424 int retry_count = 0;
1426 pthread_mutex_lock(&bufmgr_fake->lock);
1428 bufmgr_fake->performed_rendering = 0;
1430 drm_intel_fake_calculate_domains(bo);
1432 batch_fake->read_domains = I915_GEM_DOMAIN_COMMAND;
1434 /* we've ran out of RAM so blow the whole lot away and retry */
1436 ret = drm_intel_fake_reloc_and_validate_buffer(bo);
1437 if (bufmgr_fake->fail == 1) {
1438 if (retry_count == 0) {
1440 drm_intel_fake_kick_all_locked(bufmgr_fake);
1441 bufmgr_fake->fail = 0;
1443 } else /* dump out the memory here */
1444 mmDumpMemInfo(bufmgr_fake->heap);
1449 if (bufmgr_fake->exec != NULL) {
1450 int ret = bufmgr_fake->exec(bo, used, bufmgr_fake->exec_priv);
1452 pthread_mutex_unlock(&bufmgr_fake->lock);
1456 batch.start = bo->offset;
1458 batch.cliprects = cliprects;
1459 batch.num_cliprects = num_cliprects;
1464 (bufmgr_fake->fd, DRM_I915_BATCHBUFFER, &batch,
1466 drmMsg("DRM_I915_BATCHBUFFER: %d\n", -errno);
1467 pthread_mutex_unlock(&bufmgr_fake->lock);
1472 drm_intel_fake_fence_validated(bo->bufmgr);
1474 drm_intel_bo_fake_post_submit(bo);
1476 pthread_mutex_unlock(&bufmgr_fake->lock);
1482 * Return an error if the list of BOs will exceed the aperture size.
1484 * This is a rough guess and likely to fail, as during the validate sequence we
1485 * may place a buffer in an inopportune spot early on and then fail to fit
1486 * a set smaller than the aperture.
1489 drm_intel_fake_check_aperture_space(drm_intel_bo ** bo_array, int count)
1491 drm_intel_bufmgr_fake *bufmgr_fake =
1492 (drm_intel_bufmgr_fake *) bo_array[0]->bufmgr;
1493 unsigned int sz = 0;
1496 for (i = 0; i < count; i++) {
1497 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) bo_array[i];
1499 if (bo_fake == NULL)
1502 if (!bo_fake->is_static)
1503 sz += ALIGN(bo_array[i]->size, bo_fake->alignment);
1504 sz += bo_fake->child_size;
1507 if (sz > bufmgr_fake->size) {
1508 DBG("check_space: overflowed bufmgr size, %dkb vs %dkb\n",
1509 sz / 1024, bufmgr_fake->size / 1024);
1513 DBG("drm_check_space: sz %dkb vs bufgr %dkb\n", sz / 1024,
1514 bufmgr_fake->size / 1024);
1519 * Evicts all buffers, waiting for fences to pass and copying contents out
1522 * Used by the X Server on LeaveVT, when the card memory is no longer our
1525 void drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr)
1527 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1528 struct block *block, *tmp;
1530 pthread_mutex_lock(&bufmgr_fake->lock);
1532 bufmgr_fake->need_fence = 1;
1533 bufmgr_fake->fail = 0;
1535 /* Wait for hardware idle. We don't know where acceleration has been
1536 * happening, so we'll need to wait anyway before letting anything get
1537 * put on the card again.
1539 drm_intel_bufmgr_fake_wait_idle(bufmgr_fake);
1541 /* Check that we hadn't released the lock without having fenced the last
1544 assert(DRMLISTEMPTY(&bufmgr_fake->fenced));
1545 assert(DRMLISTEMPTY(&bufmgr_fake->on_hardware));
1547 DRMLISTFOREACHSAFE(block, tmp, &bufmgr_fake->lru) {
1548 drm_intel_bo_fake *bo_fake = (drm_intel_bo_fake *) block->bo;
1549 /* Releases the memory, and memcpys dirty contents out if
1552 free_block(bufmgr_fake, block, 0);
1553 bo_fake->block = NULL;
1556 pthread_mutex_unlock(&bufmgr_fake->lock);
1559 void drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr,
1560 volatile unsigned int
1563 drm_intel_bufmgr_fake *bufmgr_fake = (drm_intel_bufmgr_fake *) bufmgr;
1565 bufmgr_fake->last_dispatch = (volatile int *)last_dispatch;
1568 drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd,
1569 unsigned long low_offset,
1572 volatile unsigned int
1575 drm_intel_bufmgr_fake *bufmgr_fake;
1577 bufmgr_fake = calloc(1, sizeof(*bufmgr_fake));
1579 if (pthread_mutex_init(&bufmgr_fake->lock, NULL) != 0) {
1584 /* Initialize allocator */
1585 DRMINITLISTHEAD(&bufmgr_fake->fenced);
1586 DRMINITLISTHEAD(&bufmgr_fake->on_hardware);
1587 DRMINITLISTHEAD(&bufmgr_fake->lru);
1589 bufmgr_fake->low_offset = low_offset;
1590 bufmgr_fake->virtual = low_virtual;
1591 bufmgr_fake->size = size;
1592 bufmgr_fake->heap = mmInit(low_offset, size);
1594 /* Hook in methods */
1595 bufmgr_fake->bufmgr.bo_alloc = drm_intel_fake_bo_alloc;
1596 bufmgr_fake->bufmgr.bo_alloc_for_render = drm_intel_fake_bo_alloc;
1597 bufmgr_fake->bufmgr.bo_alloc_tiled = drm_intel_fake_bo_alloc_tiled;
1598 bufmgr_fake->bufmgr.bo_reference = drm_intel_fake_bo_reference;
1599 bufmgr_fake->bufmgr.bo_unreference = drm_intel_fake_bo_unreference;
1600 bufmgr_fake->bufmgr.bo_map = drm_intel_fake_bo_map;
1601 bufmgr_fake->bufmgr.bo_unmap = drm_intel_fake_bo_unmap;
1602 bufmgr_fake->bufmgr.bo_wait_rendering =
1603 drm_intel_fake_bo_wait_rendering;
1604 bufmgr_fake->bufmgr.bo_emit_reloc = drm_intel_fake_emit_reloc;
1605 bufmgr_fake->bufmgr.destroy = drm_intel_fake_destroy;
1606 bufmgr_fake->bufmgr.bo_exec = drm_intel_fake_bo_exec;
1607 bufmgr_fake->bufmgr.check_aperture_space =
1608 drm_intel_fake_check_aperture_space;
1609 bufmgr_fake->bufmgr.debug = 0;
1611 bufmgr_fake->fd = fd;
1612 bufmgr_fake->last_dispatch = (volatile int *)last_dispatch;
1614 return &bufmgr_fake->bufmgr;