Replace the check_aperture API with one we can make thread-safe.
[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 "dri_bufmgr.h"
48 #include "intel_bufmgr.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     struct intel_bufmgr intel_bufmgr;
80
81     int fd;
82
83     int max_relocs;
84
85     struct drm_i915_gem_exec_object *exec_objects;
86     dri_bo **exec_bos;
87     int exec_size;
88     int exec_count;
89
90     /** Array of lists of cached gem objects of power-of-two sizes */
91     struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS];
92
93     struct drm_i915_gem_execbuffer exec_arg;
94 } dri_bufmgr_gem;
95
96 struct _dri_bo_gem {
97     dri_bo bo;
98
99     int refcount;
100     /** Boolean whether the mmap ioctl has been called for this buffer yet. */
101     int mapped;
102     uint32_t gem_handle;
103     const char *name;
104
105     /**
106      * Kenel-assigned global name for this object
107      */
108     unsigned int global_name;
109     
110     /**
111      * Index of the buffer within the validation list while preparing a
112      * batchbuffer execution.
113      */
114     int validate_index;
115
116     /**
117      * Boolean whether we've started swrast
118      * Set when the buffer has been mapped
119      * Cleared when the buffer is unmapped
120      */
121     int swrast;
122
123     /** Array passed to the DRM containing relocation information. */
124     struct drm_i915_gem_relocation_entry *relocs;
125     /** Array of bos corresponding to relocs[i].target_handle */
126     dri_bo **reloc_target_bo;
127     /** Number of entries in relocs */
128     int reloc_count;
129     /** Mapped address for the buffer */
130     void *virtual;
131
132     /** free list */
133     dri_bo_gem *next;
134 };
135
136 static int
137 logbase2(int n)
138 {
139    int i = 1;
140    int log2 = 0;
141
142    while (n > i) {
143       i *= 2;
144       log2++;
145    }
146
147    return log2;
148 }
149
150 static struct dri_gem_bo_bucket *
151 dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)
152 {
153     int i;
154
155     /* We only do buckets in power of two increments */
156     if ((size & (size - 1)) != 0)
157         return NULL;
158
159     /* We should only see sizes rounded to pages. */
160     assert((size % 4096) == 0);
161
162     /* We always allocate in units of pages */
163     i = ffs(size / 4096) - 1;
164     if (i >= INTEL_GEM_BO_BUCKETS)
165         return NULL;
166
167     return &bufmgr_gem->cache_bucket[i];
168 }
169
170
171 static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)
172 {
173     int i, j;
174
175     for (i = 0; i < bufmgr_gem->exec_count; i++) {
176         dri_bo *bo = bufmgr_gem->exec_bos[i];
177         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
178
179         if (bo_gem->relocs == NULL) {
180             DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name);
181             continue;
182         }
183
184         for (j = 0; j < bo_gem->reloc_count; j++) {
185             dri_bo *target_bo = bo_gem->reloc_target_bo[j];
186             dri_bo_gem *target_gem = (dri_bo_gem *)target_bo;
187
188             DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",
189                 i,
190                 bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset,
191                 target_gem->gem_handle, target_gem->name, target_bo->offset,
192                 bo_gem->relocs[j].delta);
193         }
194     }
195 }
196
197 /**
198  * Adds the given buffer to the list of buffers to be validated (moved into the
199  * appropriate memory type) with the next batch submission.
200  *
201  * If a buffer is validated multiple times in a batch submission, it ends up
202  * with the intersection of the memory type flags and the union of the
203  * access flags.
204  */
205 static void
206 intel_add_validate_buffer(dri_bo *bo)
207 {
208     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
209     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
210     int index;
211
212     if (bo_gem->validate_index != -1)
213         return;
214
215     /* Extend the array of validation entries as necessary. */
216     if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
217         int new_size = bufmgr_gem->exec_size * 2;
218
219         if (new_size == 0)
220             new_size = 5;
221
222         bufmgr_gem->exec_objects =
223             realloc(bufmgr_gem->exec_objects,
224                     sizeof(*bufmgr_gem->exec_objects) * new_size);
225         bufmgr_gem->exec_bos =
226             realloc(bufmgr_gem->exec_bos,
227                     sizeof(*bufmgr_gem->exec_bos) * new_size);
228         bufmgr_gem->exec_size = new_size;
229     }
230
231     index = bufmgr_gem->exec_count;
232     bo_gem->validate_index = index;
233     /* Fill in array entry */
234     bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
235     bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
236     bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
237     bufmgr_gem->exec_objects[index].alignment = 0;
238     bufmgr_gem->exec_objects[index].offset = 0;
239     bufmgr_gem->exec_bos[index] = bo;
240     dri_bo_reference(bo);
241     bufmgr_gem->exec_count++;
242 }
243
244
245 #define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
246         sizeof(uint32_t))
247
248 static int
249 intel_setup_reloc_list(dri_bo *bo)
250 {
251     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
252     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
253
254     bo_gem->relocs = malloc(bufmgr_gem->max_relocs *
255                             sizeof(struct drm_i915_gem_relocation_entry));
256     bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * sizeof(dri_bo *));
257
258     return 0;
259 }
260
261 static dri_bo *
262 dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
263                  unsigned long size, unsigned int alignment)
264 {
265     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
266     dri_bo_gem *bo_gem;
267     unsigned int page_size = getpagesize();
268     int ret;
269     struct dri_gem_bo_bucket *bucket;
270     int alloc_from_cache = 0;
271     unsigned long bo_size;
272
273     /* Round the allocated size up to a power of two number of pages. */
274     bo_size = 1 << logbase2(size);
275     if (bo_size < page_size)
276         bo_size = page_size;
277     bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
278
279     /* If we don't have caching at this size, don't actually round the
280      * allocation up.
281      */
282     if (bucket == NULL || bucket->max_entries == 0) {
283         bo_size = size;
284         if (bo_size < page_size)
285             bo_size = page_size;
286     }
287
288     /* Get a buffer out of the cache if available */
289     if (bucket != NULL && bucket->num_entries > 0) {
290         struct drm_i915_gem_busy busy;
291         
292         bo_gem = bucket->head;
293         busy.handle = bo_gem->gem_handle;
294
295         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
296         alloc_from_cache = (ret == 0 && busy.busy == 0);
297
298         if (alloc_from_cache) {
299             bucket->head = bo_gem->next;
300             if (bo_gem->next == NULL)
301                 bucket->tail = &bucket->head;
302             bucket->num_entries--;
303         }
304     }
305
306     if (!alloc_from_cache) {
307         struct drm_i915_gem_create create;
308
309         bo_gem = calloc(1, sizeof(*bo_gem));
310         if (!bo_gem)
311             return NULL;
312
313         bo_gem->bo.size = bo_size;
314         memset(&create, 0, sizeof(create));
315         create.size = bo_size;
316
317         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
318         bo_gem->gem_handle = create.handle;
319         if (ret != 0) {
320             free(bo_gem);
321             return NULL;
322         }
323         bo_gem->bo.bufmgr = bufmgr;
324     }
325
326     bo_gem->name = name;
327     bo_gem->refcount = 1;
328     bo_gem->validate_index = -1;
329
330     DBG("bo_create: buf %d (%s) %ldb\n",
331         bo_gem->gem_handle, bo_gem->name, size);
332
333     return &bo_gem->bo;
334 }
335
336 /**
337  * Returns a dri_bo wrapping the given buffer object handle.
338  *
339  * This can be used when one application needs to pass a buffer object
340  * to another.
341  */
342 dri_bo *
343 intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
344                               unsigned int handle)
345 {
346     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
347     dri_bo_gem *bo_gem;
348     int ret;
349     struct drm_gem_open open_arg;
350
351     bo_gem = calloc(1, sizeof(*bo_gem));
352     if (!bo_gem)
353         return NULL;
354
355     memset(&open_arg, 0, sizeof(open_arg));
356     open_arg.name = handle;
357     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
358     if (ret != 0) {
359         fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
360                name, handle, strerror(-ret));
361         free(bo_gem);
362         return NULL;
363     }
364     bo_gem->bo.size = open_arg.size;
365     bo_gem->bo.offset = 0;
366     bo_gem->bo.virtual = NULL;
367     bo_gem->bo.bufmgr = bufmgr;
368     bo_gem->name = name;
369     bo_gem->refcount = 1;
370     bo_gem->validate_index = -1;
371     bo_gem->gem_handle = open_arg.handle;
372
373     DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
374
375     return &bo_gem->bo;
376 }
377
378 static void
379 dri_gem_bo_reference(dri_bo *bo)
380 {
381     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
382
383     bo_gem->refcount++;
384 }
385
386 static void
387 dri_gem_bo_free(dri_bo *bo)
388 {
389     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
390     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
391     struct drm_gem_close close;
392     int ret;
393
394     if (bo_gem->mapped)
395         munmap (bo_gem->virtual, bo_gem->bo.size);
396
397     /* Close this object */
398     close.handle = bo_gem->gem_handle;
399     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
400     if (ret != 0) {
401         fprintf(stderr,
402                 "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
403                 bo_gem->gem_handle, bo_gem->name, strerror(-ret));
404     }
405     free(bo);
406 }
407
408 static void
409 dri_gem_bo_unreference(dri_bo *bo)
410 {
411     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
412     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
413
414     if (!bo)
415         return;
416
417     if (--bo_gem->refcount == 0) {
418         struct dri_gem_bo_bucket *bucket;
419
420         if (bo_gem->relocs != NULL) {
421             int i;
422
423             /* Unreference all the target buffers */
424             for (i = 0; i < bo_gem->reloc_count; i++)
425                  dri_bo_unreference(bo_gem->reloc_target_bo[i]);
426             free(bo_gem->reloc_target_bo);
427             free(bo_gem->relocs);
428         }
429
430         DBG("bo_unreference final: %d (%s)\n",
431             bo_gem->gem_handle, bo_gem->name);
432
433         bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
434         /* Put the buffer into our internal cache for reuse if we can. */
435         if (bucket != NULL &&
436             (bucket->max_entries == -1 ||
437              (bucket->max_entries > 0 &&
438               bucket->num_entries < bucket->max_entries)))
439         {
440             bo_gem->name = 0;
441             bo_gem->validate_index = -1;
442             bo_gem->relocs = NULL;
443             bo_gem->reloc_target_bo = NULL;
444             bo_gem->reloc_count = 0;
445
446             bo_gem->next = NULL;
447             *bucket->tail = bo_gem;
448             bucket->tail = &bo_gem->next;
449             bucket->num_entries++;
450         } else {
451             dri_gem_bo_free(bo);
452         }
453
454         return;
455     }
456 }
457
458 static int
459 dri_gem_bo_map(dri_bo *bo, int write_enable)
460 {
461     dri_bufmgr_gem *bufmgr_gem;
462     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
463     struct drm_i915_gem_set_domain set_domain;
464     int ret;
465
466     bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
467
468     /* Allow recursive mapping. Mesa may recursively map buffers with
469      * nested display loops.
470      */
471     if (!bo_gem->mapped) {
472     
473         assert(bo->virtual == NULL);
474     
475         DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
476     
477         if (bo_gem->virtual == NULL) {
478             struct drm_i915_gem_mmap mmap_arg;
479     
480             memset(&mmap_arg, 0, sizeof(mmap_arg));
481             mmap_arg.handle = bo_gem->gem_handle;
482             mmap_arg.offset = 0;
483             mmap_arg.size = bo->size;
484             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
485             if (ret != 0) {
486                 fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
487                         __FILE__, __LINE__,
488                         bo_gem->gem_handle, bo_gem->name, strerror(errno));
489             }
490             bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
491         }
492         bo->virtual = bo_gem->virtual;
493         bo_gem->swrast = 0;
494         bo_gem->mapped = 1;
495         DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
496     }
497
498     if (!bo_gem->swrast) {
499         set_domain.handle = bo_gem->gem_handle;
500         set_domain.read_domains = I915_GEM_DOMAIN_CPU;
501         if (write_enable)
502             set_domain.write_domain = I915_GEM_DOMAIN_CPU;
503         else
504             set_domain.write_domain = 0;
505         do {
506             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
507                         &set_domain);
508         } while (ret == -1 && errno == EINTR);
509         if (ret != 0) {
510             fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
511                      __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
512         }
513         bo_gem->swrast = 1;
514     }
515
516     return 0;
517 }
518
519 static int
520 dri_gem_bo_unmap(dri_bo *bo)
521 {
522     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
523     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
524     struct drm_i915_gem_sw_finish sw_finish;
525     int ret;
526
527     if (bo == NULL)
528         return 0;
529
530     assert(bo_gem->mapped);
531
532     if (bo_gem->swrast) {
533         sw_finish.handle = bo_gem->gem_handle;
534         do {
535             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
536                         &sw_finish);
537         } while (ret == -1 && errno == EINTR);
538         bo_gem->swrast = 0;
539     }
540     return 0;
541 }
542
543 static int
544 dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,
545                     unsigned long size, const void *data)
546 {
547     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
548     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
549     struct drm_i915_gem_pwrite pwrite;
550     int ret;
551
552     memset (&pwrite, 0, sizeof (pwrite));
553     pwrite.handle = bo_gem->gem_handle;
554     pwrite.offset = offset;
555     pwrite.size = size;
556     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
557     do {
558         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
559     } while (ret == -1 && errno == EINTR);
560     if (ret != 0) {
561         fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
562                  __FILE__, __LINE__,
563                  bo_gem->gem_handle, (int) offset, (int) size,
564                  strerror (errno));
565     }
566     return 0;
567 }
568
569 static int
570 dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,
571                         unsigned long size, void *data)
572 {
573     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
574     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
575     struct drm_i915_gem_pread pread;
576     int ret;
577
578     memset (&pread, 0, sizeof (pread));
579     pread.handle = bo_gem->gem_handle;
580     pread.offset = offset;
581     pread.size = size;
582     pread.data_ptr = (uint64_t) (uintptr_t) data;
583     do {
584         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
585     } while (ret == -1 && errno == EINTR);
586     if (ret != 0) {
587         fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
588                  __FILE__, __LINE__,
589                  bo_gem->gem_handle, (int) offset, (int) size,
590                  strerror (errno));
591     }
592     return 0;
593 }
594
595 static void
596 dri_gem_bo_wait_rendering(dri_bo *bo)
597 {
598     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
599     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
600     struct drm_i915_gem_set_domain set_domain;
601     int ret;
602
603     set_domain.handle = bo_gem->gem_handle;
604     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
605     set_domain.write_domain = 0;
606     ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
607     if (ret != 0) {
608         fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
609                  __FILE__, __LINE__,
610                  bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
611                  strerror (errno));
612     }
613 }
614
615 static void
616 dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
617 {
618     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
619     int i;
620
621     free(bufmgr_gem->exec_objects);
622     free(bufmgr_gem->exec_bos);
623
624     /* Free any cached buffer objects we were going to reuse */
625     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
626         struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
627         dri_bo_gem *bo_gem;
628
629         while ((bo_gem = bucket->head) != NULL) {
630             bucket->head = bo_gem->next;
631             if (bo_gem->next == NULL)
632                 bucket->tail = &bucket->head;
633             bucket->num_entries--;
634
635             dri_gem_bo_free(&bo_gem->bo);
636         }
637     }
638
639     free(bufmgr);
640 }
641
642 /**
643  * Adds the target buffer to the validation list and adds the relocation
644  * to the reloc_buffer's relocation list.
645  *
646  * The relocation entry at the given offset must already contain the
647  * precomputed relocation value, because the kernel will optimize out
648  * the relocation entry write when the buffer hasn't moved from the
649  * last known offset in target_bo.
650  */
651 static int
652 dri_gem_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,
653                    uint32_t delta, uint32_t offset, dri_bo *target_bo)
654 {
655     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
656     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
657     dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo;
658
659     /* Create a new relocation list if needed */
660     if (bo_gem->relocs == NULL)
661         intel_setup_reloc_list(bo);
662
663     /* Check overflow */
664     assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
665
666     /* Check args */
667     assert (offset <= bo->size - 4);
668     assert ((write_domain & (write_domain-1)) == 0);
669
670     bo_gem->relocs[bo_gem->reloc_count].offset = offset;
671     bo_gem->relocs[bo_gem->reloc_count].delta = delta;
672     bo_gem->relocs[bo_gem->reloc_count].target_handle =
673         target_bo_gem->gem_handle;
674     bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
675     bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
676     bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
677
678     bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
679     dri_bo_reference(target_bo);
680
681     bo_gem->reloc_count++;
682     return 0;
683 }
684
685 /**
686  * Walk the tree of relocations rooted at BO and accumulate the list of
687  * validations to be performed and update the relocation buffers with
688  * index values into the validation list.
689  */
690 static void
691 dri_gem_bo_process_reloc(dri_bo *bo)
692 {
693     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
694     int i;
695
696     if (bo_gem->relocs == NULL)
697         return;
698
699     for (i = 0; i < bo_gem->reloc_count; i++) {
700         dri_bo *target_bo = bo_gem->reloc_target_bo[i];
701
702         /* Continue walking the tree depth-first. */
703         dri_gem_bo_process_reloc(target_bo);
704
705         /* Add the target to the validate list */
706         intel_add_validate_buffer(target_bo);
707     }
708 }
709
710 static void *
711 dri_gem_process_reloc(dri_bo *batch_buf)
712 {
713     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *) batch_buf->bufmgr;
714
715     /* Update indices and set up the validate list. */
716     dri_gem_bo_process_reloc(batch_buf);
717
718     /* Add the batch buffer to the validation list.  There are no relocations
719      * pointing to it.
720      */
721     intel_add_validate_buffer(batch_buf);
722
723     bufmgr_gem->exec_arg.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
724     bufmgr_gem->exec_arg.buffer_count = bufmgr_gem->exec_count;
725     bufmgr_gem->exec_arg.batch_start_offset = 0;
726     bufmgr_gem->exec_arg.batch_len = 0; /* written in intel_exec_ioctl */
727
728     return &bufmgr_gem->exec_arg;
729 }
730
731 static void
732 intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem)
733 {
734     int i;
735
736     for (i = 0; i < bufmgr_gem->exec_count; i++) {
737         dri_bo *bo = bufmgr_gem->exec_bos[i];
738         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
739
740         /* Update the buffer offset */
741         if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
742             DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
743                 bo_gem->gem_handle, bo_gem->name, bo->offset,
744                 bufmgr_gem->exec_objects[i].offset);
745             bo->offset = bufmgr_gem->exec_objects[i].offset;
746         }
747     }
748 }
749
750 static void
751 dri_gem_post_submit(dri_bo *batch_buf)
752 {
753     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)batch_buf->bufmgr;
754     int i;
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
776 static int
777 dri_gem_pin(dri_bo *bo, uint32_t alignment)
778 {
779     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
780     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
781     struct drm_i915_gem_pin pin;
782     int ret;
783
784     pin.handle = bo_gem->gem_handle;
785     pin.alignment = alignment;
786
787     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
788     if (ret != 0)
789         return -errno;
790
791     bo->offset = pin.offset;
792     return 0;
793 }
794
795 static int
796 dri_gem_unpin(dri_bo *bo)
797 {
798     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
799     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
800     struct drm_i915_gem_unpin unpin;
801     int ret;
802
803     unpin.handle = bo_gem->gem_handle;
804
805     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
806     if (ret != 0)
807         return -errno;
808
809     return 0;
810 }
811
812 static int
813 dri_gem_set_tiling(dri_bo *bo, uint32_t *tiling_mode)
814 {
815     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
816     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
817     struct drm_i915_gem_set_tiling set_tiling;
818     int ret;
819
820     set_tiling.handle = bo_gem->gem_handle;
821     set_tiling.tiling_mode = *tiling_mode;
822
823     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
824     if (ret != 0) {
825         *tiling_mode = I915_TILING_NONE;
826         return -errno;
827     }
828
829     *tiling_mode = set_tiling.tiling_mode;
830     return 0;
831 }
832
833 static int
834 dri_gem_flink(dri_bo *bo, uint32_t *name)
835 {
836     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
837     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
838     struct drm_gem_flink flink;
839     int ret;
840
841     if (!bo_gem->global_name) {
842         flink.handle = bo_gem->gem_handle;
843     
844         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
845         if (ret != 0)
846             return -errno;
847         bo_gem->gem_handle = flink.name;
848     }
849     
850     *name = bo_gem->gem_handle;
851     return 0;
852 }
853
854 /**
855  * Enables unlimited caching of buffer objects for reuse.
856  *
857  * This is potentially very memory expensive, as the cache at each bucket
858  * size is only bounded by how many buffers of that size we've managed to have
859  * in flight at once.
860  */
861 void
862 intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr)
863 {
864     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
865     int i;
866
867     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
868         bufmgr_gem->cache_bucket[i].max_entries = -1;
869     }
870 }
871
872 /*
873  *
874  */
875 static int
876 dri_gem_check_aperture_space(dri_bo *bo_array, int count)
877 {
878     return 0;
879 }
880
881 /**
882  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
883  * and manage map buffer objections.
884  *
885  * \param fd File descriptor of the opened DRM device.
886  */
887 dri_bufmgr *
888 intel_bufmgr_gem_init(int fd, int batch_size)
889 {
890     dri_bufmgr_gem *bufmgr_gem;
891     int i;
892
893     bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
894     bufmgr_gem->fd = fd;
895
896     /* Let's go with one relocation per every 2 dwords (but round down a bit
897      * since a power of two will mean an extra page allocation for the reloc
898      * buffer).
899      *
900      * Every 4 was too few for the blender benchmark.
901      */
902     bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
903
904     bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
905     bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
906     bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
907     bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
908     bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
909     bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata;
910     bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata;
911     bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering;
912     bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
913     bufmgr_gem->bufmgr.process_relocs = dri_gem_process_reloc;
914     bufmgr_gem->bufmgr.post_submit = dri_gem_post_submit;
915     bufmgr_gem->bufmgr.debug = 0;
916     bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space;
917     bufmgr_gem->intel_bufmgr.emit_reloc = dri_gem_emit_reloc;
918     bufmgr_gem->intel_bufmgr.pin = dri_gem_pin;
919     bufmgr_gem->intel_bufmgr.unpin = dri_gem_unpin;
920     bufmgr_gem->intel_bufmgr.set_tiling = dri_gem_set_tiling;
921     bufmgr_gem->intel_bufmgr.flink = dri_gem_flink;
922     /* Initialize the linked lists for BO reuse cache. */
923     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++)
924         bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
925
926     return &bufmgr_gem->bufmgr;
927 }
928
929 int
930 intel_bo_emit_reloc(dri_bo *reloc_buf,
931                     uint32_t read_domains, uint32_t write_domain,
932                     uint32_t delta, uint32_t offset, dri_bo *target_buf)
933 {
934     struct intel_bufmgr *intel_bufmgr;
935
936     intel_bufmgr = (struct intel_bufmgr *)(reloc_buf->bufmgr + 1);
937
938     return intel_bufmgr->emit_reloc(reloc_buf, read_domains, write_domain,
939                                     delta, offset, target_buf);
940 }
941
942 int
943 intel_bo_pin(dri_bo *bo, uint32_t alignment)
944 {
945     struct intel_bufmgr *intel_bufmgr;
946
947     intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1);
948
949     if (intel_bufmgr->pin)
950         return intel_bufmgr->pin(bo, alignment);
951
952     return 0;
953 }
954
955 int
956 intel_bo_unpin(dri_bo *bo)
957 {
958     struct intel_bufmgr *intel_bufmgr;
959
960     intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1);
961
962     if (intel_bufmgr->unpin)
963         return intel_bufmgr->unpin(bo);
964
965     return 0;
966 }
967
968 int intel_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode)
969 {
970     struct intel_bufmgr *intel_bufmgr;
971
972     intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1);
973
974     if (intel_bufmgr->set_tiling)
975         return intel_bufmgr->set_tiling (bo, tiling_mode);
976
977     *tiling_mode = I915_TILING_NONE;
978     return 0;
979 }
980
981 int intel_bo_flink(dri_bo *bo, uint32_t *name)
982 {
983     struct intel_bufmgr *intel_bufmgr;
984
985     intel_bufmgr = (struct intel_bufmgr *)(bo->bufmgr + 1);
986
987     if (intel_bufmgr->flink)
988         return intel_bufmgr->flink (bo, name);
989
990     return -ENODEV;
991 }
992