intel: move drm calls to exec buffers to libdrm_intel.
[profile/ivi/libdrm.git] / libdrm / intel / intel_bufmgr_gem.c
1 /**************************************************************************
2  *
3  * Copyright © 2007 Red Hat Inc.
4  * Copyright © 2007 Intel Corporation
5  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
6  * All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sub license, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * The above copyright notice and this permission notice (including the
25  * next paragraph) shall be included in all copies or substantial portions
26  * of the Software.
27  *
28  *
29  **************************************************************************/
30 /*
31  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
32  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
33  *          Eric Anholt <eric@anholt.net>
34  *          Dave Airlie <airlied@linux.ie>
35  */
36
37 #include <xf86drm.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <assert.h>
43 #include <sys/ioctl.h>
44 #include <sys/mman.h>
45
46 #include "errno.h"
47 #include "intel_bufmgr.h"
48 #include "intel_bufmgr_priv.h"
49 #include "string.h"
50
51 #include "i915_drm.h"
52
53 #define DBG(...) do {                                   \
54    if (bufmgr_gem->bufmgr.debug)                        \
55       fprintf(stderr, __VA_ARGS__);                     \
56 } while (0)
57
58 typedef struct _dri_bo_gem dri_bo_gem;
59
60 struct dri_gem_bo_bucket {
61    dri_bo_gem *head, **tail;
62    /**
63     * Limit on the number of entries in this bucket.
64     *
65     * 0 means that this caching at this bucket size is disabled.
66     * -1 means that there is no limit to caching at this size.
67     */
68    int max_entries;
69    int num_entries;
70 };
71
72 /* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
73  * is 1 << 16 pages, or 256MB.
74  */
75 #define INTEL_GEM_BO_BUCKETS    16
76 typedef struct _dri_bufmgr_gem {
77     dri_bufmgr bufmgr;
78
79     int fd;
80
81     int max_relocs;
82
83     struct drm_i915_gem_exec_object *exec_objects;
84     dri_bo **exec_bos;
85     int exec_size;
86     int exec_count;
87
88     /** Array of lists of cached gem objects of power-of-two sizes */
89     struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS];
90 } dri_bufmgr_gem;
91
92 struct _dri_bo_gem {
93     dri_bo bo;
94
95     int refcount;
96     /** Boolean whether the mmap ioctl has been called for this buffer yet. */
97     int mapped;
98     uint32_t gem_handle;
99     const char *name;
100
101     /**
102      * Kenel-assigned global name for this object
103      */
104     unsigned int global_name;
105     
106     /**
107      * Index of the buffer within the validation list while preparing a
108      * batchbuffer execution.
109      */
110     int validate_index;
111
112     /**
113      * Boolean whether we've started swrast
114      * Set when the buffer has been mapped
115      * Cleared when the buffer is unmapped
116      */
117     int swrast;
118
119     /** Array passed to the DRM containing relocation information. */
120     struct drm_i915_gem_relocation_entry *relocs;
121     /** Array of bos corresponding to relocs[i].target_handle */
122     dri_bo **reloc_target_bo;
123     /** Number of entries in relocs */
124     int reloc_count;
125     /** Mapped address for the buffer */
126     void *virtual;
127
128     /** free list */
129     dri_bo_gem *next;
130 };
131
132 static int
133 logbase2(int n)
134 {
135    int i = 1;
136    int log2 = 0;
137
138    while (n > i) {
139       i *= 2;
140       log2++;
141    }
142
143    return log2;
144 }
145
146 static struct dri_gem_bo_bucket *
147 dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)
148 {
149     int i;
150
151     /* We only do buckets in power of two increments */
152     if ((size & (size - 1)) != 0)
153         return NULL;
154
155     /* We should only see sizes rounded to pages. */
156     assert((size % 4096) == 0);
157
158     /* We always allocate in units of pages */
159     i = ffs(size / 4096) - 1;
160     if (i >= INTEL_GEM_BO_BUCKETS)
161         return NULL;
162
163     return &bufmgr_gem->cache_bucket[i];
164 }
165
166
167 static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)
168 {
169     int i, j;
170
171     for (i = 0; i < bufmgr_gem->exec_count; i++) {
172         dri_bo *bo = bufmgr_gem->exec_bos[i];
173         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
174
175         if (bo_gem->relocs == NULL) {
176             DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name);
177             continue;
178         }
179
180         for (j = 0; j < bo_gem->reloc_count; j++) {
181             dri_bo *target_bo = bo_gem->reloc_target_bo[j];
182             dri_bo_gem *target_gem = (dri_bo_gem *)target_bo;
183
184             DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",
185                 i,
186                 bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset,
187                 target_gem->gem_handle, target_gem->name, target_bo->offset,
188                 bo_gem->relocs[j].delta);
189         }
190     }
191 }
192
193 /**
194  * Adds the given buffer to the list of buffers to be validated (moved into the
195  * appropriate memory type) with the next batch submission.
196  *
197  * If a buffer is validated multiple times in a batch submission, it ends up
198  * with the intersection of the memory type flags and the union of the
199  * access flags.
200  */
201 static void
202 intel_add_validate_buffer(dri_bo *bo)
203 {
204     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
205     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
206     int index;
207
208     if (bo_gem->validate_index != -1)
209         return;
210
211     /* Extend the array of validation entries as necessary. */
212     if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
213         int new_size = bufmgr_gem->exec_size * 2;
214
215         if (new_size == 0)
216             new_size = 5;
217
218         bufmgr_gem->exec_objects =
219             realloc(bufmgr_gem->exec_objects,
220                     sizeof(*bufmgr_gem->exec_objects) * new_size);
221         bufmgr_gem->exec_bos =
222             realloc(bufmgr_gem->exec_bos,
223                     sizeof(*bufmgr_gem->exec_bos) * new_size);
224         bufmgr_gem->exec_size = new_size;
225     }
226
227     index = bufmgr_gem->exec_count;
228     bo_gem->validate_index = index;
229     /* Fill in array entry */
230     bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
231     bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
232     bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
233     bufmgr_gem->exec_objects[index].alignment = 0;
234     bufmgr_gem->exec_objects[index].offset = 0;
235     bufmgr_gem->exec_bos[index] = bo;
236     dri_bo_reference(bo);
237     bufmgr_gem->exec_count++;
238 }
239
240
241 #define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
242         sizeof(uint32_t))
243
244 static int
245 intel_setup_reloc_list(dri_bo *bo)
246 {
247     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
248     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
249
250     bo_gem->relocs = malloc(bufmgr_gem->max_relocs *
251                             sizeof(struct drm_i915_gem_relocation_entry));
252     bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * sizeof(dri_bo *));
253
254     return 0;
255 }
256
257 static dri_bo *
258 dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
259                  unsigned long size, unsigned int alignment)
260 {
261     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
262     dri_bo_gem *bo_gem;
263     unsigned int page_size = getpagesize();
264     int ret;
265     struct dri_gem_bo_bucket *bucket;
266     int alloc_from_cache = 0;
267     unsigned long bo_size;
268
269     /* Round the allocated size up to a power of two number of pages. */
270     bo_size = 1 << logbase2(size);
271     if (bo_size < page_size)
272         bo_size = page_size;
273     bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
274
275     /* If we don't have caching at this size, don't actually round the
276      * allocation up.
277      */
278     if (bucket == NULL || bucket->max_entries == 0) {
279         bo_size = size;
280         if (bo_size < page_size)
281             bo_size = page_size;
282     }
283
284     /* Get a buffer out of the cache if available */
285     if (bucket != NULL && bucket->num_entries > 0) {
286         struct drm_i915_gem_busy busy;
287         
288         bo_gem = bucket->head;
289         busy.handle = bo_gem->gem_handle;
290
291         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
292         alloc_from_cache = (ret == 0 && busy.busy == 0);
293
294         if (alloc_from_cache) {
295             bucket->head = bo_gem->next;
296             if (bo_gem->next == NULL)
297                 bucket->tail = &bucket->head;
298             bucket->num_entries--;
299         }
300     }
301
302     if (!alloc_from_cache) {
303         struct drm_i915_gem_create create;
304
305         bo_gem = calloc(1, sizeof(*bo_gem));
306         if (!bo_gem)
307             return NULL;
308
309         bo_gem->bo.size = bo_size;
310         memset(&create, 0, sizeof(create));
311         create.size = bo_size;
312
313         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
314         bo_gem->gem_handle = create.handle;
315         if (ret != 0) {
316             free(bo_gem);
317             return NULL;
318         }
319         bo_gem->bo.bufmgr = bufmgr;
320     }
321
322     bo_gem->name = name;
323     bo_gem->refcount = 1;
324     bo_gem->validate_index = -1;
325
326     DBG("bo_create: buf %d (%s) %ldb\n",
327         bo_gem->gem_handle, bo_gem->name, size);
328
329     return &bo_gem->bo;
330 }
331
332 /**
333  * Returns a dri_bo wrapping the given buffer object handle.
334  *
335  * This can be used when one application needs to pass a buffer object
336  * to another.
337  */
338 dri_bo *
339 intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
340                               unsigned int handle)
341 {
342     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
343     dri_bo_gem *bo_gem;
344     int ret;
345     struct drm_gem_open open_arg;
346
347     bo_gem = calloc(1, sizeof(*bo_gem));
348     if (!bo_gem)
349         return NULL;
350
351     memset(&open_arg, 0, sizeof(open_arg));
352     open_arg.name = handle;
353     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
354     if (ret != 0) {
355         fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
356                name, handle, strerror(-ret));
357         free(bo_gem);
358         return NULL;
359     }
360     bo_gem->bo.size = open_arg.size;
361     bo_gem->bo.offset = 0;
362     bo_gem->bo.virtual = NULL;
363     bo_gem->bo.bufmgr = bufmgr;
364     bo_gem->name = name;
365     bo_gem->refcount = 1;
366     bo_gem->validate_index = -1;
367     bo_gem->gem_handle = open_arg.handle;
368     bo_gem->global_name = handle;
369
370     DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
371
372     return &bo_gem->bo;
373 }
374
375 static void
376 dri_gem_bo_reference(dri_bo *bo)
377 {
378     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
379
380     bo_gem->refcount++;
381 }
382
383 static void
384 dri_gem_bo_free(dri_bo *bo)
385 {
386     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
387     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
388     struct drm_gem_close close;
389     int ret;
390
391     if (bo_gem->mapped)
392         munmap (bo_gem->virtual, bo_gem->bo.size);
393
394     /* Close this object */
395     close.handle = bo_gem->gem_handle;
396     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
397     if (ret != 0) {
398         fprintf(stderr,
399                 "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
400                 bo_gem->gem_handle, bo_gem->name, strerror(-ret));
401     }
402     free(bo);
403 }
404
405 static void
406 dri_gem_bo_unreference(dri_bo *bo)
407 {
408     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
409     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
410
411     if (!bo)
412         return;
413
414     if (--bo_gem->refcount == 0) {
415         struct dri_gem_bo_bucket *bucket;
416
417         if (bo_gem->relocs != NULL) {
418             int i;
419
420             /* Unreference all the target buffers */
421             for (i = 0; i < bo_gem->reloc_count; i++)
422                  dri_bo_unreference(bo_gem->reloc_target_bo[i]);
423             free(bo_gem->reloc_target_bo);
424             free(bo_gem->relocs);
425         }
426
427         DBG("bo_unreference final: %d (%s)\n",
428             bo_gem->gem_handle, bo_gem->name);
429
430         bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
431         /* Put the buffer into our internal cache for reuse if we can. */
432         if (bucket != NULL &&
433             (bucket->max_entries == -1 ||
434              (bucket->max_entries > 0 &&
435               bucket->num_entries < bucket->max_entries)))
436         {
437             bo_gem->name = 0;
438             bo_gem->validate_index = -1;
439             bo_gem->relocs = NULL;
440             bo_gem->reloc_target_bo = NULL;
441             bo_gem->reloc_count = 0;
442
443             bo_gem->next = NULL;
444             *bucket->tail = bo_gem;
445             bucket->tail = &bo_gem->next;
446             bucket->num_entries++;
447         } else {
448             dri_gem_bo_free(bo);
449         }
450
451         return;
452     }
453 }
454
455 static int
456 dri_gem_bo_map(dri_bo *bo, int write_enable)
457 {
458     dri_bufmgr_gem *bufmgr_gem;
459     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
460     struct drm_i915_gem_set_domain set_domain;
461     int ret;
462
463     bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
464
465     /* Allow recursive mapping. Mesa may recursively map buffers with
466      * nested display loops.
467      */
468     if (!bo_gem->mapped) {
469     
470         assert(bo->virtual == NULL);
471     
472         DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
473     
474         if (bo_gem->virtual == NULL) {
475             struct drm_i915_gem_mmap mmap_arg;
476     
477             memset(&mmap_arg, 0, sizeof(mmap_arg));
478             mmap_arg.handle = bo_gem->gem_handle;
479             mmap_arg.offset = 0;
480             mmap_arg.size = bo->size;
481             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
482             if (ret != 0) {
483                 fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
484                         __FILE__, __LINE__,
485                         bo_gem->gem_handle, bo_gem->name, strerror(errno));
486             }
487             bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
488         }
489         bo->virtual = bo_gem->virtual;
490         bo_gem->swrast = 0;
491         bo_gem->mapped = 1;
492         DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
493     }
494
495     if (!bo_gem->swrast) {
496         set_domain.handle = bo_gem->gem_handle;
497         set_domain.read_domains = I915_GEM_DOMAIN_CPU;
498         if (write_enable)
499             set_domain.write_domain = I915_GEM_DOMAIN_CPU;
500         else
501             set_domain.write_domain = 0;
502         do {
503             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
504                         &set_domain);
505         } while (ret == -1 && errno == EINTR);
506         if (ret != 0) {
507             fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
508                      __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
509         }
510         bo_gem->swrast = 1;
511     }
512
513     return 0;
514 }
515
516 static int
517 dri_gem_bo_unmap(dri_bo *bo)
518 {
519     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
520     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
521     struct drm_i915_gem_sw_finish sw_finish;
522     int ret;
523
524     if (bo == NULL)
525         return 0;
526
527     assert(bo_gem->mapped);
528
529     if (bo_gem->swrast) {
530         sw_finish.handle = bo_gem->gem_handle;
531         do {
532             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
533                         &sw_finish);
534         } while (ret == -1 && errno == EINTR);
535         bo_gem->swrast = 0;
536     }
537     return 0;
538 }
539
540 static int
541 dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,
542                     unsigned long size, const void *data)
543 {
544     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
545     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
546     struct drm_i915_gem_pwrite pwrite;
547     int ret;
548
549     memset (&pwrite, 0, sizeof (pwrite));
550     pwrite.handle = bo_gem->gem_handle;
551     pwrite.offset = offset;
552     pwrite.size = size;
553     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
554     do {
555         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
556     } while (ret == -1 && errno == EINTR);
557     if (ret != 0) {
558         fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
559                  __FILE__, __LINE__,
560                  bo_gem->gem_handle, (int) offset, (int) size,
561                  strerror (errno));
562     }
563     return 0;
564 }
565
566 static int
567 dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,
568                         unsigned long size, void *data)
569 {
570     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
571     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
572     struct drm_i915_gem_pread pread;
573     int ret;
574
575     memset (&pread, 0, sizeof (pread));
576     pread.handle = bo_gem->gem_handle;
577     pread.offset = offset;
578     pread.size = size;
579     pread.data_ptr = (uint64_t) (uintptr_t) data;
580     do {
581         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
582     } while (ret == -1 && errno == EINTR);
583     if (ret != 0) {
584         fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
585                  __FILE__, __LINE__,
586                  bo_gem->gem_handle, (int) offset, (int) size,
587                  strerror (errno));
588     }
589     return 0;
590 }
591
592 static void
593 dri_gem_bo_wait_rendering(dri_bo *bo)
594 {
595     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
596     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
597     struct drm_i915_gem_set_domain set_domain;
598     int ret;
599
600     set_domain.handle = bo_gem->gem_handle;
601     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
602     set_domain.write_domain = 0;
603     ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
604     if (ret != 0) {
605         fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
606                  __FILE__, __LINE__,
607                  bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
608                  strerror (errno));
609     }
610 }
611
612 static void
613 dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
614 {
615     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
616     int i;
617
618     free(bufmgr_gem->exec_objects);
619     free(bufmgr_gem->exec_bos);
620
621     /* Free any cached buffer objects we were going to reuse */
622     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
623         struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
624         dri_bo_gem *bo_gem;
625
626         while ((bo_gem = bucket->head) != NULL) {
627             bucket->head = bo_gem->next;
628             if (bo_gem->next == NULL)
629                 bucket->tail = &bucket->head;
630             bucket->num_entries--;
631
632             dri_gem_bo_free(&bo_gem->bo);
633         }
634     }
635
636     free(bufmgr);
637 }
638
639 /**
640  * Adds the target buffer to the validation list and adds the relocation
641  * to the reloc_buffer's relocation list.
642  *
643  * The relocation entry at the given offset must already contain the
644  * precomputed relocation value, because the kernel will optimize out
645  * the relocation entry write when the buffer hasn't moved from the
646  * last known offset in target_bo.
647  */
648 static int
649 dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,
650                       uint32_t delta, uint32_t offset, dri_bo *target_bo)
651 {
652     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
653     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
654     dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo;
655
656     /* Create a new relocation list if needed */
657     if (bo_gem->relocs == NULL)
658         intel_setup_reloc_list(bo);
659
660     /* Check overflow */
661     assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
662
663     /* Check args */
664     assert (offset <= bo->size - 4);
665     assert ((write_domain & (write_domain-1)) == 0);
666
667     bo_gem->relocs[bo_gem->reloc_count].offset = offset;
668     bo_gem->relocs[bo_gem->reloc_count].delta = delta;
669     bo_gem->relocs[bo_gem->reloc_count].target_handle =
670         target_bo_gem->gem_handle;
671     bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
672     bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
673     bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
674
675     bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
676     dri_bo_reference(target_bo);
677
678     bo_gem->reloc_count++;
679     return 0;
680 }
681
682 /**
683  * Walk the tree of relocations rooted at BO and accumulate the list of
684  * validations to be performed and update the relocation buffers with
685  * index values into the validation list.
686  */
687 static void
688 dri_gem_bo_process_reloc(dri_bo *bo)
689 {
690     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
691     int i;
692
693     if (bo_gem->relocs == NULL)
694         return;
695
696     for (i = 0; i < bo_gem->reloc_count; i++) {
697         dri_bo *target_bo = bo_gem->reloc_target_bo[i];
698
699         /* Continue walking the tree depth-first. */
700         dri_gem_bo_process_reloc(target_bo);
701
702         /* Add the target to the validate list */
703         intel_add_validate_buffer(target_bo);
704     }
705 }
706
707 static void
708 intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem)
709 {
710     int i;
711
712     for (i = 0; i < bufmgr_gem->exec_count; i++) {
713         dri_bo *bo = bufmgr_gem->exec_bos[i];
714         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
715
716         /* Update the buffer offset */
717         if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
718             DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
719                 bo_gem->gem_handle, bo_gem->name, bo->offset,
720                 bufmgr_gem->exec_objects[i].offset);
721             bo->offset = bufmgr_gem->exec_objects[i].offset;
722         }
723     }
724 }
725
726 static int
727 dri_gem_bo_exec(dri_bo *bo, int used,
728                 drm_clip_rect_t *cliprects, int num_cliprects,
729                 int DR4)
730 {
731     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
732     struct drm_i915_gem_execbuffer execbuf;
733     int ret, i;
734
735     /* Update indices and set up the validate list. */
736     dri_gem_bo_process_reloc(bo);
737
738     /* Add the batch buffer to the validation list.  There are no relocations
739      * pointing to it.
740      */
741     intel_add_validate_buffer(bo);
742
743     execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
744     execbuf.buffer_count = bufmgr_gem->exec_count;
745     execbuf.batch_start_offset = 0;
746     execbuf.batch_len = used;
747     execbuf.cliprects_ptr = (uintptr_t)cliprects;
748     execbuf.num_cliprects = num_cliprects;
749     execbuf.DR1 = 0;
750     execbuf.DR4 = DR4;
751
752     do {
753         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf);
754     } while (ret == -EAGAIN);
755
756     intel_update_buffer_offsets (bufmgr_gem);
757
758     if (bufmgr_gem->bufmgr.debug)
759         dri_gem_dump_validation_list(bufmgr_gem);
760
761     for (i = 0; i < bufmgr_gem->exec_count; i++) {
762         dri_bo *bo = bufmgr_gem->exec_bos[i];
763         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
764
765         /* Need to call swrast on next bo_map */
766         bo_gem->swrast = 0;
767
768         /* Disconnect the buffer from the validate list */
769         bo_gem->validate_index = -1;
770         dri_bo_unreference(bo);
771         bufmgr_gem->exec_bos[i] = NULL;
772     }
773     bufmgr_gem->exec_count = 0;
774
775     return 0;
776 }
777
778 static int
779 dri_gem_bo_pin(dri_bo *bo, uint32_t alignment)
780 {
781     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
782     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
783     struct drm_i915_gem_pin pin;
784     int ret;
785
786     pin.handle = bo_gem->gem_handle;
787     pin.alignment = alignment;
788
789     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
790     if (ret != 0)
791         return -errno;
792
793     bo->offset = pin.offset;
794     return 0;
795 }
796
797 static int
798 dri_gem_bo_unpin(dri_bo *bo)
799 {
800     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
801     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
802     struct drm_i915_gem_unpin unpin;
803     int ret;
804
805     unpin.handle = bo_gem->gem_handle;
806
807     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
808     if (ret != 0)
809         return -errno;
810
811     return 0;
812 }
813
814 static int
815 dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode)
816 {
817     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
818     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
819     struct drm_i915_gem_set_tiling set_tiling;
820     int ret;
821
822     set_tiling.handle = bo_gem->gem_handle;
823     set_tiling.tiling_mode = *tiling_mode;
824
825     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
826     if (ret != 0) {
827         *tiling_mode = I915_TILING_NONE;
828         return -errno;
829     }
830
831     *tiling_mode = set_tiling.tiling_mode;
832     return 0;
833 }
834
835 static int
836 dri_gem_bo_flink(dri_bo *bo, uint32_t *name)
837 {
838     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
839     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
840     struct drm_gem_flink flink;
841     int ret;
842
843     if (!bo_gem->global_name) {
844         flink.handle = bo_gem->gem_handle;
845     
846         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
847         if (ret != 0)
848             return -errno;
849         bo_gem->global_name = flink.name;
850     }
851     
852     *name = bo_gem->global_name;
853     return 0;
854 }
855
856 /**
857  * Enables unlimited caching of buffer objects for reuse.
858  *
859  * This is potentially very memory expensive, as the cache at each bucket
860  * size is only bounded by how many buffers of that size we've managed to have
861  * in flight at once.
862  */
863 void
864 intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr)
865 {
866     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
867     int i;
868
869     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
870         bufmgr_gem->cache_bucket[i].max_entries = -1;
871     }
872 }
873
874 /*
875  *
876  */
877 static int
878 dri_gem_check_aperture_space(dri_bo **bo_array, int count)
879 {
880     return 0;
881 }
882
883 /**
884  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
885  * and manage map buffer objections.
886  *
887  * \param fd File descriptor of the opened DRM device.
888  */
889 dri_bufmgr *
890 intel_bufmgr_gem_init(int fd, int batch_size)
891 {
892     dri_bufmgr_gem *bufmgr_gem;
893     int i;
894
895     bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
896     bufmgr_gem->fd = fd;
897
898     /* Let's go with one relocation per every 2 dwords (but round down a bit
899      * since a power of two will mean an extra page allocation for the reloc
900      * buffer).
901      *
902      * Every 4 was too few for the blender benchmark.
903      */
904     bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
905
906     bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
907     bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
908     bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
909     bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
910     bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
911     bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata;
912     bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata;
913     bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering;
914     bufmgr_gem->bufmgr.bo_emit_reloc = dri_gem_bo_emit_reloc;
915     bufmgr_gem->bufmgr.bo_pin = dri_gem_bo_pin;
916     bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin;
917     bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling;
918     bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink;
919     bufmgr_gem->bufmgr.bo_exec = dri_gem_bo_exec;
920     bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
921     bufmgr_gem->bufmgr.debug = 0;
922     bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space;
923     /* Initialize the linked lists for BO reuse cache. */
924     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++)
925         bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
926
927     return &bufmgr_gem->bufmgr;
928 }
929