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