intel bufmgr: reinstate buffer handle tracking
[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 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include <xf86drm.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <assert.h>
47 #include <sys/ioctl.h>
48 #include <sys/mman.h>
49
50 #include "errno.h"
51 #include "intel_bufmgr.h"
52 #include "intel_bufmgr_priv.h"
53 #include "string.h"
54
55 #include "i915_drm.h"
56
57 #define DBG(...) do {                                   \
58    if (bufmgr_gem->bufmgr.debug)                        \
59       fprintf(stderr, __VA_ARGS__);                     \
60 } while (0)
61
62 typedef struct _dri_bo_gem dri_bo_gem;
63
64 struct dri_gem_bo_bucket {
65    dri_bo_gem *head, **tail;
66    /**
67     * Limit on the number of entries in this bucket.
68     *
69     * 0 means that this caching at this bucket size is disabled.
70     * -1 means that there is no limit to caching at this size.
71     */
72    int max_entries;
73    int num_entries;
74 };
75
76 /* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
77  * is 1 << 16 pages, or 256MB.
78  */
79 #define INTEL_GEM_BO_BUCKETS    16
80 typedef struct _dri_bufmgr_gem {
81     dri_bufmgr bufmgr;
82
83     int fd;
84
85     int max_relocs;
86
87     struct drm_i915_gem_exec_object *exec_objects;
88     dri_bo **exec_bos;
89     int exec_size;
90     int exec_count;
91
92     /** Array of lists of cached gem objects of power-of-two sizes */
93     struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS];
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         bo_gem->bo.handle = bo_gem->gem_handle;
320         if (ret != 0) {
321             free(bo_gem);
322             return NULL;
323         }
324         bo_gem->bo.bufmgr = bufmgr;
325     }
326
327     bo_gem->name = name;
328     bo_gem->refcount = 1;
329     bo_gem->validate_index = -1;
330
331     DBG("bo_create: buf %d (%s) %ldb\n",
332         bo_gem->gem_handle, bo_gem->name, size);
333
334     return &bo_gem->bo;
335 }
336
337 /**
338  * Returns a dri_bo wrapping the given buffer object handle.
339  *
340  * This can be used when one application needs to pass a buffer object
341  * to another.
342  */
343 dri_bo *
344 intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
345                               unsigned int handle)
346 {
347     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
348     dri_bo_gem *bo_gem;
349     int ret;
350     struct drm_gem_open open_arg;
351
352     bo_gem = calloc(1, sizeof(*bo_gem));
353     if (!bo_gem)
354         return NULL;
355
356     memset(&open_arg, 0, sizeof(open_arg));
357     open_arg.name = handle;
358     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
359     if (ret != 0) {
360         fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
361                name, handle, strerror(errno));
362         free(bo_gem);
363         return NULL;
364     }
365     bo_gem->bo.size = open_arg.size;
366     bo_gem->bo.offset = 0;
367     bo_gem->bo.virtual = NULL;
368     bo_gem->bo.bufmgr = bufmgr;
369     bo_gem->name = name;
370     bo_gem->refcount = 1;
371     bo_gem->validate_index = -1;
372     bo_gem->gem_handle = open_arg.handle;
373     bo_gem->global_name = handle;
374
375     DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
376
377     return &bo_gem->bo;
378 }
379
380 static void
381 dri_gem_bo_reference(dri_bo *bo)
382 {
383     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
384
385     bo_gem->refcount++;
386 }
387
388 static void
389 dri_gem_bo_free(dri_bo *bo)
390 {
391     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
392     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
393     struct drm_gem_close close;
394     int ret;
395
396     if (bo_gem->mapped)
397         munmap (bo_gem->virtual, bo_gem->bo.size);
398
399     /* Close this object */
400     close.handle = bo_gem->gem_handle;
401     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
402     if (ret != 0) {
403         fprintf(stderr,
404                 "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
405                 bo_gem->gem_handle, bo_gem->name, strerror(errno));
406     }
407     free(bo);
408 }
409
410 static void
411 dri_gem_bo_unreference(dri_bo *bo)
412 {
413     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
414     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
415
416     if (!bo)
417         return;
418
419     if (--bo_gem->refcount == 0) {
420         struct dri_gem_bo_bucket *bucket;
421
422         if (bo_gem->relocs != NULL) {
423             int i;
424
425             /* Unreference all the target buffers */
426             for (i = 0; i < bo_gem->reloc_count; i++)
427                  dri_bo_unreference(bo_gem->reloc_target_bo[i]);
428             free(bo_gem->reloc_target_bo);
429             free(bo_gem->relocs);
430         }
431
432         DBG("bo_unreference final: %d (%s)\n",
433             bo_gem->gem_handle, bo_gem->name);
434
435         bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
436         /* Put the buffer into our internal cache for reuse if we can. */
437         if (bucket != NULL &&
438             (bucket->max_entries == -1 ||
439              (bucket->max_entries > 0 &&
440               bucket->num_entries < bucket->max_entries)))
441         {
442             bo_gem->name = 0;
443             bo_gem->validate_index = -1;
444             bo_gem->relocs = NULL;
445             bo_gem->reloc_target_bo = NULL;
446             bo_gem->reloc_count = 0;
447
448             bo_gem->next = NULL;
449             *bucket->tail = bo_gem;
450             bucket->tail = &bo_gem->next;
451             bucket->num_entries++;
452         } else {
453             dri_gem_bo_free(bo);
454         }
455
456         return;
457     }
458 }
459
460 static int
461 dri_gem_bo_map(dri_bo *bo, int write_enable)
462 {
463     dri_bufmgr_gem *bufmgr_gem;
464     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
465     struct drm_i915_gem_set_domain set_domain;
466     int ret;
467
468     bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
469
470     /* Allow recursive mapping. Mesa may recursively map buffers with
471      * nested display loops.
472      */
473     if (!bo_gem->mapped) {
474     
475         assert(bo->virtual == NULL);
476     
477         DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
478     
479         if (bo_gem->virtual == NULL) {
480             struct drm_i915_gem_mmap mmap_arg;
481     
482             memset(&mmap_arg, 0, sizeof(mmap_arg));
483             mmap_arg.handle = bo_gem->gem_handle;
484             mmap_arg.offset = 0;
485             mmap_arg.size = bo->size;
486             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
487             if (ret != 0) {
488                 fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
489                         __FILE__, __LINE__,
490                         bo_gem->gem_handle, bo_gem->name, strerror(errno));
491             }
492             bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
493         }
494         bo->virtual = bo_gem->virtual;
495         bo_gem->swrast = 0;
496         bo_gem->mapped = 1;
497         DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
498     }
499
500     if (!bo_gem->swrast) {
501         set_domain.handle = bo_gem->gem_handle;
502         set_domain.read_domains = I915_GEM_DOMAIN_CPU;
503         if (write_enable)
504             set_domain.write_domain = I915_GEM_DOMAIN_CPU;
505         else
506             set_domain.write_domain = 0;
507         do {
508             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
509                         &set_domain);
510         } while (ret == -1 && errno == EINTR);
511         if (ret != 0) {
512             fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
513                      __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
514         }
515         bo_gem->swrast = 1;
516     }
517
518     return 0;
519 }
520
521 static int
522 dri_gem_bo_unmap(dri_bo *bo)
523 {
524     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
525     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
526     struct drm_i915_gem_sw_finish sw_finish;
527     int ret;
528
529     if (bo == NULL)
530         return 0;
531
532     assert(bo_gem->mapped);
533
534     if (bo_gem->swrast) {
535         sw_finish.handle = bo_gem->gem_handle;
536         do {
537             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
538                         &sw_finish);
539         } while (ret == -1 && errno == EINTR);
540         bo_gem->swrast = 0;
541     }
542     return 0;
543 }
544
545 static int
546 dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,
547                     unsigned long size, const void *data)
548 {
549     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
550     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
551     struct drm_i915_gem_pwrite pwrite;
552     int ret;
553
554     memset (&pwrite, 0, sizeof (pwrite));
555     pwrite.handle = bo_gem->gem_handle;
556     pwrite.offset = offset;
557     pwrite.size = size;
558     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
559     do {
560         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
561     } while (ret == -1 && errno == EINTR);
562     if (ret != 0) {
563         fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
564                  __FILE__, __LINE__,
565                  bo_gem->gem_handle, (int) offset, (int) size,
566                  strerror (errno));
567     }
568     return 0;
569 }
570
571 static int
572 dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,
573                         unsigned long size, void *data)
574 {
575     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
576     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
577     struct drm_i915_gem_pread pread;
578     int ret;
579
580     memset (&pread, 0, sizeof (pread));
581     pread.handle = bo_gem->gem_handle;
582     pread.offset = offset;
583     pread.size = size;
584     pread.data_ptr = (uint64_t) (uintptr_t) data;
585     do {
586         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
587     } while (ret == -1 && errno == EINTR);
588     if (ret != 0) {
589         fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
590                  __FILE__, __LINE__,
591                  bo_gem->gem_handle, (int) offset, (int) size,
592                  strerror (errno));
593     }
594     return 0;
595 }
596
597 static void
598 dri_gem_bo_wait_rendering(dri_bo *bo)
599 {
600     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
601     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
602     struct drm_i915_gem_set_domain set_domain;
603     int ret;
604
605     set_domain.handle = bo_gem->gem_handle;
606     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
607     set_domain.write_domain = 0;
608     ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
609     if (ret != 0) {
610         fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
611                  __FILE__, __LINE__,
612                  bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
613                  strerror (errno));
614     }
615 }
616
617 static void
618 dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
619 {
620     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
621     int i;
622
623     free(bufmgr_gem->exec_objects);
624     free(bufmgr_gem->exec_bos);
625
626     /* Free any cached buffer objects we were going to reuse */
627     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
628         struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
629         dri_bo_gem *bo_gem;
630
631         while ((bo_gem = bucket->head) != NULL) {
632             bucket->head = bo_gem->next;
633             if (bo_gem->next == NULL)
634                 bucket->tail = &bucket->head;
635             bucket->num_entries--;
636
637             dri_gem_bo_free(&bo_gem->bo);
638         }
639     }
640
641     free(bufmgr);
642 }
643
644 /**
645  * Adds the target buffer to the validation list and adds the relocation
646  * to the reloc_buffer's relocation list.
647  *
648  * The relocation entry at the given offset must already contain the
649  * precomputed relocation value, because the kernel will optimize out
650  * the relocation entry write when the buffer hasn't moved from the
651  * last known offset in target_bo.
652  */
653 static int
654 dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,
655                       uint32_t delta, uint32_t offset, dri_bo *target_bo)
656 {
657     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
658     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
659     dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo;
660
661     /* Create a new relocation list if needed */
662     if (bo_gem->relocs == NULL)
663         intel_setup_reloc_list(bo);
664
665     /* Check overflow */
666     assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
667
668     /* Check args */
669     assert (offset <= bo->size - 4);
670     assert ((write_domain & (write_domain-1)) == 0);
671
672     bo_gem->relocs[bo_gem->reloc_count].offset = offset;
673     bo_gem->relocs[bo_gem->reloc_count].delta = delta;
674     bo_gem->relocs[bo_gem->reloc_count].target_handle =
675         target_bo_gem->gem_handle;
676     bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
677     bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
678     bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
679
680     bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
681     dri_bo_reference(target_bo);
682
683     bo_gem->reloc_count++;
684     return 0;
685 }
686
687 /**
688  * Walk the tree of relocations rooted at BO and accumulate the list of
689  * validations to be performed and update the relocation buffers with
690  * index values into the validation list.
691  */
692 static void
693 dri_gem_bo_process_reloc(dri_bo *bo)
694 {
695     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
696     int i;
697
698     if (bo_gem->relocs == NULL)
699         return;
700
701     for (i = 0; i < bo_gem->reloc_count; i++) {
702         dri_bo *target_bo = bo_gem->reloc_target_bo[i];
703
704         /* Continue walking the tree depth-first. */
705         dri_gem_bo_process_reloc(target_bo);
706
707         /* Add the target to the validate list */
708         intel_add_validate_buffer(target_bo);
709     }
710 }
711
712 static void
713 intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem)
714 {
715     int i;
716
717     for (i = 0; i < bufmgr_gem->exec_count; i++) {
718         dri_bo *bo = bufmgr_gem->exec_bos[i];
719         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
720
721         /* Update the buffer offset */
722         if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
723             DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
724                 bo_gem->gem_handle, bo_gem->name, bo->offset,
725                 bufmgr_gem->exec_objects[i].offset);
726             bo->offset = bufmgr_gem->exec_objects[i].offset;
727         }
728     }
729 }
730
731 static int
732 dri_gem_bo_exec(dri_bo *bo, int used,
733                 drm_clip_rect_t *cliprects, int num_cliprects,
734                 int DR4)
735 {
736     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
737     struct drm_i915_gem_execbuffer execbuf;
738     int ret, i;
739
740     /* Update indices and set up the validate list. */
741     dri_gem_bo_process_reloc(bo);
742
743     /* Add the batch buffer to the validation list.  There are no relocations
744      * pointing to it.
745      */
746     intel_add_validate_buffer(bo);
747
748     execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
749     execbuf.buffer_count = bufmgr_gem->exec_count;
750     execbuf.batch_start_offset = 0;
751     execbuf.batch_len = used;
752     execbuf.cliprects_ptr = (uintptr_t)cliprects;
753     execbuf.num_cliprects = num_cliprects;
754     execbuf.DR1 = 0;
755     execbuf.DR4 = DR4;
756
757     do {
758         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf);
759     } while (ret == -EAGAIN);
760
761     intel_update_buffer_offsets (bufmgr_gem);
762
763     if (bufmgr_gem->bufmgr.debug)
764         dri_gem_dump_validation_list(bufmgr_gem);
765
766     for (i = 0; i < bufmgr_gem->exec_count; i++) {
767         dri_bo *bo = bufmgr_gem->exec_bos[i];
768         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
769
770         /* Need to call swrast on next bo_map */
771         bo_gem->swrast = 0;
772
773         /* Disconnect the buffer from the validate list */
774         bo_gem->validate_index = -1;
775         dri_bo_unreference(bo);
776         bufmgr_gem->exec_bos[i] = NULL;
777     }
778     bufmgr_gem->exec_count = 0;
779
780     return 0;
781 }
782
783 static int
784 dri_gem_bo_pin(dri_bo *bo, uint32_t alignment)
785 {
786     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
787     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
788     struct drm_i915_gem_pin pin;
789     int ret;
790
791     pin.handle = bo_gem->gem_handle;
792     pin.alignment = alignment;
793
794     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
795     if (ret != 0)
796         return -errno;
797
798     bo->offset = pin.offset;
799     return 0;
800 }
801
802 static int
803 dri_gem_bo_unpin(dri_bo *bo)
804 {
805     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
806     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
807     struct drm_i915_gem_unpin unpin;
808     int ret;
809
810     unpin.handle = bo_gem->gem_handle;
811
812     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
813     if (ret != 0)
814         return -errno;
815
816     return 0;
817 }
818
819 static int
820 dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode)
821 {
822     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
823     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
824     struct drm_i915_gem_set_tiling set_tiling;
825     int ret;
826
827     set_tiling.handle = bo_gem->gem_handle;
828     set_tiling.tiling_mode = *tiling_mode;
829
830     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
831     if (ret != 0) {
832         *tiling_mode = I915_TILING_NONE;
833         return -errno;
834     }
835
836     *tiling_mode = set_tiling.tiling_mode;
837     return 0;
838 }
839
840 static int
841 dri_gem_bo_flink(dri_bo *bo, uint32_t *name)
842 {
843     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
844     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
845     struct drm_gem_flink flink;
846     int ret;
847
848     if (!bo_gem->global_name) {
849         flink.handle = bo_gem->gem_handle;
850     
851         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
852         if (ret != 0)
853             return -errno;
854         bo_gem->global_name = flink.name;
855     }
856     
857     *name = bo_gem->global_name;
858     return 0;
859 }
860
861 /**
862  * Enables unlimited caching of buffer objects for reuse.
863  *
864  * This is potentially very memory expensive, as the cache at each bucket
865  * size is only bounded by how many buffers of that size we've managed to have
866  * in flight at once.
867  */
868 void
869 intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr)
870 {
871     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
872     int i;
873
874     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
875         bufmgr_gem->cache_bucket[i].max_entries = -1;
876     }
877 }
878
879 /*
880  *
881  */
882 static int
883 dri_gem_check_aperture_space(dri_bo **bo_array, int count)
884 {
885     return 0;
886 }
887
888 /**
889  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
890  * and manage map buffer objections.
891  *
892  * \param fd File descriptor of the opened DRM device.
893  */
894 dri_bufmgr *
895 intel_bufmgr_gem_init(int fd, int batch_size)
896 {
897     dri_bufmgr_gem *bufmgr_gem;
898     int i;
899
900     bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
901     bufmgr_gem->fd = fd;
902
903     /* Let's go with one relocation per every 2 dwords (but round down a bit
904      * since a power of two will mean an extra page allocation for the reloc
905      * buffer).
906      *
907      * Every 4 was too few for the blender benchmark.
908      */
909     bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
910
911     bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
912     bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
913     bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
914     bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
915     bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
916     bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata;
917     bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata;
918     bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering;
919     bufmgr_gem->bufmgr.bo_emit_reloc = dri_gem_bo_emit_reloc;
920     bufmgr_gem->bufmgr.bo_pin = dri_gem_bo_pin;
921     bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin;
922     bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling;
923     bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink;
924     bufmgr_gem->bufmgr.bo_exec = dri_gem_bo_exec;
925     bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
926     bufmgr_gem->bufmgr.debug = 0;
927     bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space;
928     /* Initialize the linked lists for BO reuse cache. */
929     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++)
930         bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
931
932     return &bufmgr_gem->bufmgr;
933 }
934