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