dd74659aeaaba97a27f7c25e3163413963146fa8
[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 <pthread.h>
48 #include <sys/ioctl.h>
49 #include <sys/mman.h>
50
51 #include "errno.h"
52 #include "intel_bufmgr.h"
53 #include "intel_bufmgr_priv.h"
54 #include "string.h"
55
56 #include "i915_drm.h"
57
58 #define DBG(...) do {                                   \
59    if (bufmgr_gem->bufmgr.debug)                        \
60       fprintf(stderr, __VA_ARGS__);                     \
61 } while (0)
62
63 typedef struct _dri_bo_gem dri_bo_gem;
64
65 struct dri_gem_bo_bucket {
66    dri_bo_gem *head, **tail;
67    /**
68     * Limit on the number of entries in this bucket.
69     *
70     * 0 means that this caching at this bucket size is disabled.
71     * -1 means that there is no limit to caching at this size.
72     */
73    int max_entries;
74    int num_entries;
75 };
76
77 /* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
78  * is 1 << 16 pages, or 256MB.
79  */
80 #define INTEL_GEM_BO_BUCKETS    16
81 typedef struct _dri_bufmgr_gem {
82     dri_bufmgr bufmgr;
83
84     int fd;
85
86     int max_relocs;
87
88     pthread_mutex_t lock;
89
90     struct drm_i915_gem_exec_object *exec_objects;
91     dri_bo **exec_bos;
92     int exec_size;
93     int exec_count;
94
95     /** Array of lists of cached gem objects of power-of-two sizes */
96     struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS];
97
98     uint64_t gtt_size;
99 } dri_bufmgr_gem;
100
101 struct _dri_bo_gem {
102     dri_bo bo;
103
104     int refcount;
105     /** Boolean whether the mmap ioctl has been called for this buffer yet. */
106     int mapped;
107     uint32_t gem_handle;
108     const char *name;
109
110     /**
111      * Kenel-assigned global name for this object
112      */
113     unsigned int global_name;
114     
115     /**
116      * Index of the buffer within the validation list while preparing a
117      * batchbuffer execution.
118      */
119     int validate_index;
120
121     /**
122      * Boolean whether we've started swrast
123      * Set when the buffer has been mapped
124      * Cleared when the buffer is unmapped
125      */
126     int swrast;
127
128     /** Array passed to the DRM containing relocation information. */
129     struct drm_i915_gem_relocation_entry *relocs;
130     /** Array of bos corresponding to relocs[i].target_handle */
131     dri_bo **reloc_target_bo;
132     /** Number of entries in relocs */
133     int reloc_count;
134     /** Mapped address for the buffer */
135     void *virtual;
136
137     /** free list */
138     dri_bo_gem *next;
139
140     /**
141      * Boolean of whether this BO and its children have been included in
142      * the current dri_bufmgr_check_aperture_space() total.
143      */
144     char included_in_check_aperture;
145
146     /**
147      * Boolean of whether this buffer has been used as a relocation
148      * target and had its size accounted for, and thus can't have any
149      * further relocations added to it.
150      */
151      char used_as_reloc_target;
152
153     /**
154      * Size in bytes of this buffer and its relocation descendents.
155      *
156      * Used to avoid costly tree walking in dri_bufmgr_check_aperture in
157      * the common case.
158      */
159     int reloc_tree_size;
160 };
161
162 static void dri_gem_bo_reference_locked(dri_bo *bo);
163
164 static int
165 logbase2(int n)
166 {
167    int i = 1;
168    int log2 = 0;
169
170    while (n > i) {
171       i *= 2;
172       log2++;
173    }
174
175    return log2;
176 }
177
178 static struct dri_gem_bo_bucket *
179 dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)
180 {
181     int i;
182
183     /* We only do buckets in power of two increments */
184     if ((size & (size - 1)) != 0)
185         return NULL;
186
187     /* We should only see sizes rounded to pages. */
188     assert((size % 4096) == 0);
189
190     /* We always allocate in units of pages */
191     i = ffs(size / 4096) - 1;
192     if (i >= INTEL_GEM_BO_BUCKETS)
193         return NULL;
194
195     return &bufmgr_gem->cache_bucket[i];
196 }
197
198
199 static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)
200 {
201     int i, j;
202
203     for (i = 0; i < bufmgr_gem->exec_count; i++) {
204         dri_bo *bo = bufmgr_gem->exec_bos[i];
205         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
206
207         if (bo_gem->relocs == NULL) {
208             DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name);
209             continue;
210         }
211
212         for (j = 0; j < bo_gem->reloc_count; j++) {
213             dri_bo *target_bo = bo_gem->reloc_target_bo[j];
214             dri_bo_gem *target_gem = (dri_bo_gem *)target_bo;
215
216             DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",
217                 i,
218                 bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset,
219                 target_gem->gem_handle, target_gem->name, target_bo->offset,
220                 bo_gem->relocs[j].delta);
221         }
222     }
223 }
224
225 /**
226  * Adds the given buffer to the list of buffers to be validated (moved into the
227  * appropriate memory type) with the next batch submission.
228  *
229  * If a buffer is validated multiple times in a batch submission, it ends up
230  * with the intersection of the memory type flags and the union of the
231  * access flags.
232  */
233 static void
234 intel_add_validate_buffer(dri_bo *bo)
235 {
236     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
237     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
238     int index;
239
240     if (bo_gem->validate_index != -1)
241         return;
242
243     /* Extend the array of validation entries as necessary. */
244     if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
245         int new_size = bufmgr_gem->exec_size * 2;
246
247         if (new_size == 0)
248             new_size = 5;
249
250         bufmgr_gem->exec_objects =
251             realloc(bufmgr_gem->exec_objects,
252                     sizeof(*bufmgr_gem->exec_objects) * new_size);
253         bufmgr_gem->exec_bos =
254             realloc(bufmgr_gem->exec_bos,
255                     sizeof(*bufmgr_gem->exec_bos) * new_size);
256         bufmgr_gem->exec_size = new_size;
257     }
258
259     index = bufmgr_gem->exec_count;
260     bo_gem->validate_index = index;
261     /* Fill in array entry */
262     bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
263     bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
264     bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
265     bufmgr_gem->exec_objects[index].alignment = 0;
266     bufmgr_gem->exec_objects[index].offset = 0;
267     bufmgr_gem->exec_bos[index] = bo;
268     dri_gem_bo_reference_locked(bo);
269     bufmgr_gem->exec_count++;
270 }
271
272
273 #define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
274         sizeof(uint32_t))
275
276 static int
277 intel_setup_reloc_list(dri_bo *bo)
278 {
279     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
280     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
281
282     bo_gem->relocs = malloc(bufmgr_gem->max_relocs *
283                             sizeof(struct drm_i915_gem_relocation_entry));
284     bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * sizeof(dri_bo *));
285
286     return 0;
287 }
288
289 static dri_bo *
290 dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
291                  unsigned long size, unsigned int alignment)
292 {
293     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
294     dri_bo_gem *bo_gem;
295     unsigned int page_size = getpagesize();
296     int ret;
297     struct dri_gem_bo_bucket *bucket;
298     int alloc_from_cache = 0;
299     unsigned long bo_size;
300
301     /* Round the allocated size up to a power of two number of pages. */
302     bo_size = 1 << logbase2(size);
303     if (bo_size < page_size)
304         bo_size = page_size;
305     bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
306
307     /* If we don't have caching at this size, don't actually round the
308      * allocation up.
309      */
310     if (bucket == NULL || bucket->max_entries == 0) {
311         bo_size = size;
312         if (bo_size < page_size)
313             bo_size = page_size;
314     }
315
316     pthread_mutex_lock(&bufmgr_gem->lock);
317     /* Get a buffer out of the cache if available */
318     if (bucket != NULL && bucket->num_entries > 0) {
319         struct drm_i915_gem_busy busy;
320         
321         bo_gem = bucket->head;
322         busy.handle = bo_gem->gem_handle;
323
324         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
325         alloc_from_cache = (ret == 0 && busy.busy == 0);
326
327         if (alloc_from_cache) {
328             bucket->head = bo_gem->next;
329             if (bo_gem->next == NULL)
330                 bucket->tail = &bucket->head;
331             bucket->num_entries--;
332         }
333     }
334     pthread_mutex_unlock(&bufmgr_gem->lock);
335
336     if (!alloc_from_cache) {
337         struct drm_i915_gem_create create;
338
339         bo_gem = calloc(1, sizeof(*bo_gem));
340         if (!bo_gem)
341             return NULL;
342
343         bo_gem->bo.size = bo_size;
344         memset(&create, 0, sizeof(create));
345         create.size = bo_size;
346
347         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
348         bo_gem->gem_handle = create.handle;
349         if (ret != 0) {
350             free(bo_gem);
351             return NULL;
352         }
353         bo_gem->bo.bufmgr = bufmgr;
354     }
355
356     bo_gem->name = name;
357     bo_gem->refcount = 1;
358     bo_gem->validate_index = -1;
359     bo_gem->reloc_tree_size = bo_gem->bo.size;
360     bo_gem->used_as_reloc_target = 0;
361
362     DBG("bo_create: buf %d (%s) %ldb\n",
363         bo_gem->gem_handle, bo_gem->name, size);
364
365     return &bo_gem->bo;
366 }
367
368 /**
369  * Returns a dri_bo wrapping the given buffer object handle.
370  *
371  * This can be used when one application needs to pass a buffer object
372  * to another.
373  */
374 dri_bo *
375 intel_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name,
376                               unsigned int handle)
377 {
378     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
379     dri_bo_gem *bo_gem;
380     int ret;
381     struct drm_gem_open open_arg;
382
383     bo_gem = calloc(1, sizeof(*bo_gem));
384     if (!bo_gem)
385         return NULL;
386
387     memset(&open_arg, 0, sizeof(open_arg));
388     open_arg.name = handle;
389     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
390     if (ret != 0) {
391         fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
392                name, handle, strerror(errno));
393         free(bo_gem);
394         return NULL;
395     }
396     bo_gem->bo.size = open_arg.size;
397     bo_gem->bo.offset = 0;
398     bo_gem->bo.virtual = NULL;
399     bo_gem->bo.bufmgr = bufmgr;
400     bo_gem->name = name;
401     bo_gem->refcount = 1;
402     bo_gem->validate_index = -1;
403     bo_gem->gem_handle = open_arg.handle;
404     bo_gem->global_name = handle;
405
406     DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
407
408     return &bo_gem->bo;
409 }
410
411 static void
412 dri_gem_bo_reference(dri_bo *bo)
413 {
414     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
415     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
416
417     pthread_mutex_lock(&bufmgr_gem->lock);
418     bo_gem->refcount++;
419     pthread_mutex_unlock(&bufmgr_gem->lock);
420 }
421
422 static void
423 dri_gem_bo_reference_locked(dri_bo *bo)
424 {
425     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
426
427     bo_gem->refcount++;
428 }
429
430 static void
431 dri_gem_bo_free(dri_bo *bo)
432 {
433     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
434     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
435     struct drm_gem_close close;
436     int ret;
437
438     if (bo_gem->mapped)
439         munmap (bo_gem->virtual, bo_gem->bo.size);
440
441     /* Close this object */
442     close.handle = bo_gem->gem_handle;
443     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
444     if (ret != 0) {
445         fprintf(stderr,
446                 "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
447                 bo_gem->gem_handle, bo_gem->name, strerror(errno));
448     }
449     free(bo);
450 }
451
452 static void
453 dri_gem_bo_unreference_locked(dri_bo *bo)
454 {
455     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
456     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
457
458     if (--bo_gem->refcount == 0) {
459         struct dri_gem_bo_bucket *bucket;
460
461         if (bo_gem->relocs != NULL) {
462             int i;
463
464             /* Unreference all the target buffers */
465             for (i = 0; i < bo_gem->reloc_count; i++)
466                  dri_gem_bo_unreference_locked(bo_gem->reloc_target_bo[i]);
467             free(bo_gem->reloc_target_bo);
468             free(bo_gem->relocs);
469         }
470
471         DBG("bo_unreference final: %d (%s)\n",
472             bo_gem->gem_handle, bo_gem->name);
473
474         bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
475         /* Put the buffer into our internal cache for reuse if we can. */
476         if (bucket != NULL &&
477             (bucket->max_entries == -1 ||
478              (bucket->max_entries > 0 &&
479               bucket->num_entries < bucket->max_entries)))
480         {
481             bo_gem->name = 0;
482             bo_gem->validate_index = -1;
483             bo_gem->relocs = NULL;
484             bo_gem->reloc_target_bo = NULL;
485             bo_gem->reloc_count = 0;
486
487             bo_gem->next = NULL;
488             *bucket->tail = bo_gem;
489             bucket->tail = &bo_gem->next;
490             bucket->num_entries++;
491         } else {
492             dri_gem_bo_free(bo);
493         }
494     }
495 }
496
497 static void
498 dri_gem_bo_unreference(dri_bo *bo)
499 {
500     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
501
502     pthread_mutex_lock(&bufmgr_gem->lock);
503     dri_gem_bo_unreference_locked(bo);
504     pthread_mutex_unlock(&bufmgr_gem->lock);
505 }
506
507 static int
508 dri_gem_bo_map(dri_bo *bo, int write_enable)
509 {
510     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
511     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
512     struct drm_i915_gem_set_domain set_domain;
513     int ret;
514
515     pthread_mutex_lock(&bufmgr_gem->lock);
516
517     /* Allow recursive mapping. Mesa may recursively map buffers with
518      * nested display loops.
519      */
520     if (!bo_gem->mapped) {
521     
522         assert(bo->virtual == NULL);
523     
524         DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
525     
526         if (bo_gem->virtual == NULL) {
527             struct drm_i915_gem_mmap mmap_arg;
528     
529             memset(&mmap_arg, 0, sizeof(mmap_arg));
530             mmap_arg.handle = bo_gem->gem_handle;
531             mmap_arg.offset = 0;
532             mmap_arg.size = bo->size;
533             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
534             if (ret != 0) {
535                 fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
536                         __FILE__, __LINE__,
537                         bo_gem->gem_handle, bo_gem->name, strerror(errno));
538             }
539             bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
540         }
541         bo->virtual = bo_gem->virtual;
542         bo_gem->swrast = 0;
543         bo_gem->mapped = 1;
544         DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
545     }
546
547     if (!bo_gem->swrast) {
548         set_domain.handle = bo_gem->gem_handle;
549         set_domain.read_domains = I915_GEM_DOMAIN_CPU;
550         if (write_enable)
551             set_domain.write_domain = I915_GEM_DOMAIN_CPU;
552         else
553             set_domain.write_domain = 0;
554         do {
555             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
556                         &set_domain);
557         } while (ret == -1 && errno == EINTR);
558         if (ret != 0) {
559             fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
560                      __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
561         }
562         bo_gem->swrast = 1;
563     }
564
565     pthread_mutex_unlock(&bufmgr_gem->lock);
566
567     return 0;
568 }
569
570 static int
571 dri_gem_bo_unmap(dri_bo *bo)
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_sw_finish sw_finish;
576     int ret;
577
578     if (bo == NULL)
579         return 0;
580
581     assert(bo_gem->mapped);
582
583     pthread_mutex_lock(&bufmgr_gem->lock);
584     if (bo_gem->swrast) {
585         sw_finish.handle = bo_gem->gem_handle;
586         do {
587             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
588                         &sw_finish);
589         } while (ret == -1 && errno == EINTR);
590         bo_gem->swrast = 0;
591     }
592     pthread_mutex_unlock(&bufmgr_gem->lock);
593     return 0;
594 }
595
596 static int
597 dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,
598                     unsigned long size, const void *data)
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_pwrite pwrite;
603     int ret;
604
605     memset (&pwrite, 0, sizeof (pwrite));
606     pwrite.handle = bo_gem->gem_handle;
607     pwrite.offset = offset;
608     pwrite.size = size;
609     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
610     do {
611         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
612     } while (ret == -1 && errno == EINTR);
613     if (ret != 0) {
614         fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
615                  __FILE__, __LINE__,
616                  bo_gem->gem_handle, (int) offset, (int) size,
617                  strerror (errno));
618     }
619     return 0;
620 }
621
622 static int
623 dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,
624                         unsigned long size, void *data)
625 {
626     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
627     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
628     struct drm_i915_gem_pread pread;
629     int ret;
630
631     memset (&pread, 0, sizeof (pread));
632     pread.handle = bo_gem->gem_handle;
633     pread.offset = offset;
634     pread.size = size;
635     pread.data_ptr = (uint64_t) (uintptr_t) data;
636     do {
637         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
638     } while (ret == -1 && errno == EINTR);
639     if (ret != 0) {
640         fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
641                  __FILE__, __LINE__,
642                  bo_gem->gem_handle, (int) offset, (int) size,
643                  strerror (errno));
644     }
645     return 0;
646 }
647
648 static void
649 dri_gem_bo_wait_rendering(dri_bo *bo)
650 {
651     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
652     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
653     struct drm_i915_gem_set_domain set_domain;
654     int ret;
655
656     set_domain.handle = bo_gem->gem_handle;
657     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
658     set_domain.write_domain = 0;
659     ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
660     if (ret != 0) {
661         fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
662                  __FILE__, __LINE__,
663                  bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
664                  strerror (errno));
665     }
666 }
667
668 static void
669 dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
670 {
671     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
672     int i;
673
674     free(bufmgr_gem->exec_objects);
675     free(bufmgr_gem->exec_bos);
676
677     pthread_mutex_destroy(&bufmgr_gem->lock);
678
679     /* Free any cached buffer objects we were going to reuse */
680     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
681         struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
682         dri_bo_gem *bo_gem;
683
684         while ((bo_gem = bucket->head) != NULL) {
685             bucket->head = bo_gem->next;
686             if (bo_gem->next == NULL)
687                 bucket->tail = &bucket->head;
688             bucket->num_entries--;
689
690             dri_gem_bo_free(&bo_gem->bo);
691         }
692     }
693
694     free(bufmgr);
695 }
696
697 /**
698  * Adds the target buffer to the validation list and adds the relocation
699  * to the reloc_buffer's relocation list.
700  *
701  * The relocation entry at the given offset must already contain the
702  * precomputed relocation value, because the kernel will optimize out
703  * the relocation entry write when the buffer hasn't moved from the
704  * last known offset in target_bo.
705  */
706 static int
707 dri_gem_bo_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,
708                       uint32_t delta, uint32_t offset, dri_bo *target_bo)
709 {
710     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
711     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
712     dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo;
713
714     pthread_mutex_lock(&bufmgr_gem->lock);
715
716     /* Create a new relocation list if needed */
717     if (bo_gem->relocs == NULL)
718         intel_setup_reloc_list(bo);
719
720     /* Check overflow */
721     assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
722
723     /* Check args */
724     assert (offset <= bo->size - 4);
725     assert ((write_domain & (write_domain-1)) == 0);
726
727     /* Make sure that we're not adding a reloc to something whose size has
728      * already been accounted for.
729      */
730     assert(!bo_gem->used_as_reloc_target);
731     bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
732
733     /* Flag the target to disallow further relocations in it. */
734     target_bo_gem->used_as_reloc_target = 1;
735
736     bo_gem->relocs[bo_gem->reloc_count].offset = offset;
737     bo_gem->relocs[bo_gem->reloc_count].delta = delta;
738     bo_gem->relocs[bo_gem->reloc_count].target_handle =
739         target_bo_gem->gem_handle;
740     bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
741     bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
742     bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
743
744     bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
745     dri_gem_bo_reference_locked(target_bo);
746
747     bo_gem->reloc_count++;
748
749     pthread_mutex_unlock(&bufmgr_gem->lock);
750
751     return 0;
752 }
753
754 /**
755  * Walk the tree of relocations rooted at BO and accumulate the list of
756  * validations to be performed and update the relocation buffers with
757  * index values into the validation list.
758  */
759 static void
760 dri_gem_bo_process_reloc(dri_bo *bo)
761 {
762     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
763     int i;
764
765     if (bo_gem->relocs == NULL)
766         return;
767
768     for (i = 0; i < bo_gem->reloc_count; i++) {
769         dri_bo *target_bo = bo_gem->reloc_target_bo[i];
770
771         /* Continue walking the tree depth-first. */
772         dri_gem_bo_process_reloc(target_bo);
773
774         /* Add the target to the validate list */
775         intel_add_validate_buffer(target_bo);
776     }
777 }
778
779 static void
780 intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem)
781 {
782     int i;
783
784     for (i = 0; i < bufmgr_gem->exec_count; i++) {
785         dri_bo *bo = bufmgr_gem->exec_bos[i];
786         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
787
788         /* Update the buffer offset */
789         if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
790             DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
791                 bo_gem->gem_handle, bo_gem->name, bo->offset,
792                 bufmgr_gem->exec_objects[i].offset);
793             bo->offset = bufmgr_gem->exec_objects[i].offset;
794         }
795     }
796 }
797
798 static int
799 dri_gem_bo_exec(dri_bo *bo, int used,
800                 drm_clip_rect_t *cliprects, int num_cliprects,
801                 int DR4)
802 {
803     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
804     struct drm_i915_gem_execbuffer execbuf;
805     int ret, i;
806
807     pthread_mutex_lock(&bufmgr_gem->lock);
808     /* Update indices and set up the validate list. */
809     dri_gem_bo_process_reloc(bo);
810
811     /* Add the batch buffer to the validation list.  There are no relocations
812      * pointing to it.
813      */
814     intel_add_validate_buffer(bo);
815
816     execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
817     execbuf.buffer_count = bufmgr_gem->exec_count;
818     execbuf.batch_start_offset = 0;
819     execbuf.batch_len = used;
820     execbuf.cliprects_ptr = (uintptr_t)cliprects;
821     execbuf.num_cliprects = num_cliprects;
822     execbuf.DR1 = 0;
823     execbuf.DR4 = DR4;
824
825     do {
826         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf);
827     } while (ret != 0 && errno == EAGAIN);
828
829     intel_update_buffer_offsets (bufmgr_gem);
830
831     if (bufmgr_gem->bufmgr.debug)
832         dri_gem_dump_validation_list(bufmgr_gem);
833
834     for (i = 0; i < bufmgr_gem->exec_count; i++) {
835         dri_bo *bo = bufmgr_gem->exec_bos[i];
836         dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
837
838         /* Need to call swrast on next bo_map */
839         bo_gem->swrast = 0;
840
841         /* Disconnect the buffer from the validate list */
842         bo_gem->validate_index = -1;
843         dri_gem_bo_unreference_locked(bo);
844         bufmgr_gem->exec_bos[i] = NULL;
845     }
846     bufmgr_gem->exec_count = 0;
847     pthread_mutex_unlock(&bufmgr_gem->lock);
848
849     return 0;
850 }
851
852 static int
853 dri_gem_bo_pin(dri_bo *bo, uint32_t alignment)
854 {
855     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
856     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
857     struct drm_i915_gem_pin pin;
858     int ret;
859
860     pin.handle = bo_gem->gem_handle;
861     pin.alignment = alignment;
862
863     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
864     if (ret != 0)
865         return -errno;
866
867     bo->offset = pin.offset;
868     return 0;
869 }
870
871 static int
872 dri_gem_bo_unpin(dri_bo *bo)
873 {
874     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
875     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
876     struct drm_i915_gem_unpin unpin;
877     int ret;
878
879     unpin.handle = bo_gem->gem_handle;
880
881     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
882     if (ret != 0)
883         return -errno;
884
885     return 0;
886 }
887
888 static int
889 dri_gem_bo_set_tiling(dri_bo *bo, uint32_t *tiling_mode)
890 {
891     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
892     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
893     struct drm_i915_gem_set_tiling set_tiling;
894     int ret;
895
896     set_tiling.handle = bo_gem->gem_handle;
897     set_tiling.tiling_mode = *tiling_mode;
898
899     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
900     if (ret != 0) {
901         *tiling_mode = I915_TILING_NONE;
902         return -errno;
903     }
904
905     *tiling_mode = set_tiling.tiling_mode;
906     return 0;
907 }
908
909 static int
910 dri_gem_bo_get_tiling(dri_bo *bo, uint32_t *tiling_mode, uint32_t *swizzle_mode)
911 {
912     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
913     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
914     struct drm_i915_gem_get_tiling get_tiling;
915     int ret;
916
917     get_tiling.handle = bo_gem->gem_handle;
918
919     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
920     if (ret != 0) {
921         *tiling_mode = I915_TILING_NONE;
922         *swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
923         return -errno;
924     }
925
926     *tiling_mode = get_tiling.tiling_mode;
927     *swizzle_mode = get_tiling.swizzle_mode;
928     return 0;
929 }
930
931 static int
932 dri_gem_bo_flink(dri_bo *bo, uint32_t *name)
933 {
934     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
935     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
936     struct drm_gem_flink flink;
937     int ret;
938
939     if (!bo_gem->global_name) {
940         flink.handle = bo_gem->gem_handle;
941     
942         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
943         if (ret != 0)
944             return -errno;
945         bo_gem->global_name = flink.name;
946     }
947     
948     *name = bo_gem->global_name;
949     return 0;
950 }
951
952 /**
953  * Enables unlimited caching of buffer objects for reuse.
954  *
955  * This is potentially very memory expensive, as the cache at each bucket
956  * size is only bounded by how many buffers of that size we've managed to have
957  * in flight at once.
958  */
959 void
960 intel_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr)
961 {
962     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
963     int i;
964
965     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
966         bufmgr_gem->cache_bucket[i].max_entries = -1;
967     }
968 }
969
970 /**
971  * Return the additional aperture space required by the tree of buffer objects
972  * rooted at bo.
973  */
974 static int
975 dri_gem_bo_get_aperture_space(dri_bo *bo)
976 {
977     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
978     int i;
979     int total = 0;
980
981     if (bo == NULL || bo_gem->included_in_check_aperture)
982         return 0;
983
984     total += bo->size;
985     bo_gem->included_in_check_aperture = 1;
986
987     for (i = 0; i < bo_gem->reloc_count; i++)
988         total += dri_gem_bo_get_aperture_space(bo_gem->reloc_target_bo[i]);
989
990     return total;
991 }
992
993 /**
994  * Clear the flag set by dri_gem_bo_get_aperture_space() so we're ready for
995  * the next dri_bufmgr_check_aperture_space() call.
996  */
997 static void
998 dri_gem_bo_clear_aperture_space_flag(dri_bo *bo)
999 {
1000     dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
1001     int i;
1002
1003     if (bo == NULL || !bo_gem->included_in_check_aperture)
1004         return;
1005
1006     bo_gem->included_in_check_aperture = 0;
1007
1008     for (i = 0; i < bo_gem->reloc_count; i++)
1009         dri_gem_bo_clear_aperture_space_flag(bo_gem->reloc_target_bo[i]);
1010 }
1011
1012 /**
1013  * Return -1 if the batchbuffer should be flushed before attempting to
1014  * emit rendering referencing the buffers pointed to by bo_array.
1015  *
1016  * This is required because if we try to emit a batchbuffer with relocations
1017  * to a tree of buffers that won't simultaneously fit in the aperture,
1018  * the rendering will return an error at a point where the software is not
1019  * prepared to recover from it.
1020  *
1021  * However, we also want to emit the batchbuffer significantly before we reach
1022  * the limit, as a series of batchbuffers each of which references buffers
1023  * covering almost all of the aperture means that at each emit we end up
1024  * waiting to evict a buffer from the last rendering, and we get synchronous
1025  * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
1026  * get better parallelism.
1027  */
1028 static int
1029 dri_gem_check_aperture_space(dri_bo **bo_array, int count)
1030 {
1031     dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo_array[0]->bufmgr;
1032     unsigned int total = 0;
1033     unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
1034     int i;
1035
1036     for (i = 0; i < count; i++) {
1037         dri_bo_gem *bo_gem = (dri_bo_gem *)bo_array[i];
1038         if (bo_gem != NULL)
1039                 total += bo_gem->reloc_tree_size;
1040     }
1041
1042     if (total > threshold) {
1043         total = 0;
1044         for (i = 0; i < count; i++)
1045             total += dri_gem_bo_get_aperture_space(bo_array[i]);
1046
1047         for (i = 0; i < count; i++)
1048             dri_gem_bo_clear_aperture_space_flag(bo_array[i]);
1049     }
1050
1051     if (total > bufmgr_gem->gtt_size * 3 / 4) {
1052         DBG("check_space: overflowed available aperture, %dkb vs %dkb\n",
1053             total / 1024, (int)bufmgr_gem->gtt_size / 1024);
1054         return -1;
1055     } else {
1056         DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024 ,
1057             (int)bufmgr_gem->gtt_size / 1024);
1058         return 0;
1059     }
1060 }
1061
1062 /**
1063  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
1064  * and manage map buffer objections.
1065  *
1066  * \param fd File descriptor of the opened DRM device.
1067  */
1068 dri_bufmgr *
1069 intel_bufmgr_gem_init(int fd, int batch_size)
1070 {
1071     dri_bufmgr_gem *bufmgr_gem;
1072     struct drm_i915_gem_get_aperture aperture;
1073     int ret, i;
1074
1075     bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
1076     bufmgr_gem->fd = fd;
1077
1078     if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) {
1079       free(bufmgr_gem);
1080       return NULL;
1081    }
1082
1083     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
1084
1085     if (ret == 0)
1086         bufmgr_gem->gtt_size = aperture.aper_available_size;
1087     else {
1088         fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n",
1089                 strerror(errno));
1090         bufmgr_gem->gtt_size = 128 * 1024 * 1024;
1091         fprintf(stderr, "Assuming %dkB available aperture size.\n"
1092                 "May lead to reduced performance or incorrect rendering.\n",
1093                 (int)bufmgr_gem->gtt_size / 1024);
1094     }
1095
1096     /* Let's go with one relocation per every 2 dwords (but round down a bit
1097      * since a power of two will mean an extra page allocation for the reloc
1098      * buffer).
1099      *
1100      * Every 4 was too few for the blender benchmark.
1101      */
1102     bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
1103
1104     bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
1105     bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
1106     bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
1107     bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
1108     bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
1109     bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata;
1110     bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata;
1111     bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering;
1112     bufmgr_gem->bufmgr.bo_emit_reloc = dri_gem_bo_emit_reloc;
1113     bufmgr_gem->bufmgr.bo_pin = dri_gem_bo_pin;
1114     bufmgr_gem->bufmgr.bo_unpin = dri_gem_bo_unpin;
1115     bufmgr_gem->bufmgr.bo_get_tiling = dri_gem_bo_get_tiling;
1116     bufmgr_gem->bufmgr.bo_set_tiling = dri_gem_bo_set_tiling;
1117     bufmgr_gem->bufmgr.bo_flink = dri_gem_bo_flink;
1118     bufmgr_gem->bufmgr.bo_exec = dri_gem_bo_exec;
1119     bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
1120     bufmgr_gem->bufmgr.debug = 0;
1121     bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space;
1122     /* Initialize the linked lists for BO reuse cache. */
1123     for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++)
1124         bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
1125
1126     return &bufmgr_gem->bufmgr;
1127 }
1128