intel: Rename dri_ and intel_ symbols to drm_intel_.
[profile/ivi/libdrm.git] / libdrm / intel / intel_bufmgr_gem.c
1 /**************************************************************************
2  *
3  * Copyright © 2007 Red Hat Inc.
4  * Copyright © 2007 Intel Corporation
5  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
6  * All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sub license, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * The above copyright notice and this permission notice (including the
25  * next paragraph) shall be included in all copies or substantial portions
26  * of the Software.
27  *
28  *
29  **************************************************************************/
30 /*
31  * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
32  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com>
33  *          Eric Anholt <eric@anholt.net>
34  *          Dave Airlie <airlied@linux.ie>
35  */
36
37 #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 _drm_intel_bo_gem drm_intel_bo_gem;
64
65 struct drm_intel_gem_bo_bucket {
66    drm_intel_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 DRM_INTEL_GEM_BO_BUCKETS        16
81 typedef struct _drm_intel_bufmgr_gem {
82     drm_intel_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     drm_intel_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 drm_intel_gem_bo_bucket cache_bucket[DRM_INTEL_GEM_BO_BUCKETS];
97
98     uint64_t gtt_size;
99 } drm_intel_bufmgr_gem;
100
101 struct _drm_intel_bo_gem {
102     drm_intel_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     drm_intel_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     drm_intel_bo_gem *next;
139
140     /**
141      * Boolean of whether this BO and its children have been included in
142      * the current drm_intel_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 drm_intel_bufmgr_check_aperture in
157      * the common case.
158      */
159     int reloc_tree_size;
160 };
161
162 static void drm_intel_gem_bo_reference_locked(drm_intel_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 drm_intel_gem_bo_bucket *
179 drm_intel_gem_bo_bucket_for_size(drm_intel_bufmgr_gem *bufmgr_gem,
180                                  unsigned long size)
181 {
182     int i;
183
184     /* We only do buckets in power of two increments */
185     if ((size & (size - 1)) != 0)
186         return NULL;
187
188     /* We should only see sizes rounded to pages. */
189     assert((size % 4096) == 0);
190
191     /* We always allocate in units of pages */
192     i = ffs(size / 4096) - 1;
193     if (i >= DRM_INTEL_GEM_BO_BUCKETS)
194         return NULL;
195
196     return &bufmgr_gem->cache_bucket[i];
197 }
198
199
200 static void drm_intel_gem_dump_validation_list(drm_intel_bufmgr_gem *bufmgr_gem)
201 {
202     int i, j;
203
204     for (i = 0; i < bufmgr_gem->exec_count; i++) {
205         drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
206         drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
207
208         if (bo_gem->relocs == NULL) {
209             DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name);
210             continue;
211         }
212
213         for (j = 0; j < bo_gem->reloc_count; j++) {
214             drm_intel_bo *target_bo = bo_gem->reloc_target_bo[j];
215             drm_intel_bo_gem *target_gem = (drm_intel_bo_gem *)target_bo;
216
217             DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",
218                 i,
219                 bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset,
220                 target_gem->gem_handle, target_gem->name, target_bo->offset,
221                 bo_gem->relocs[j].delta);
222         }
223     }
224 }
225
226 /**
227  * Adds the given buffer to the list of buffers to be validated (moved into the
228  * appropriate memory type) with the next batch submission.
229  *
230  * If a buffer is validated multiple times in a batch submission, it ends up
231  * with the intersection of the memory type flags and the union of the
232  * access flags.
233  */
234 static void
235 drm_intel_add_validate_buffer(drm_intel_bo *bo)
236 {
237     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
238     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
239     int index;
240
241     if (bo_gem->validate_index != -1)
242         return;
243
244     /* Extend the array of validation entries as necessary. */
245     if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
246         int new_size = bufmgr_gem->exec_size * 2;
247
248         if (new_size == 0)
249             new_size = 5;
250
251         bufmgr_gem->exec_objects =
252             realloc(bufmgr_gem->exec_objects,
253                     sizeof(*bufmgr_gem->exec_objects) * new_size);
254         bufmgr_gem->exec_bos =
255             realloc(bufmgr_gem->exec_bos,
256                     sizeof(*bufmgr_gem->exec_bos) * new_size);
257         bufmgr_gem->exec_size = new_size;
258     }
259
260     index = bufmgr_gem->exec_count;
261     bo_gem->validate_index = index;
262     /* Fill in array entry */
263     bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
264     bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
265     bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
266     bufmgr_gem->exec_objects[index].alignment = 0;
267     bufmgr_gem->exec_objects[index].offset = 0;
268     bufmgr_gem->exec_bos[index] = bo;
269     drm_intel_gem_bo_reference_locked(bo);
270     bufmgr_gem->exec_count++;
271 }
272
273
274 #define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
275         sizeof(uint32_t))
276
277 static int
278 drm_intel_setup_reloc_list(drm_intel_bo *bo)
279 {
280     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
281     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
282
283     bo_gem->relocs = malloc(bufmgr_gem->max_relocs *
284                             sizeof(struct drm_i915_gem_relocation_entry));
285     bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs *
286                                      sizeof(drm_intel_bo *));
287
288     return 0;
289 }
290
291 static drm_intel_bo *
292 drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
293                    unsigned long size, unsigned int alignment)
294 {
295     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
296     drm_intel_bo_gem *bo_gem;
297     unsigned int page_size = getpagesize();
298     int ret;
299     struct drm_intel_gem_bo_bucket *bucket;
300     int alloc_from_cache = 0;
301     unsigned long bo_size;
302
303     /* Round the allocated size up to a power of two number of pages. */
304     bo_size = 1 << logbase2(size);
305     if (bo_size < page_size)
306         bo_size = page_size;
307     bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo_size);
308
309     /* If we don't have caching at this size, don't actually round the
310      * allocation up.
311      */
312     if (bucket == NULL || bucket->max_entries == 0) {
313         bo_size = size;
314         if (bo_size < page_size)
315             bo_size = page_size;
316     }
317
318     pthread_mutex_lock(&bufmgr_gem->lock);
319     /* Get a buffer out of the cache if available */
320     if (bucket != NULL && bucket->num_entries > 0) {
321         struct drm_i915_gem_busy busy;
322         
323         bo_gem = bucket->head;
324         busy.handle = bo_gem->gem_handle;
325
326         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
327         alloc_from_cache = (ret == 0 && busy.busy == 0);
328
329         if (alloc_from_cache) {
330             bucket->head = bo_gem->next;
331             if (bo_gem->next == NULL)
332                 bucket->tail = &bucket->head;
333             bucket->num_entries--;
334         }
335     }
336     pthread_mutex_unlock(&bufmgr_gem->lock);
337
338     if (!alloc_from_cache) {
339         struct drm_i915_gem_create create;
340
341         bo_gem = calloc(1, sizeof(*bo_gem));
342         if (!bo_gem)
343             return NULL;
344
345         bo_gem->bo.size = bo_size;
346         memset(&create, 0, sizeof(create));
347         create.size = bo_size;
348
349         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
350         bo_gem->gem_handle = create.handle;
351         if (ret != 0) {
352             free(bo_gem);
353             return NULL;
354         }
355         bo_gem->bo.bufmgr = bufmgr;
356     }
357
358     bo_gem->name = name;
359     bo_gem->refcount = 1;
360     bo_gem->validate_index = -1;
361     bo_gem->reloc_tree_size = bo_gem->bo.size;
362     bo_gem->used_as_reloc_target = 0;
363
364     DBG("bo_create: buf %d (%s) %ldb\n",
365         bo_gem->gem_handle, bo_gem->name, size);
366
367     return &bo_gem->bo;
368 }
369
370 /**
371  * Returns a drm_intel_bo wrapping the given buffer object handle.
372  *
373  * This can be used when one application needs to pass a buffer object
374  * to another.
375  */
376 drm_intel_bo *
377 drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr, const char *name,
378                                   unsigned int handle)
379 {
380     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
381     drm_intel_bo_gem *bo_gem;
382     int ret;
383     struct drm_gem_open open_arg;
384
385     bo_gem = calloc(1, sizeof(*bo_gem));
386     if (!bo_gem)
387         return NULL;
388
389     memset(&open_arg, 0, sizeof(open_arg));
390     open_arg.name = handle;
391     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
392     if (ret != 0) {
393         fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
394                name, handle, strerror(errno));
395         free(bo_gem);
396         return NULL;
397     }
398     bo_gem->bo.size = open_arg.size;
399     bo_gem->bo.offset = 0;
400     bo_gem->bo.virtual = NULL;
401     bo_gem->bo.bufmgr = bufmgr;
402     bo_gem->name = name;
403     bo_gem->refcount = 1;
404     bo_gem->validate_index = -1;
405     bo_gem->gem_handle = open_arg.handle;
406     bo_gem->global_name = handle;
407
408     DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
409
410     return &bo_gem->bo;
411 }
412
413 static void
414 drm_intel_gem_bo_reference(drm_intel_bo *bo)
415 {
416     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
417     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
418
419     pthread_mutex_lock(&bufmgr_gem->lock);
420     bo_gem->refcount++;
421     pthread_mutex_unlock(&bufmgr_gem->lock);
422 }
423
424 static void
425 drm_intel_gem_bo_reference_locked(drm_intel_bo *bo)
426 {
427     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
428
429     bo_gem->refcount++;
430 }
431
432 static void
433 drm_intel_gem_bo_free(drm_intel_bo *bo)
434 {
435     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
436     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
437     struct drm_gem_close close;
438     int ret;
439
440     if (bo_gem->mapped)
441         munmap (bo_gem->virtual, bo_gem->bo.size);
442
443     /* Close this object */
444     close.handle = bo_gem->gem_handle;
445     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
446     if (ret != 0) {
447         fprintf(stderr,
448                 "DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
449                 bo_gem->gem_handle, bo_gem->name, strerror(errno));
450     }
451     free(bo);
452 }
453
454 static void
455 drm_intel_gem_bo_unreference_locked(drm_intel_bo *bo)
456 {
457     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
458     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
459
460     if (--bo_gem->refcount == 0) {
461         struct drm_intel_gem_bo_bucket *bucket;
462
463         if (bo_gem->relocs != NULL) {
464             int i;
465
466             /* Unreference all the target buffers */
467             for (i = 0; i < bo_gem->reloc_count; i++)
468                  drm_intel_gem_bo_unreference_locked(bo_gem->reloc_target_bo[i]);
469             free(bo_gem->reloc_target_bo);
470             free(bo_gem->relocs);
471         }
472
473         DBG("bo_unreference final: %d (%s)\n",
474             bo_gem->gem_handle, bo_gem->name);
475
476         bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
477         /* Put the buffer into our internal cache for reuse if we can. */
478         if (bucket != NULL &&
479             (bucket->max_entries == -1 ||
480              (bucket->max_entries > 0 &&
481               bucket->num_entries < bucket->max_entries)))
482         {
483             bo_gem->name = 0;
484             bo_gem->validate_index = -1;
485             bo_gem->relocs = NULL;
486             bo_gem->reloc_target_bo = NULL;
487             bo_gem->reloc_count = 0;
488
489             bo_gem->next = NULL;
490             *bucket->tail = bo_gem;
491             bucket->tail = &bo_gem->next;
492             bucket->num_entries++;
493         } else {
494             drm_intel_gem_bo_free(bo);
495         }
496     }
497 }
498
499 static void
500 drm_intel_gem_bo_unreference(drm_intel_bo *bo)
501 {
502     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
503
504     pthread_mutex_lock(&bufmgr_gem->lock);
505     drm_intel_gem_bo_unreference_locked(bo);
506     pthread_mutex_unlock(&bufmgr_gem->lock);
507 }
508
509 static int
510 drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
511 {
512     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
513     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
514     struct drm_i915_gem_set_domain set_domain;
515     int ret;
516
517     pthread_mutex_lock(&bufmgr_gem->lock);
518
519     /* Allow recursive mapping. Mesa may recursively map buffers with
520      * nested display loops.
521      */
522     if (!bo_gem->mapped) {
523     
524         assert(bo->virtual == NULL);
525     
526         DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
527     
528         if (bo_gem->virtual == NULL) {
529             struct drm_i915_gem_mmap mmap_arg;
530     
531             memset(&mmap_arg, 0, sizeof(mmap_arg));
532             mmap_arg.handle = bo_gem->gem_handle;
533             mmap_arg.offset = 0;
534             mmap_arg.size = bo->size;
535             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
536             if (ret != 0) {
537                 fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
538                         __FILE__, __LINE__,
539                         bo_gem->gem_handle, bo_gem->name, strerror(errno));
540             }
541             bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
542         }
543         bo->virtual = bo_gem->virtual;
544         bo_gem->swrast = 0;
545         bo_gem->mapped = 1;
546         DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
547     }
548
549     if (!bo_gem->swrast) {
550         set_domain.handle = bo_gem->gem_handle;
551         set_domain.read_domains = I915_GEM_DOMAIN_CPU;
552         if (write_enable)
553             set_domain.write_domain = I915_GEM_DOMAIN_CPU;
554         else
555             set_domain.write_domain = 0;
556         do {
557             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN,
558                         &set_domain);
559         } while (ret == -1 && errno == EINTR);
560         if (ret != 0) {
561             fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n",
562                      __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno));
563         }
564         bo_gem->swrast = 1;
565     }
566
567     pthread_mutex_unlock(&bufmgr_gem->lock);
568
569     return 0;
570 }
571
572 static int
573 drm_intel_gem_bo_unmap(drm_intel_bo *bo)
574 {
575     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
576     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
577     struct drm_i915_gem_sw_finish sw_finish;
578     int ret;
579
580     if (bo == NULL)
581         return 0;
582
583     assert(bo_gem->mapped);
584
585     pthread_mutex_lock(&bufmgr_gem->lock);
586     if (bo_gem->swrast) {
587         sw_finish.handle = bo_gem->gem_handle;
588         do {
589             ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SW_FINISH,
590                         &sw_finish);
591         } while (ret == -1 && errno == EINTR);
592         bo_gem->swrast = 0;
593     }
594     pthread_mutex_unlock(&bufmgr_gem->lock);
595     return 0;
596 }
597
598 static int
599 drm_intel_gem_bo_subdata (drm_intel_bo *bo, unsigned long offset,
600                           unsigned long size, const void *data)
601 {
602     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
603     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
604     struct drm_i915_gem_pwrite pwrite;
605     int ret;
606
607     memset (&pwrite, 0, sizeof (pwrite));
608     pwrite.handle = bo_gem->gem_handle;
609     pwrite.offset = offset;
610     pwrite.size = size;
611     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
612     do {
613         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
614     } while (ret == -1 && errno == EINTR);
615     if (ret != 0) {
616         fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
617                  __FILE__, __LINE__,
618                  bo_gem->gem_handle, (int) offset, (int) size,
619                  strerror (errno));
620     }
621     return 0;
622 }
623
624 static int
625 drm_intel_gem_bo_get_subdata (drm_intel_bo *bo, unsigned long offset,
626                               unsigned long size, void *data)
627 {
628     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
629     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
630     struct drm_i915_gem_pread pread;
631     int ret;
632
633     memset (&pread, 0, sizeof (pread));
634     pread.handle = bo_gem->gem_handle;
635     pread.offset = offset;
636     pread.size = size;
637     pread.data_ptr = (uint64_t) (uintptr_t) data;
638     do {
639         ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
640     } while (ret == -1 && errno == EINTR);
641     if (ret != 0) {
642         fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
643                  __FILE__, __LINE__,
644                  bo_gem->gem_handle, (int) offset, (int) size,
645                  strerror (errno));
646     }
647     return 0;
648 }
649
650 static void
651 drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
652 {
653     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
654     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
655     struct drm_i915_gem_set_domain set_domain;
656     int ret;
657
658     set_domain.handle = bo_gem->gem_handle;
659     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
660     set_domain.write_domain = 0;
661     ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
662     if (ret != 0) {
663         fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
664                  __FILE__, __LINE__,
665                  bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
666                  strerror (errno));
667     }
668 }
669
670 static void
671 drm_intel_bufmgr_gem_destroy(drm_intel_bufmgr *bufmgr)
672 {
673     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
674     int i;
675
676     free(bufmgr_gem->exec_objects);
677     free(bufmgr_gem->exec_bos);
678
679     pthread_mutex_destroy(&bufmgr_gem->lock);
680
681     /* Free any cached buffer objects we were going to reuse */
682     for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++) {
683         struct drm_intel_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
684         drm_intel_bo_gem *bo_gem;
685
686         while ((bo_gem = bucket->head) != NULL) {
687             bucket->head = bo_gem->next;
688             if (bo_gem->next == NULL)
689                 bucket->tail = &bucket->head;
690             bucket->num_entries--;
691
692             drm_intel_gem_bo_free(&bo_gem->bo);
693         }
694     }
695
696     free(bufmgr);
697 }
698
699 /**
700  * Adds the target buffer to the validation list and adds the relocation
701  * to the reloc_buffer's relocation list.
702  *
703  * The relocation entry at the given offset must already contain the
704  * precomputed relocation value, because the kernel will optimize out
705  * the relocation entry write when the buffer hasn't moved from the
706  * last known offset in target_bo.
707  */
708 static int
709 drm_intel_gem_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
710                             drm_intel_bo *target_bo, uint32_t target_offset,
711                             uint32_t read_domains, uint32_t write_domain)
712 {
713     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
714     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
715     drm_intel_bo_gem *target_bo_gem = (drm_intel_bo_gem *)target_bo;
716
717     pthread_mutex_lock(&bufmgr_gem->lock);
718
719     /* Create a new relocation list if needed */
720     if (bo_gem->relocs == NULL)
721         drm_intel_setup_reloc_list(bo);
722
723     /* Check overflow */
724     assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
725
726     /* Check args */
727     assert (offset <= bo->size - 4);
728     assert ((write_domain & (write_domain-1)) == 0);
729
730     /* Make sure that we're not adding a reloc to something whose size has
731      * already been accounted for.
732      */
733     assert(!bo_gem->used_as_reloc_target);
734     bo_gem->reloc_tree_size += target_bo_gem->reloc_tree_size;
735
736     /* Flag the target to disallow further relocations in it. */
737     target_bo_gem->used_as_reloc_target = 1;
738
739     bo_gem->relocs[bo_gem->reloc_count].offset = offset;
740     bo_gem->relocs[bo_gem->reloc_count].delta = target_offset;
741     bo_gem->relocs[bo_gem->reloc_count].target_handle =
742         target_bo_gem->gem_handle;
743     bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
744     bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
745     bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
746
747     bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
748     drm_intel_gem_bo_reference_locked(target_bo);
749
750     bo_gem->reloc_count++;
751
752     pthread_mutex_unlock(&bufmgr_gem->lock);
753
754     return 0;
755 }
756
757 /**
758  * Walk the tree of relocations rooted at BO and accumulate the list of
759  * validations to be performed and update the relocation buffers with
760  * index values into the validation list.
761  */
762 static void
763 drm_intel_gem_bo_process_reloc(drm_intel_bo *bo)
764 {
765     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
766     int i;
767
768     if (bo_gem->relocs == NULL)
769         return;
770
771     for (i = 0; i < bo_gem->reloc_count; i++) {
772         drm_intel_bo *target_bo = bo_gem->reloc_target_bo[i];
773
774         /* Continue walking the tree depth-first. */
775         drm_intel_gem_bo_process_reloc(target_bo);
776
777         /* Add the target to the validate list */
778         drm_intel_add_validate_buffer(target_bo);
779     }
780 }
781
782 static void
783 drm_intel_update_buffer_offsets (drm_intel_bufmgr_gem *bufmgr_gem)
784 {
785     int i;
786
787     for (i = 0; i < bufmgr_gem->exec_count; i++) {
788         drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
789         drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
790
791         /* Update the buffer offset */
792         if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
793             DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
794                 bo_gem->gem_handle, bo_gem->name, bo->offset,
795                 bufmgr_gem->exec_objects[i].offset);
796             bo->offset = bufmgr_gem->exec_objects[i].offset;
797         }
798     }
799 }
800
801 static int
802 drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
803                       drm_clip_rect_t *cliprects, int num_cliprects,
804                       int DR4)
805 {
806     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
807     struct drm_i915_gem_execbuffer execbuf;
808     int ret, i;
809
810     pthread_mutex_lock(&bufmgr_gem->lock);
811     /* Update indices and set up the validate list. */
812     drm_intel_gem_bo_process_reloc(bo);
813
814     /* Add the batch buffer to the validation list.  There are no relocations
815      * pointing to it.
816      */
817     drm_intel_add_validate_buffer(bo);
818
819     execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
820     execbuf.buffer_count = bufmgr_gem->exec_count;
821     execbuf.batch_start_offset = 0;
822     execbuf.batch_len = used;
823     execbuf.cliprects_ptr = (uintptr_t)cliprects;
824     execbuf.num_cliprects = num_cliprects;
825     execbuf.DR1 = 0;
826     execbuf.DR4 = DR4;
827
828     do {
829         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER, &execbuf);
830     } while (ret != 0 && errno == EAGAIN);
831
832     drm_intel_update_buffer_offsets (bufmgr_gem);
833
834     if (bufmgr_gem->bufmgr.debug)
835         drm_intel_gem_dump_validation_list(bufmgr_gem);
836
837     for (i = 0; i < bufmgr_gem->exec_count; i++) {
838         drm_intel_bo *bo = bufmgr_gem->exec_bos[i];
839         drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
840
841         /* Need to call swrast on next bo_map */
842         bo_gem->swrast = 0;
843
844         /* Disconnect the buffer from the validate list */
845         bo_gem->validate_index = -1;
846         drm_intel_gem_bo_unreference_locked(bo);
847         bufmgr_gem->exec_bos[i] = NULL;
848     }
849     bufmgr_gem->exec_count = 0;
850     pthread_mutex_unlock(&bufmgr_gem->lock);
851
852     return 0;
853 }
854
855 static int
856 drm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
857 {
858     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
859     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
860     struct drm_i915_gem_pin pin;
861     int ret;
862
863     pin.handle = bo_gem->gem_handle;
864     pin.alignment = alignment;
865
866     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_PIN, &pin);
867     if (ret != 0)
868         return -errno;
869
870     bo->offset = pin.offset;
871     return 0;
872 }
873
874 static int
875 drm_intel_gem_bo_unpin(drm_intel_bo *bo)
876 {
877     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
878     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
879     struct drm_i915_gem_unpin unpin;
880     int ret;
881
882     unpin.handle = bo_gem->gem_handle;
883
884     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
885     if (ret != 0)
886         return -errno;
887
888     return 0;
889 }
890
891 static int
892 drm_intel_gem_bo_set_tiling(drm_intel_bo *bo, uint32_t *tiling_mode,
893                             uint32_t stride)
894 {
895     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
896     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
897     struct drm_i915_gem_set_tiling set_tiling;
898     int ret;
899
900     set_tiling.handle = bo_gem->gem_handle;
901     set_tiling.tiling_mode = *tiling_mode;
902     set_tiling.stride = stride;
903
904     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
905     if (ret != 0) {
906         *tiling_mode = I915_TILING_NONE;
907         return -errno;
908     }
909
910     *tiling_mode = set_tiling.tiling_mode;
911     return 0;
912 }
913
914 static int
915 drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t *tiling_mode,
916                             uint32_t *swizzle_mode)
917 {
918     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
919     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
920     struct drm_i915_gem_get_tiling get_tiling;
921     int ret;
922
923     get_tiling.handle = bo_gem->gem_handle;
924
925     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
926     if (ret != 0) {
927         *tiling_mode = I915_TILING_NONE;
928         *swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
929         return -errno;
930     }
931
932     *tiling_mode = get_tiling.tiling_mode;
933     *swizzle_mode = get_tiling.swizzle_mode;
934     return 0;
935 }
936
937 static int
938 drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t *name)
939 {
940     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
941     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
942     struct drm_gem_flink flink;
943     int ret;
944
945     if (!bo_gem->global_name) {
946         flink.handle = bo_gem->gem_handle;
947     
948         ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
949         if (ret != 0)
950             return -errno;
951         bo_gem->global_name = flink.name;
952     }
953     
954     *name = bo_gem->global_name;
955     return 0;
956 }
957
958 /**
959  * Enables unlimited caching of buffer objects for reuse.
960  *
961  * This is potentially very memory expensive, as the cache at each bucket
962  * size is only bounded by how many buffers of that size we've managed to have
963  * in flight at once.
964  */
965 void
966 drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr)
967 {
968     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
969     int i;
970
971     for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++) {
972         bufmgr_gem->cache_bucket[i].max_entries = -1;
973     }
974 }
975
976 /**
977  * Return the additional aperture space required by the tree of buffer objects
978  * rooted at bo.
979  */
980 static int
981 drm_intel_gem_bo_get_aperture_space(drm_intel_bo *bo)
982 {
983     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
984     int i;
985     int total = 0;
986
987     if (bo == NULL || bo_gem->included_in_check_aperture)
988         return 0;
989
990     total += bo->size;
991     bo_gem->included_in_check_aperture = 1;
992
993     for (i = 0; i < bo_gem->reloc_count; i++)
994         total += drm_intel_gem_bo_get_aperture_space(bo_gem->reloc_target_bo[i]);
995
996     return total;
997 }
998
999 /**
1000  * Clear the flag set by drm_intel_gem_bo_get_aperture_space() so we're ready
1001  * for the next drm_intel_bufmgr_check_aperture_space() call.
1002  */
1003 static void
1004 drm_intel_gem_bo_clear_aperture_space_flag(drm_intel_bo *bo)
1005 {
1006     drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
1007     int i;
1008
1009     if (bo == NULL || !bo_gem->included_in_check_aperture)
1010         return;
1011
1012     bo_gem->included_in_check_aperture = 0;
1013
1014     for (i = 0; i < bo_gem->reloc_count; i++)
1015         drm_intel_gem_bo_clear_aperture_space_flag(bo_gem->reloc_target_bo[i]);
1016 }
1017
1018 /**
1019  * Return -1 if the batchbuffer should be flushed before attempting to
1020  * emit rendering referencing the buffers pointed to by bo_array.
1021  *
1022  * This is required because if we try to emit a batchbuffer with relocations
1023  * to a tree of buffers that won't simultaneously fit in the aperture,
1024  * the rendering will return an error at a point where the software is not
1025  * prepared to recover from it.
1026  *
1027  * However, we also want to emit the batchbuffer significantly before we reach
1028  * the limit, as a series of batchbuffers each of which references buffers
1029  * covering almost all of the aperture means that at each emit we end up
1030  * waiting to evict a buffer from the last rendering, and we get synchronous
1031  * performance.  By emitting smaller batchbuffers, we eat some CPU overhead to
1032  * get better parallelism.
1033  */
1034 static int
1035 drm_intel_gem_check_aperture_space(drm_intel_bo **bo_array, int count)
1036 {
1037     drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo_array[0]->bufmgr;
1038     unsigned int total = 0;
1039     unsigned int threshold = bufmgr_gem->gtt_size * 3 / 4;
1040     int i;
1041
1042     for (i = 0; i < count; i++) {
1043         drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo_array[i];
1044         if (bo_gem != NULL)
1045                 total += bo_gem->reloc_tree_size;
1046     }
1047
1048     if (total > threshold) {
1049         total = 0;
1050         for (i = 0; i < count; i++)
1051             total += drm_intel_gem_bo_get_aperture_space(bo_array[i]);
1052
1053         for (i = 0; i < count; i++)
1054             drm_intel_gem_bo_clear_aperture_space_flag(bo_array[i]);
1055     }
1056
1057     if (total > bufmgr_gem->gtt_size * 3 / 4) {
1058         DBG("check_space: overflowed available aperture, %dkb vs %dkb\n",
1059             total / 1024, (int)bufmgr_gem->gtt_size / 1024);
1060         return -1;
1061     } else {
1062         DBG("drm_check_space: total %dkb vs bufgr %dkb\n", total / 1024 ,
1063             (int)bufmgr_gem->gtt_size / 1024);
1064         return 0;
1065     }
1066 }
1067
1068 /**
1069  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
1070  * and manage map buffer objections.
1071  *
1072  * \param fd File descriptor of the opened DRM device.
1073  */
1074 drm_intel_bufmgr *
1075 drm_intel_bufmgr_gem_init(int fd, int batch_size)
1076 {
1077     drm_intel_bufmgr_gem *bufmgr_gem;
1078     struct drm_i915_gem_get_aperture aperture;
1079     int ret, i;
1080
1081     bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
1082     bufmgr_gem->fd = fd;
1083
1084     if (pthread_mutex_init(&bufmgr_gem->lock, NULL) != 0) {
1085       free(bufmgr_gem);
1086       return NULL;
1087    }
1088
1089     ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
1090
1091     if (ret == 0)
1092         bufmgr_gem->gtt_size = aperture.aper_available_size;
1093     else {
1094         fprintf(stderr, "DRM_IOCTL_I915_GEM_APERTURE failed: %s\n",
1095                 strerror(errno));
1096         bufmgr_gem->gtt_size = 128 * 1024 * 1024;
1097         fprintf(stderr, "Assuming %dkB available aperture size.\n"
1098                 "May lead to reduced performance or incorrect rendering.\n",
1099                 (int)bufmgr_gem->gtt_size / 1024);
1100     }
1101
1102     /* Let's go with one relocation per every 2 dwords (but round down a bit
1103      * since a power of two will mean an extra page allocation for the reloc
1104      * buffer).
1105      *
1106      * Every 4 was too few for the blender benchmark.
1107      */
1108     bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
1109
1110     bufmgr_gem->bufmgr.bo_alloc = drm_intel_gem_bo_alloc;
1111     bufmgr_gem->bufmgr.bo_reference = drm_intel_gem_bo_reference;
1112     bufmgr_gem->bufmgr.bo_unreference = drm_intel_gem_bo_unreference;
1113     bufmgr_gem->bufmgr.bo_map = drm_intel_gem_bo_map;
1114     bufmgr_gem->bufmgr.bo_unmap = drm_intel_gem_bo_unmap;
1115     bufmgr_gem->bufmgr.bo_subdata = drm_intel_gem_bo_subdata;
1116     bufmgr_gem->bufmgr.bo_get_subdata = drm_intel_gem_bo_get_subdata;
1117     bufmgr_gem->bufmgr.bo_wait_rendering = drm_intel_gem_bo_wait_rendering;
1118     bufmgr_gem->bufmgr.bo_emit_reloc = drm_intel_gem_bo_emit_reloc;
1119     bufmgr_gem->bufmgr.bo_pin = drm_intel_gem_bo_pin;
1120     bufmgr_gem->bufmgr.bo_unpin = drm_intel_gem_bo_unpin;
1121     bufmgr_gem->bufmgr.bo_get_tiling = drm_intel_gem_bo_get_tiling;
1122     bufmgr_gem->bufmgr.bo_set_tiling = drm_intel_gem_bo_set_tiling;
1123     bufmgr_gem->bufmgr.bo_flink = drm_intel_gem_bo_flink;
1124     bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec;
1125     bufmgr_gem->bufmgr.destroy = drm_intel_bufmgr_gem_destroy;
1126     bufmgr_gem->bufmgr.debug = 0;
1127     bufmgr_gem->bufmgr.check_aperture_space = drm_intel_gem_check_aperture_space;
1128     /* Initialize the linked lists for BO reuse cache. */
1129     for (i = 0; i < DRM_INTEL_GEM_BO_BUCKETS; i++)
1130         bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
1131
1132     return &bufmgr_gem->bufmgr;
1133 }
1134