Tizen 2.0 Release
[framework/graphics/cairo.git] / src / drm / cairo-drm-intel.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Chris Wilson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it either under the terms of the GNU Lesser General Public
7  * License version 2.1 as published by the Free Software Foundation
8  * (the "LGPL") or, at your option, under the terms of the Mozilla
9  * Public License Version 1.1 (the "MPL"). If you do not alter this
10  * notice, a recipient may use your version of this file under either
11  * the MPL or the LGPL.
12  *
13  * You should have received a copy of the LGPL along with this library
14  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
19  * The contents of this file are subject to the Mozilla Public License
20  * Version 1.1 (the "License"); you may not use this file except in
21  * compliance with the License. You may obtain a copy of the License at
22  * http://www.mozilla.org/MPL/
23  *
24  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26  * the specific language governing rights and limitations.
27  *
28  */
29
30 #include "cairoint.h"
31
32 #include "cairo-drm-private.h"
33 #include "cairo-drm-ioctl-private.h"
34 #include "cairo-drm-intel-private.h"
35 #include "cairo-drm-intel-ioctl-private.h"
36
37 #include "cairo-error-private.h"
38 #include "cairo-freelist-private.h"
39
40 #include <sys/ioctl.h>
41 #include <sys/mman.h>
42 #include <errno.h>
43
44 #define GLYPH_CACHE_WIDTH 1024
45 #define GLYPH_CACHE_HEIGHT 1024
46 #define GLYPH_CACHE_MIN_SIZE 1
47 #define GLYPH_CACHE_MAX_SIZE 128
48
49 #define IMAGE_CACHE_WIDTH 1024
50 #define IMAGE_CACHE_HEIGHT 1024
51
52 int
53 intel_get (int fd, int param)
54 {
55     struct intel_getparam gp;
56     int value;
57
58     gp.param = param;
59     gp.value = &value;
60     if (ioctl (fd, DRM_IOCTL_I915_GETPARAM, &gp) < 0)
61         return 0;
62
63     VG (VALGRIND_MAKE_MEM_DEFINED (&value, sizeof (value)));
64
65     return value;
66 }
67
68 cairo_bool_t
69 intel_info (int fd, uint64_t *gtt_size)
70 {
71     struct drm_i915_gem_get_aperture info;
72
73     if (! intel_get (fd, I915_PARAM_HAS_GEM))
74         return FALSE;
75
76     if (! intel_get (fd, I915_PARAM_HAS_EXECBUF2))
77         return FALSE;
78
79     if (ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &info) < 0)
80         return FALSE;
81
82     VG (VALGRIND_MAKE_MEM_DEFINED (&info, sizeof (info)));
83
84     if (gtt_size != NULL)
85         *gtt_size = info.aper_size;
86
87     return TRUE;
88 }
89
90 void
91 intel_bo_write (const intel_device_t *device,
92                 intel_bo_t *bo,
93                 unsigned long offset,
94                 unsigned long size,
95                 const void *data)
96 {
97     struct drm_i915_gem_pwrite pwrite;
98     int ret;
99
100     assert (bo->tiling == I915_TILING_NONE);
101     assert (size);
102     assert (offset < bo->base.size);
103     assert (size+offset <= bo->base.size);
104
105     intel_bo_set_tiling (device, bo);
106
107     assert (bo->_tiling == I915_TILING_NONE);
108
109     memset (&pwrite, 0, sizeof (pwrite));
110     pwrite.handle = bo->base.handle;
111     pwrite.offset = offset;
112     pwrite.size = size;
113     pwrite.data_ptr = (uint64_t) (uintptr_t) data;
114     do {
115         ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
116     } while (ret == -1 && errno == EINTR);
117     assert (ret == 0);
118
119     bo->busy = FALSE;
120 }
121
122 void
123 intel_bo_read (const intel_device_t *device,
124                intel_bo_t *bo,
125                unsigned long offset,
126                unsigned long size,
127                void *data)
128 {
129     struct drm_i915_gem_pread pread;
130     int ret;
131
132     assert (bo->tiling == I915_TILING_NONE);
133     assert (size);
134     assert (offset < bo->base.size);
135     assert (size+offset <= bo->base.size);
136
137     intel_bo_set_tiling (device, bo);
138
139     assert (bo->_tiling == I915_TILING_NONE);
140
141     memset (&pread, 0, sizeof (pread));
142     pread.handle = bo->base.handle;
143     pread.offset = offset;
144     pread.size = size;
145     pread.data_ptr = (uint64_t) (uintptr_t) data;
146     do {
147         ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
148     } while (ret == -1 && errno == EINTR);
149     assert (ret == 0);
150
151     bo->cpu = TRUE;
152     bo->busy = FALSE;
153 }
154
155 void *
156 intel_bo_map (const intel_device_t *device, intel_bo_t *bo)
157 {
158     struct drm_i915_gem_set_domain set_domain;
159     uint32_t domain;
160     int ret;
161
162     intel_bo_set_tiling (device, bo);
163
164     if (bo->virtual != NULL)
165         return bo->virtual;
166
167     if (bo->cpu && bo->tiling == I915_TILING_NONE) {
168         struct drm_i915_gem_mmap mmap_arg;
169
170         mmap_arg.handle = bo->base.handle;
171         mmap_arg.offset = 0;
172         mmap_arg.size = bo->base.size;
173         mmap_arg.addr_ptr = 0;
174
175         do {
176             ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
177         } while (ret == -1 && errno == EINTR);
178         if (unlikely (ret != 0)) {
179             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
180             return NULL;
181         }
182
183         bo->virtual = (void *) (uintptr_t) mmap_arg.addr_ptr;
184         domain = I915_GEM_DOMAIN_CPU;
185     } else {
186         struct drm_i915_gem_mmap_gtt mmap_arg;
187         void *ptr;
188
189         /* Get the fake offset back... */
190         mmap_arg.handle = bo->base.handle;
191         do {
192             ret = ioctl (device->base.fd,
193                          DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
194         } while (ret == -1 && errno == EINTR);
195         if (unlikely (ret != 0)) {
196             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
197             return NULL;
198         }
199
200         /* and mmap it */
201         ptr = mmap (0, bo->base.size, PROT_READ | PROT_WRITE,
202                     MAP_SHARED, device->base.fd,
203                     mmap_arg.offset);
204         if (unlikely (ptr == MAP_FAILED)) {
205             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
206             return NULL;
207         }
208
209         bo->virtual = ptr;
210         domain = I915_GEM_DOMAIN_GTT;
211     }
212
213     VG (VALGRIND_MAKE_MEM_DEFINED (bo->virtual, bo->base.size));
214
215     set_domain.handle = bo->base.handle;
216     set_domain.read_domains = domain;
217     set_domain.write_domain = domain;
218
219     do {
220         ret = ioctl (device->base.fd,
221                      DRM_IOCTL_I915_GEM_SET_DOMAIN,
222                      &set_domain);
223     } while (ret == -1 && errno == EINTR);
224
225     if (ret != 0) {
226         intel_bo_unmap (bo);
227         _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR);
228         return NULL;
229     }
230
231     bo->busy = FALSE;
232     return bo->virtual;
233 }
234
235 void
236 intel_bo_unmap (intel_bo_t *bo)
237 {
238     munmap (bo->virtual, bo->base.size);
239     bo->virtual = NULL;
240 }
241
242 cairo_bool_t
243 intel_bo_is_inactive (const intel_device_t *device, intel_bo_t *bo)
244 {
245     struct drm_i915_gem_busy busy;
246
247     if (! bo->busy)
248         return TRUE;
249
250     /* Is this buffer busy for our intended usage pattern? */
251     busy.handle = bo->base.handle;
252     busy.busy = 1;
253     ioctl (device->base.fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
254
255     bo->busy = busy.busy;
256     return ! busy.busy;
257 }
258
259 cairo_bool_t
260 intel_bo_wait (const intel_device_t *device, const intel_bo_t *bo)
261 {
262     struct drm_i915_gem_set_domain set_domain;
263     int ret;
264
265     set_domain.handle = bo->base.handle;
266     set_domain.read_domains = I915_GEM_DOMAIN_GTT;
267     set_domain.write_domain = 0;
268
269     do {
270         ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
271     } while (ret == -1 && errno == EINTR);
272
273     return ret == 0;
274 }
275
276 static inline int
277 pot (int v)
278 {
279     v--;
280     v |= v >> 1;
281     v |= v >> 2;
282     v |= v >> 4;
283     v |= v >> 8;
284     v |= v >> 16;
285     v++;
286     return v;
287 }
288
289 cairo_bool_t
290 intel_bo_madvise (intel_device_t *device,
291                   intel_bo_t *bo,
292                   int advice)
293 {
294     struct drm_i915_gem_madvise madv;
295
296     madv.handle = bo->base.handle;
297     madv.madv = advice;
298     madv.retained = TRUE;
299     ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
300     return madv.retained;
301 }
302
303 static void
304 intel_bo_set_real_size (intel_device_t *device,
305                         intel_bo_t *bo,
306                         size_t size)
307 {
308     struct drm_i915_gem_real_size arg;
309     int ret;
310
311     return;
312
313     if (size == bo->base.size)
314         return;
315
316     arg.handle = bo->base.handle;
317     arg.size = size;
318     do {
319         ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_REAL_SIZE, &arg);
320     } while (ret == -1 && errno == EINTR);
321
322     if (ret == 0) {
323         if (size > bo->base.size) {
324             assert (bo->exec == NULL);
325             bo->cpu = TRUE;
326             bo->busy = FALSE;
327         }
328
329         bo->base.size = size;
330     }
331 }
332
333 intel_bo_t *
334 intel_bo_create (intel_device_t *device,
335                  uint32_t max_size,
336                  uint32_t real_size,
337                  cairo_bool_t gpu_target,
338                  uint32_t tiling,
339                  uint32_t stride)
340 {
341     intel_bo_t *bo;
342     uint32_t cache_size;
343     struct drm_i915_gem_create create;
344     int bucket;
345     int ret;
346
347     max_size = (max_size + 4095) & -4096;
348     real_size = (real_size + 4095) & -4096;
349     cache_size = pot (max_size);
350     bucket = ffs (cache_size / 4096) - 1;
351     if (bucket >= INTEL_BO_CACHE_BUCKETS)
352         cache_size = max_size;
353
354     if (gpu_target) {
355         intel_bo_t *first = NULL;
356
357         cairo_list_foreach_entry (bo, intel_bo_t,
358                                   &device->bo_in_flight,
359                                   cache_list)
360         {
361             assert (bo->exec != NULL);
362             if (tiling && bo->_tiling &&
363                 (bo->_tiling != tiling || bo->_stride != stride))
364             {
365                 continue;
366             }
367
368             if (real_size <= bo->base.size) {
369                 if (real_size >= bo->base.size/2) {
370                     cairo_list_del (&bo->cache_list);
371                     bo = intel_bo_reference (bo);
372                     goto DONE;
373                 }
374
375                 if (first == NULL)
376                     first = bo;
377             }
378         }
379
380         if (first != NULL) {
381             cairo_list_del (&first->cache_list);
382             bo = intel_bo_reference (first);
383             goto DONE;
384         }
385     }
386
387     /* no cached buffer available, allocate fresh */
388     bo = _cairo_freepool_alloc (&device->bo_pool);
389     if (unlikely (bo == NULL)) {
390         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
391         return bo;
392     }
393
394     cairo_list_init (&bo->cache_list);
395
396     bo->base.name = 0;
397
398     bo->offset = 0;
399     bo->virtual = NULL;
400     bo->cpu = TRUE;
401
402     bo->_tiling = I915_TILING_NONE;
403     bo->_stride = 0;
404     bo->purgeable = 0;
405     bo->busy = FALSE;
406
407     bo->opaque0 = 0;
408     bo->opaque1 = 0;
409
410     bo->exec = NULL;
411     bo->batch_read_domains = 0;
412     bo->batch_write_domain = 0;
413     cairo_list_init (&bo->link);
414
415     create.size = cache_size;
416     create.handle = 0;
417     ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_CREATE, &create);
418     if (unlikely (ret != 0)) {
419         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
420         _cairo_freepool_free (&device->bo_pool, bo);
421         return NULL;
422     }
423
424     bo->base.handle = create.handle;
425     bo->full_size = bo->base.size = create.size;
426
427     intel_bo_set_real_size (device, bo, real_size);
428     CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1);
429 DONE:
430     bo->tiling = tiling;
431     bo->stride = stride;
432     return bo;
433 }
434
435 intel_bo_t *
436 intel_bo_create_for_name (intel_device_t *device, uint32_t name)
437 {
438     struct drm_i915_gem_get_tiling get_tiling;
439     cairo_status_t status;
440     intel_bo_t *bo;
441     int ret;
442
443     bo = _cairo_freepool_alloc (&device->bo_pool);
444     if (unlikely (bo == NULL)) {
445         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
446         return NULL;
447     }
448
449     status = _cairo_drm_bo_open_for_name (&device->base, &bo->base, name);
450     if (unlikely (status))
451         goto FAIL;
452
453     CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1);
454     cairo_list_init (&bo->cache_list);
455
456     bo->full_size = bo->base.size;
457     bo->offset = 0;
458     bo->virtual = NULL;
459     bo->purgeable = 0;
460     bo->busy = TRUE;
461     bo->cpu = FALSE;
462
463     bo->opaque0 = 0;
464     bo->opaque1 = 0;
465
466     bo->exec = NULL;
467     bo->batch_read_domains = 0;
468     bo->batch_write_domain = 0;
469     cairo_list_init (&bo->link);
470
471     memset (&get_tiling, 0, sizeof (get_tiling));
472     get_tiling.handle = bo->base.handle;
473
474     ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
475     if (unlikely (ret != 0)) {
476         _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR);
477         _cairo_drm_bo_close (&device->base, &bo->base);
478         goto FAIL;
479     }
480
481     bo->_tiling = bo->tiling = get_tiling.tiling_mode;
482     // bo->stride = get_tiling.stride; /* XXX not available from get_tiling */
483
484     return bo;
485
486 FAIL:
487     _cairo_freepool_free (&device->bo_pool, bo);
488     return NULL;
489 }
490
491 static void
492 intel_bo_release (void *_dev, void *_bo)
493 {
494     intel_device_t *device = _dev;
495     intel_bo_t *bo = _bo;
496
497     if (bo->virtual != NULL)
498         intel_bo_unmap (bo);
499
500     assert (bo->exec == NULL);
501     assert (cairo_list_is_empty (&bo->cache_list));
502
503     _cairo_drm_bo_close (&device->base, &bo->base);
504     _cairo_freepool_free (&device->bo_pool, bo);
505 }
506
507 void
508 intel_bo_set_tiling (const intel_device_t *device,
509                      intel_bo_t *bo)
510 {
511     struct drm_i915_gem_set_tiling set_tiling;
512     int ret;
513
514     if (bo->tiling == bo->_tiling &&
515         (bo->tiling == I915_TILING_NONE || bo->stride == bo->_stride))
516         return;
517
518     do {
519         set_tiling.handle = bo->base.handle;
520         set_tiling.tiling_mode = bo->tiling;
521         set_tiling.stride = bo->stride;
522
523         ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
524     } while (ret == -1 && errno == EINTR);
525
526     assert (ret == 0);
527     bo->_tiling = bo->tiling;
528     bo->_stride = bo->stride;
529 }
530
531 cairo_surface_t *
532 intel_bo_get_image (const intel_device_t *device,
533                     intel_bo_t *bo,
534                     const cairo_drm_surface_t *surface)
535 {
536     cairo_image_surface_t *image;
537     uint8_t *dst;
538     int size, row;
539
540     image = (cairo_image_surface_t *)
541         cairo_image_surface_create (surface->format,
542                                     surface->width,
543                                     surface->height);
544     if (unlikely (image->base.status))
545         return &image->base;
546
547     intel_bo_set_tiling (device, bo);
548
549     if (bo->tiling == I915_TILING_NONE && image->stride == surface->stride) {
550         size = surface->stride * surface->height;
551         intel_bo_read (device, bo, 0, size, image->data);
552     } else {
553         const uint8_t *src;
554
555         src = intel_bo_map (device, bo);
556         if (unlikely (src == NULL))
557             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
558
559         size = surface->width;
560         if (surface->format != CAIRO_FORMAT_A8)
561             size *= 4;
562
563         row = surface->height;
564         dst = image->data;
565         while (row--) {
566             memcpy (dst, src, size);
567             dst += image->stride;
568             src += surface->stride;
569         }
570     }
571
572     return &image->base;
573 }
574
575 static cairo_status_t
576 _intel_bo_put_a1_image (intel_device_t *device,
577                         intel_bo_t *bo,
578                         cairo_image_surface_t *src,
579                         int src_x, int src_y,
580                         int width, int height,
581                         int dst_x, int dst_y)
582 {
583     uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
584     uint8_t *a8 = buf;
585     uint8_t *data;
586     int x;
587
588     data = src->data + src_y * src->stride;
589
590     if (bo->tiling == I915_TILING_NONE && width == bo->stride) {
591         uint8_t *p;
592         int size;
593
594         size = bo->stride * height;
595         if (size > (int) sizeof (buf)) {
596             a8 = _cairo_malloc_ab (bo->stride, height);
597             if (a8 == NULL)
598                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
599         }
600
601         p = a8;
602         while (height--) {
603             for (x = 0; x < width; x++) {
604                 int i = src_x + x;
605                 int byte = i / 8;
606                 int bit = i % 8;
607                 p[x] = data[byte] & (1 << bit) ? 0xff : 0x00;
608             }
609
610             data += src->stride;
611             p += bo->stride;
612         }
613
614         intel_bo_write (device, bo,
615                         dst_y * bo->stride + dst_x, /* XXX  bo_offset */
616                         size, a8);
617     } else {
618         uint8_t *dst;
619
620         if (width > (int) sizeof (buf)) {
621             a8 = malloc (width);
622             if (a8 == NULL)
623                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
624         }
625
626         dst = intel_bo_map (device, bo);
627         if (dst == NULL) {
628             if (a8 != buf)
629                 free (a8);
630             return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
631         }
632
633         dst += dst_y * bo->stride + dst_x; /* XXX  bo_offset */
634         while (height--) {
635             for (x = 0; x < width; x++) {
636                 int i = src_x + x;
637                 int byte = i / 8;
638                 int bit = i % 8;
639                 a8[x] = data[byte] & (1 << bit) ? 0xff : 0x00;
640             }
641
642             memcpy (dst, a8, width);
643             dst  += bo->stride;
644             data += src->stride;
645         }
646     }
647
648     if (a8 != buf)
649         free (a8);
650
651     return CAIRO_STATUS_SUCCESS;
652 }
653
654 cairo_status_t
655 intel_bo_put_image (intel_device_t *device,
656                     intel_bo_t *bo,
657                     cairo_image_surface_t *src,
658                     int src_x, int src_y,
659                     int width, int height,
660                     int dst_x, int dst_y)
661 {
662     uint8_t *data;
663     int size;
664     int offset;
665
666     intel_bo_set_tiling (device, bo);
667
668     offset = dst_y * bo->stride;
669     data = src->data + src_y * src->stride;
670     switch (src->format) {
671     case CAIRO_FORMAT_ARGB32:
672     case CAIRO_FORMAT_RGB24:
673         offset += 4 * dst_x;
674         data   += 4 * src_x;
675         size    = 4 * width;
676         break;
677     case CAIRO_FORMAT_RGB16_565:
678         offset += 2 * dst_x;
679         data   += 2 * src_x;
680         size    = 2 * width;
681         break;
682     case CAIRO_FORMAT_A8:
683         offset += dst_x;
684         data   += src_x;
685         size    = width;
686         break;
687     case CAIRO_FORMAT_A1:
688         return _intel_bo_put_a1_image (device, bo, src,
689                                        src_x, src_y,
690                                        width, height,
691                                        dst_x, dst_y);
692     default:
693     case CAIRO_FORMAT_INVALID:
694         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
695     }
696
697     if (bo->tiling == I915_TILING_NONE && src->stride == bo->stride) {
698         intel_bo_write (device, bo, offset, bo->stride * height, data);
699     } else {
700         uint8_t *dst;
701
702         dst = intel_bo_map (device, bo);
703         if (unlikely (dst == NULL))
704             return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
705
706         dst += offset;
707         while (height--) {
708             memcpy (dst, data, size);
709             dst  += bo->stride;
710             data += src->stride;
711         }
712     }
713
714     return CAIRO_STATUS_SUCCESS;
715 }
716
717 static cairo_bool_t
718 _intel_snapshot_cache_entry_can_remove (const void *closure)
719 {
720     return TRUE;
721 }
722
723 static void
724 _intel_snapshot_cache_entry_destroy (void *closure)
725 {
726     intel_surface_t *surface = cairo_container_of (closure,
727                                                    intel_surface_t,
728                                                    snapshot_cache_entry);
729
730     surface->snapshot_cache_entry.hash = 0;
731 }
732
733 cairo_status_t
734 intel_device_init (intel_device_t *device, int fd)
735 {
736     struct drm_i915_gem_get_aperture aperture;
737     cairo_status_t status;
738     size_t size;
739     int ret;
740     int n;
741
742     ret = ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
743     if (ret != 0)
744         return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
745
746     CAIRO_MUTEX_INIT (device->mutex);
747
748     device->gtt_max_size = aperture.aper_size;
749     device->gtt_avail_size = aperture.aper_available_size;
750     device->gtt_avail_size -= device->gtt_avail_size >> 5;
751
752     size = aperture.aper_size / 8;
753     device->snapshot_cache_max_size = size / 4;
754     status = _cairo_cache_init (&device->snapshot_cache,
755                                 NULL,
756                                 _intel_snapshot_cache_entry_can_remove,
757                                 _intel_snapshot_cache_entry_destroy,
758                                 size);
759     if (unlikely (status))
760         return status;
761
762     for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++) {
763         device->glyph_cache[n].buffer.bo = NULL;
764         cairo_list_init (&device->glyph_cache[n].rtree.pinned);
765     }
766     cairo_list_init (&device->fonts);
767
768     device->gradient_cache.size = 0;
769
770     device->base.bo.release = intel_bo_release;
771
772     return CAIRO_STATUS_SUCCESS;
773 }
774
775 static void
776 _intel_gradient_cache_fini (intel_device_t *device)
777 {
778     unsigned int n;
779
780     for (n = 0; n < device->gradient_cache.size; n++) {
781         _cairo_pattern_fini (&device->gradient_cache.cache[n].pattern.base);
782         if (device->gradient_cache.cache[n].buffer.bo != NULL)
783             cairo_drm_bo_destroy (&device->base.base,
784                                   &device->gradient_cache.cache[n].buffer.bo->base);
785     }
786 }
787
788 static void
789 _intel_glyph_cache_fini (intel_device_t *device, intel_buffer_cache_t *cache)
790 {
791     if (cache->buffer.bo == NULL)
792         return;
793
794     intel_bo_destroy (device, cache->buffer.bo);
795     _cairo_rtree_fini (&cache->rtree);
796 }
797
798 void
799 intel_device_fini (intel_device_t *device)
800 {
801     cairo_scaled_font_t *scaled_font, *next_scaled_font;
802     int n;
803
804     cairo_list_foreach_entry_safe (scaled_font,
805                                    next_scaled_font,
806                                    cairo_scaled_font_t,
807                                    &device->fonts,
808                                    link)
809     {
810         _cairo_scaled_font_revoke_ownership (scaled_font);
811     }
812
813     for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++)
814         _intel_glyph_cache_fini (device, &device->glyph_cache[n]);
815
816     _cairo_cache_fini (&device->snapshot_cache);
817
818     _intel_gradient_cache_fini (device);
819     _cairo_freepool_fini (&device->bo_pool);
820
821     _cairo_drm_device_fini (&device->base);
822 }
823
824 void
825 intel_throttle (intel_device_t *device)
826 {
827     ioctl (device->base.fd, DRM_IOCTL_I915_GEM_THROTTLE);
828 }
829
830 void
831 intel_glyph_cache_unpin (intel_device_t *device)
832 {
833     int n;
834
835     for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++)
836         _cairo_rtree_unpin (&device->glyph_cache[n].rtree);
837 }
838
839 static cairo_status_t
840 intel_glyph_cache_add_glyph (intel_device_t *device,
841                              intel_buffer_cache_t *cache,
842                              cairo_scaled_glyph_t  *scaled_glyph)
843 {
844     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
845     intel_glyph_t *glyph;
846     cairo_rtree_node_t *node = NULL;
847     double sf_x, sf_y;
848     cairo_status_t status;
849     uint8_t *dst, *src;
850     int width, height;
851
852     width = glyph_surface->width;
853     if (width < GLYPH_CACHE_MIN_SIZE)
854         width = GLYPH_CACHE_MIN_SIZE;
855     height = glyph_surface->height;
856     if (height < GLYPH_CACHE_MIN_SIZE)
857         height = GLYPH_CACHE_MIN_SIZE;
858
859     /* search for an available slot */
860     status = _cairo_rtree_insert (&cache->rtree, width, height, &node);
861     /* search for an unpinned slot */
862     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
863         status = _cairo_rtree_evict_random (&cache->rtree, width, height, &node);
864         if (status == CAIRO_STATUS_SUCCESS)
865             status = _cairo_rtree_node_insert (&cache->rtree, node, width, height, &node);
866     }
867     if (unlikely (status))
868         return status;
869
870     /* XXX streaming upload? */
871
872     height = glyph_surface->height;
873     src = glyph_surface->data;
874     dst = cache->buffer.bo->virtual;
875     if (dst == NULL) {
876         dst = intel_bo_map (device, cache->buffer.bo);
877         if (unlikely (dst == NULL))
878             return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
879     }
880
881     dst += node->y * cache->buffer.stride;
882     switch (glyph_surface->format) {
883     case CAIRO_FORMAT_A1: {
884         uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
885         uint8_t *a8 = buf;
886         int x;
887
888         if (width > (int) sizeof (buf)) {
889             a8 = malloc (width);
890             if (unlikely (a8 == NULL))
891                 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
892         }
893
894         dst += node->x;
895         width = glyph_surface->width;
896         while (height--) {
897             for (x = 0; x < width; x++)
898                 a8[x] = src[x>>3] & (1 << (x&7)) ? 0xff : 0x00;
899
900             memcpy (dst, a8, width);
901             dst += cache->buffer.stride;
902             src += glyph_surface->stride;
903         }
904
905         if (a8 != buf)
906             free (a8);
907         break;
908     }
909
910     case CAIRO_FORMAT_A8:
911         dst  += node->x;
912         width = glyph_surface->width;
913         while (height--) {
914             memcpy (dst, src, width);
915             dst += cache->buffer.stride;
916             src += glyph_surface->stride;
917         }
918         break;
919
920     case CAIRO_FORMAT_ARGB32:
921         dst  += 4*node->x;
922         width = 4*glyph_surface->width;
923         while (height--) {
924             memcpy (dst, src, width);
925             dst += cache->buffer.stride;
926             src += glyph_surface->stride;
927         }
928         break;
929     default:
930     case CAIRO_FORMAT_RGB16_565:
931     case CAIRO_FORMAT_RGB24:
932     case CAIRO_FORMAT_INVALID:
933         ASSERT_NOT_REACHED;
934         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
935     }
936
937     scaled_glyph->surface_private = node;
938
939     glyph= (intel_glyph_t *) node;
940     glyph->node.owner = &scaled_glyph->surface_private;
941     glyph->cache = cache;
942
943     /* compute tex coords: bottom-right, bottom-left, top-left */
944     sf_x = 1. / cache->buffer.width;
945     sf_y = 1. / cache->buffer.height;
946     glyph->texcoord[0] =
947         texcoord_2d_16 (sf_x * (node->x + glyph_surface->width),
948                         sf_y * (node->y + glyph_surface->height));
949     glyph->texcoord[1] =
950         texcoord_2d_16 (sf_x * node->x,
951                         sf_y * (node->y + glyph_surface->height));
952     glyph->texcoord[2] =
953         texcoord_2d_16 (sf_x * node->x,
954                         sf_y * node->y);
955
956     glyph->width  = glyph_surface->width;
957     glyph->height = glyph_surface->height;
958
959     return CAIRO_STATUS_SUCCESS;
960 }
961
962 void
963 intel_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
964                          cairo_scaled_font_t  *scaled_font)
965 {
966     intel_glyph_t *glyph;
967
968     glyph = scaled_glyph->surface_private;
969     if (glyph != NULL) {
970         /* XXX thread-safety? Probably ok due to the frozen scaled-font. */
971         glyph->node.owner = NULL;
972         if (! glyph->node.pinned)
973             _cairo_rtree_node_remove (&glyph->cache->rtree, &glyph->node);
974     }
975 }
976
977 void
978 intel_scaled_font_fini (cairo_scaled_font_t *scaled_font)
979 {
980     cairo_list_del (&scaled_font->link);
981 }
982
983 static cairo_status_t
984 intel_get_glyph_cache (intel_device_t *device,
985                        cairo_format_t format,
986                        intel_buffer_cache_t **out)
987 {
988     intel_buffer_cache_t *cache;
989     cairo_status_t status;
990
991     switch (format) {
992     case CAIRO_FORMAT_ARGB32:
993         cache = &device->glyph_cache[0];
994         format = CAIRO_FORMAT_ARGB32;
995         break;
996     case CAIRO_FORMAT_A8:
997     case CAIRO_FORMAT_A1:
998         cache = &device->glyph_cache[1];
999         format = CAIRO_FORMAT_A8;
1000         break;
1001     default:
1002     case CAIRO_FORMAT_RGB16_565:
1003     case CAIRO_FORMAT_RGB24:
1004     case CAIRO_FORMAT_INVALID:
1005         ASSERT_NOT_REACHED;
1006         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1007     }
1008
1009     if (unlikely (cache->buffer.bo == NULL)) {
1010         status = intel_buffer_cache_init (cache, device, format,
1011                                          INTEL_GLYPH_CACHE_WIDTH,
1012                                          INTEL_GLYPH_CACHE_HEIGHT);
1013         if (unlikely (status))
1014             return status;
1015
1016         _cairo_rtree_init (&cache->rtree,
1017                            INTEL_GLYPH_CACHE_WIDTH,
1018                            INTEL_GLYPH_CACHE_HEIGHT,
1019                            0, sizeof (intel_glyph_t));
1020     }
1021
1022     *out = cache;
1023     return CAIRO_STATUS_SUCCESS;
1024 }
1025
1026 cairo_int_status_t
1027 intel_get_glyph (intel_device_t *device,
1028                  cairo_scaled_font_t *scaled_font,
1029                  cairo_scaled_glyph_t *scaled_glyph)
1030 {
1031     cairo_bool_t own_surface = FALSE;
1032     intel_buffer_cache_t *cache;
1033     cairo_status_t status;
1034
1035     if (scaled_glyph->surface == NULL) {
1036         status =
1037             scaled_font->backend->scaled_glyph_init (scaled_font,
1038                                                      scaled_glyph,
1039                                                      CAIRO_SCALED_GLYPH_INFO_SURFACE);
1040         if (unlikely (status))
1041             return status;
1042
1043         if (unlikely (scaled_glyph->surface == NULL))
1044             return CAIRO_INT_STATUS_UNSUPPORTED;
1045
1046         own_surface = TRUE;
1047     }
1048
1049     if (unlikely (scaled_glyph->surface->width == 0 ||
1050                   scaled_glyph->surface->height == 0))
1051     {
1052         return CAIRO_INT_STATUS_NOTHING_TO_DO;
1053     }
1054
1055     if (unlikely (scaled_glyph->surface->width  > GLYPH_CACHE_MAX_SIZE ||
1056                   scaled_glyph->surface->height > GLYPH_CACHE_MAX_SIZE))
1057     {
1058         return CAIRO_INT_STATUS_UNSUPPORTED;
1059     }
1060
1061     status = intel_get_glyph_cache (device,
1062                                     scaled_glyph->surface->format,
1063                                     &cache);
1064     if (unlikely (status))
1065         return status;
1066
1067     status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph);
1068     if (unlikely (_cairo_status_is_error (status)))
1069         return status;
1070
1071     if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) {
1072         /* no room, replace entire cache */
1073
1074         assert (cache->buffer.bo->exec != NULL);
1075
1076         _cairo_rtree_reset (&cache->rtree);
1077         intel_bo_destroy (device, cache->buffer.bo);
1078         cache->buffer.bo = NULL;
1079
1080         status = intel_buffer_cache_init (cache, device,
1081                                           scaled_glyph->surface->format,
1082                                           GLYPH_CACHE_WIDTH,
1083                                           GLYPH_CACHE_HEIGHT);
1084         if (unlikely (status))
1085             return status;
1086
1087         status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph);
1088         if (unlikely (status))
1089             return status;
1090     }
1091
1092     if (own_surface) {
1093         /* and release the copy of the image from system memory */
1094         cairo_surface_destroy (&scaled_glyph->surface->base);
1095         scaled_glyph->surface = NULL;
1096     }
1097
1098     return CAIRO_STATUS_SUCCESS;
1099 }
1100
1101 cairo_status_t
1102 intel_buffer_cache_init (intel_buffer_cache_t *cache,
1103                         intel_device_t *device,
1104                         cairo_format_t format,
1105                         int width, int height)
1106 {
1107     const uint32_t tiling = I915_TILING_Y;
1108     uint32_t stride, size;
1109
1110     assert ((width & 3) == 0);
1111     assert ((height & 1) == 0);
1112     cache->buffer.format = format;
1113     cache->buffer.width = width;
1114     cache->buffer.height = height;
1115
1116     switch (format) {
1117     default:
1118     case CAIRO_FORMAT_A1:
1119     case CAIRO_FORMAT_RGB16_565:
1120     case CAIRO_FORMAT_RGB24:
1121     case CAIRO_FORMAT_INVALID:
1122         ASSERT_NOT_REACHED;
1123         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1124     case CAIRO_FORMAT_ARGB32:
1125         cache->buffer.map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
1126         stride = width * 4;
1127         break;
1128     case CAIRO_FORMAT_A8:
1129         cache->buffer.map0 = MAPSURF_8BIT | MT_8BIT_I8;
1130         stride = width;
1131         break;
1132     }
1133
1134     size = height * stride;
1135     cache->buffer.bo = intel_bo_create (device,
1136                                         size, size,
1137                                         FALSE, tiling, stride);
1138     if (unlikely (cache->buffer.bo == NULL))
1139         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1140
1141     cache->buffer.stride = stride;
1142
1143     cache->buffer.offset = 0;
1144     cache->buffer.map0 |= MS3_tiling (tiling);
1145     cache->buffer.map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) |
1146                           ((width - 1)  << MS3_WIDTH_SHIFT);
1147     cache->buffer.map1 = ((stride / 4) - 1) << MS4_PITCH_SHIFT;
1148
1149     cache->ref_count = 0;
1150     cairo_list_init (&cache->link);
1151
1152     return CAIRO_STATUS_SUCCESS;
1153 }
1154
1155 cairo_status_t
1156 intel_snapshot_cache_insert (intel_device_t *device,
1157                              intel_surface_t *surface)
1158 {
1159     cairo_status_t status;
1160
1161     surface->snapshot_cache_entry.size = surface->drm.bo->size;
1162     if (surface->snapshot_cache_entry.size >
1163         device->snapshot_cache_max_size)
1164     {
1165         return CAIRO_STATUS_SUCCESS;
1166     }
1167
1168     if (device->snapshot_cache.freeze_count == 0)
1169         _cairo_cache_freeze (&device->snapshot_cache);
1170
1171     surface->snapshot_cache_entry.hash = (unsigned long) surface;
1172     status = _cairo_cache_insert (&device->snapshot_cache,
1173                                   &surface->snapshot_cache_entry);
1174     if (unlikely (status)) {
1175         surface->snapshot_cache_entry.hash = 0;
1176         return status;
1177     }
1178
1179     return CAIRO_STATUS_SUCCESS;
1180 }
1181
1182 void
1183 intel_surface_detach_snapshot (cairo_surface_t *abstract_surface)
1184 {
1185     intel_surface_t *surface = (intel_surface_t *) abstract_surface;
1186
1187     if (surface->snapshot_cache_entry.hash) {
1188         intel_device_t *device;
1189
1190         device = (intel_device_t *) surface->drm.base.device;
1191         _cairo_cache_remove (&device->snapshot_cache,
1192                              &surface->snapshot_cache_entry);
1193         assert (surface->snapshot_cache_entry.hash == 0);
1194     }
1195 }
1196
1197 void
1198 intel_snapshot_cache_thaw (intel_device_t *device)
1199 {
1200     if (device->snapshot_cache.freeze_count)
1201         _cairo_cache_thaw (&device->snapshot_cache);
1202 }
1203
1204 static cairo_bool_t
1205 _gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
1206                              const cairo_gradient_pattern_t *b)
1207 {
1208     unsigned int n;
1209
1210     if (a->n_stops != b->n_stops)
1211         return FALSE;
1212
1213     for (n = 0; n < a->n_stops; n++) {
1214         if (_cairo_fixed_from_double (a->stops[n].offset) !=
1215             _cairo_fixed_from_double (b->stops[n].offset))
1216         {
1217             return FALSE;
1218         }
1219
1220         if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
1221             return FALSE;
1222     }
1223
1224     return TRUE;
1225 }
1226
1227 static uint32_t
1228 hars_petruska_f54_1_random (void)
1229 {
1230 #define rol(x,k) ((x << k) | (x >> (32-k)))
1231     static uint32_t x;
1232     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
1233 #undef rol
1234 }
1235
1236 static int
1237 intel_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
1238 {
1239     unsigned int n;
1240     int width;
1241
1242     width = 8;
1243     for (n = 1; n < gradient->n_stops; n++) {
1244         double dx = gradient->stops[n].offset - gradient->stops[n-1].offset;
1245         double delta, max;
1246         int ramp;
1247
1248         if (dx == 0)
1249             continue;
1250
1251         max = gradient->stops[n].color.red -
1252               gradient->stops[n-1].color.red;
1253
1254         delta = gradient->stops[n].color.green -
1255                 gradient->stops[n-1].color.green;
1256         if (delta > max)
1257             max = delta;
1258
1259         delta = gradient->stops[n].color.blue -
1260                 gradient->stops[n-1].color.blue;
1261         if (delta > max)
1262             max = delta;
1263
1264         delta = gradient->stops[n].color.alpha -
1265                 gradient->stops[n-1].color.alpha;
1266         if (delta > max)
1267             max = delta;
1268
1269         ramp = 128 * max / dx;
1270         if (ramp > width)
1271             width = ramp;
1272     }
1273
1274     width = (width + 7) & -8;
1275     return MIN (width, 1024);
1276 }
1277
1278 cairo_status_t
1279 intel_gradient_render (intel_device_t *device,
1280                        const cairo_gradient_pattern_t *pattern,
1281                        intel_buffer_t *buffer)
1282 {
1283     pixman_image_t *gradient, *image;
1284     pixman_gradient_stop_t pixman_stops_stack[32];
1285     pixman_gradient_stop_t *pixman_stops;
1286     pixman_point_fixed_t p1, p2;
1287     int width;
1288     unsigned int i;
1289     cairo_status_t status;
1290
1291     for (i = 0; i < device->gradient_cache.size; i++) {
1292         if (_gradient_color_stops_equal (pattern,
1293                                          &device->gradient_cache.cache[i].pattern.gradient.base)) {
1294             *buffer = device->gradient_cache.cache[i].buffer;
1295             return CAIRO_STATUS_SUCCESS;
1296         }
1297     }
1298
1299     pixman_stops = pixman_stops_stack;
1300     if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
1301         pixman_stops = _cairo_malloc_ab (pattern->n_stops,
1302                                          sizeof (pixman_gradient_stop_t));
1303         if (unlikely (pixman_stops == NULL))
1304             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1305     }
1306
1307     for (i = 0; i < pattern->n_stops; i++) {
1308         pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
1309         pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
1310         pixman_stops[i].color.green = pattern->stops[i].color.green_short;
1311         pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
1312         pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
1313     }
1314
1315     width = intel_gradient_sample_width (pattern);
1316
1317     p1.x = 0;
1318     p1.y = 0;
1319     p2.x = width << 16;
1320     p2.y = 0;
1321
1322     gradient = pixman_image_create_linear_gradient (&p1, &p2,
1323                                                     pixman_stops,
1324                                                     pattern->n_stops);
1325     if (pixman_stops != pixman_stops_stack)
1326         free (pixman_stops);
1327
1328     if (unlikely (gradient == NULL))
1329         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1330
1331     pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
1332     pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
1333
1334     image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1, NULL, 0);
1335     if (unlikely (image == NULL)) {
1336         pixman_image_unref (gradient);
1337         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1338     }
1339
1340     pixman_image_composite32 (PIXMAN_OP_SRC,
1341                               gradient, NULL, image,
1342                               0, 0,
1343                               0, 0,
1344                               0, 0,
1345                               width, 1);
1346
1347     pixman_image_unref (gradient);
1348
1349     buffer->bo = intel_bo_create (device,
1350                                   4*width, 4*width,
1351                                   FALSE, I915_TILING_NONE, 4*width);
1352     if (unlikely (buffer->bo == NULL)) {
1353         pixman_image_unref (image);
1354         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1355     }
1356
1357     intel_bo_write (device, buffer->bo, 0, 4*width, pixman_image_get_data (image));
1358     pixman_image_unref (image);
1359
1360     buffer->offset = 0;
1361     buffer->width  = width;
1362     buffer->height = 1;
1363     buffer->stride = 4*width;
1364     buffer->format = CAIRO_FORMAT_ARGB32;
1365     buffer->map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
1366     buffer->map0 |= ((width - 1) << MS3_WIDTH_SHIFT);
1367     buffer->map1 = (width - 1) << MS4_PITCH_SHIFT;
1368
1369     if (device->gradient_cache.size < GRADIENT_CACHE_SIZE) {
1370         i = device->gradient_cache.size++;
1371     } else {
1372         i = hars_petruska_f54_1_random () % GRADIENT_CACHE_SIZE;
1373         _cairo_pattern_fini (&device->gradient_cache.cache[i].pattern.base);
1374         intel_bo_destroy (device, device->gradient_cache.cache[i].buffer.bo);
1375     }
1376
1377     status = _cairo_pattern_init_copy (&device->gradient_cache.cache[i].pattern.base,
1378                                        &pattern->base);
1379     if (unlikely (status)) {
1380         intel_bo_destroy (device, buffer->bo);
1381         /* Ensure the cache is correctly initialised for i965_device_destroy */
1382         _cairo_pattern_init_solid (&device->gradient_cache.cache[i].pattern.solid,
1383                                    CAIRO_COLOR_TRANSPARENT);
1384         return status;
1385     }
1386
1387     device->gradient_cache.cache[i].buffer = *buffer;
1388     return CAIRO_STATUS_SUCCESS;
1389 }