summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/cairo/src/drm/cairo-drm-intel.c
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/cairo/src/drm/cairo-drm-intel.c')
-rw-r--r--gfx/cairo/cairo/src/drm/cairo-drm-intel.c1347
1 files changed, 0 insertions, 1347 deletions
diff --git a/gfx/cairo/cairo/src/drm/cairo-drm-intel.c b/gfx/cairo/cairo/src/drm/cairo-drm-intel.c
deleted file mode 100644
index e6fb83dd51..0000000000
--- a/gfx/cairo/cairo/src/drm/cairo-drm-intel.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2009 Chris Wilson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- */
-
-#include "cairoint.h"
-
-#include "cairo-drm-private.h"
-#include "cairo-drm-intel-private.h"
-#include "cairo-drm-intel-ioctl-private.h"
-
-#include "cairo-error-private.h"
-#include "cairo-freelist-private.h"
-#include "cairo-pattern-private.h"
-#include "cairo-image-surface-private.h"
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <drm/i915_drm.h>
-
-#define GLYPH_CACHE_WIDTH 1024
-#define GLYPH_CACHE_HEIGHT 1024
-#define GLYPH_CACHE_MIN_SIZE 1
-#define GLYPH_CACHE_MAX_SIZE 128
-
-#define IMAGE_CACHE_WIDTH 1024
-#define IMAGE_CACHE_HEIGHT 1024
-
-int
-intel_get (int fd, int param)
-{
- struct drm_i915_getparam gp;
- int value;
-
- gp.param = param;
- gp.value = &value;
- if (ioctl (fd, DRM_IOCTL_I915_GETPARAM, &gp) < 0)
- return 0;
-
- VG (VALGRIND_MAKE_MEM_DEFINED (&value, sizeof (value)));
-
- return value;
-}
-
-cairo_bool_t
-intel_info (int fd, uint64_t *gtt_size)
-{
- struct drm_i915_gem_get_aperture info;
-
- if (! intel_get (fd, I915_PARAM_HAS_GEM))
- return FALSE;
-
- if (! intel_get (fd, I915_PARAM_HAS_EXECBUF2))
- return FALSE;
-
- if (ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &info) < 0)
- return FALSE;
-
- VG (VALGRIND_MAKE_MEM_DEFINED (&info, sizeof (info)));
-
- if (gtt_size != NULL)
- *gtt_size = info.aper_size;
-
- return TRUE;
-}
-
-void
-intel_bo_write (const intel_device_t *device,
- intel_bo_t *bo,
- unsigned long offset,
- unsigned long size,
- const void *data)
-{
- struct drm_i915_gem_pwrite pwrite;
- int ret;
-
- assert (bo->tiling == I915_TILING_NONE);
- assert (size);
- assert (offset < bo->base.size);
- assert (size+offset <= bo->base.size);
-
- intel_bo_set_tiling (device, bo);
-
- assert (bo->_tiling == I915_TILING_NONE);
-
- memset (&pwrite, 0, sizeof (pwrite));
- pwrite.handle = bo->base.handle;
- pwrite.offset = offset;
- pwrite.size = size;
- pwrite.data_ptr = (uint64_t) (uintptr_t) data;
- do {
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite);
- } while (ret == -1 && errno == EINTR);
- assert (ret == 0);
-
- bo->busy = FALSE;
-}
-
-void
-intel_bo_read (const intel_device_t *device,
- intel_bo_t *bo,
- unsigned long offset,
- unsigned long size,
- void *data)
-{
- struct drm_i915_gem_pread pread;
- int ret;
-
- assert (bo->tiling == I915_TILING_NONE);
- assert (size);
- assert (offset < bo->base.size);
- assert (size+offset <= bo->base.size);
-
- intel_bo_set_tiling (device, bo);
-
- assert (bo->_tiling == I915_TILING_NONE);
-
- memset (&pread, 0, sizeof (pread));
- pread.handle = bo->base.handle;
- pread.offset = offset;
- pread.size = size;
- pread.data_ptr = (uint64_t) (uintptr_t) data;
- do {
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_PREAD, &pread);
- } while (ret == -1 && errno == EINTR);
- assert (ret == 0);
-
- bo->cpu = TRUE;
- bo->busy = FALSE;
-}
-
-void *
-intel_bo_map (const intel_device_t *device, intel_bo_t *bo)
-{
- struct drm_i915_gem_set_domain set_domain;
- uint32_t domain;
- int ret;
-
- intel_bo_set_tiling (device, bo);
-
- if (bo->virtual != NULL)
- return bo->virtual;
-
- if (bo->cpu && bo->tiling == I915_TILING_NONE) {
- struct drm_i915_gem_mmap mmap_arg;
-
- mmap_arg.handle = bo->base.handle;
- mmap_arg.offset = 0;
- mmap_arg.size = bo->base.size;
- mmap_arg.addr_ptr = 0;
-
- do {
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
- } while (ret == -1 && errno == EINTR);
- if (unlikely (ret != 0)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- bo->virtual = (void *) (uintptr_t) mmap_arg.addr_ptr;
- domain = I915_GEM_DOMAIN_CPU;
- } else {
- struct drm_i915_gem_mmap_gtt mmap_arg;
- void *ptr;
-
- /* Get the fake offset back... */
- mmap_arg.handle = bo->base.handle;
- do {
- ret = ioctl (device->base.fd,
- DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
- } while (ret == -1 && errno == EINTR);
- if (unlikely (ret != 0)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- /* and mmap it */
- ptr = mmap (0, bo->base.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, device->base.fd,
- mmap_arg.offset);
- if (unlikely (ptr == MAP_FAILED)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- bo->virtual = ptr;
- domain = I915_GEM_DOMAIN_GTT;
- }
-
- VG (VALGRIND_MAKE_MEM_DEFINED (bo->virtual, bo->base.size));
-
- set_domain.handle = bo->base.handle;
- set_domain.read_domains = domain;
- set_domain.write_domain = domain;
-
- do {
- ret = ioctl (device->base.fd,
- DRM_IOCTL_I915_GEM_SET_DOMAIN,
- &set_domain);
- } while (ret == -1 && errno == EINTR);
-
- if (ret != 0) {
- intel_bo_unmap (bo);
- _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR);
- return NULL;
- }
-
- bo->busy = FALSE;
- return bo->virtual;
-}
-
-void
-intel_bo_unmap (intel_bo_t *bo)
-{
- munmap (bo->virtual, bo->base.size);
- bo->virtual = NULL;
-}
-
-cairo_bool_t
-intel_bo_is_inactive (const intel_device_t *device, intel_bo_t *bo)
-{
- struct drm_i915_gem_busy busy;
-
- if (! bo->busy)
- return TRUE;
-
- /* Is this buffer busy for our intended usage pattern? */
- busy.handle = bo->base.handle;
- busy.busy = 1;
- ioctl (device->base.fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
-
- bo->busy = busy.busy;
- return ! busy.busy;
-}
-
-cairo_bool_t
-intel_bo_wait (const intel_device_t *device, const intel_bo_t *bo)
-{
- struct drm_i915_gem_set_domain set_domain;
- int ret;
-
- set_domain.handle = bo->base.handle;
- set_domain.read_domains = I915_GEM_DOMAIN_GTT;
- set_domain.write_domain = 0;
-
- do {
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
- } while (ret == -1 && errno == EINTR);
-
- return ret == 0;
-}
-
-static inline int
-pot (int v)
-{
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
-}
-
-cairo_bool_t
-intel_bo_madvise (intel_device_t *device,
- intel_bo_t *bo,
- int advice)
-{
- struct drm_i915_gem_madvise madv;
-
- madv.handle = bo->base.handle;
- madv.madv = advice;
- madv.retained = TRUE;
- ioctl (device->base.fd, DRM_IOCTL_I915_GEM_MADVISE, &madv);
- return madv.retained;
-}
-
-static void
-intel_bo_set_real_size (intel_device_t *device,
- intel_bo_t *bo,
- size_t size)
-{
- struct drm_i915_gem_real_size arg;
- int ret;
-
- return;
-
- if (size == bo->base.size)
- return;
-
- arg.handle = bo->base.handle;
- arg.size = size;
- do {
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_REAL_SIZE, &arg);
- } while (ret == -1 && errno == EINTR);
-
- if (ret == 0) {
- if (size > bo->base.size) {
- assert (bo->exec == NULL);
- bo->cpu = TRUE;
- bo->busy = FALSE;
- }
-
- bo->base.size = size;
- }
-}
-
-intel_bo_t *
-intel_bo_create (intel_device_t *device,
- uint32_t max_size,
- uint32_t real_size,
- cairo_bool_t gpu_target,
- uint32_t tiling,
- uint32_t stride)
-{
- intel_bo_t *bo;
- uint32_t cache_size;
- struct drm_i915_gem_create create;
- int bucket;
- int ret;
-
- max_size = (max_size + 4095) & -4096;
- real_size = (real_size + 4095) & -4096;
- cache_size = pot (max_size);
- bucket = ffs (cache_size / 4096) - 1;
- if (bucket >= INTEL_BO_CACHE_BUCKETS)
- cache_size = max_size;
-
- if (gpu_target) {
- intel_bo_t *first = NULL;
-
- cairo_list_foreach_entry (bo, intel_bo_t,
- &device->bo_in_flight,
- cache_list)
- {
- assert (bo->exec != NULL);
- if (tiling && bo->_tiling &&
- (bo->_tiling != tiling || bo->_stride != stride))
- {
- continue;
- }
-
- if (real_size <= bo->base.size) {
- if (real_size >= bo->base.size/2) {
- cairo_list_del (&bo->cache_list);
- bo = intel_bo_reference (bo);
- goto DONE;
- }
-
- if (first == NULL)
- first = bo;
- }
- }
-
- if (first != NULL) {
- cairo_list_del (&first->cache_list);
- bo = intel_bo_reference (first);
- goto DONE;
- }
- }
-
- /* no cached buffer available, allocate fresh */
- bo = _cairo_freepool_alloc (&device->bo_pool);
- if (unlikely (bo == NULL)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return bo;
- }
-
- cairo_list_init (&bo->cache_list);
-
- bo->base.name = 0;
-
- bo->offset = 0;
- bo->virtual = NULL;
- bo->cpu = TRUE;
-
- bo->_tiling = I915_TILING_NONE;
- bo->_stride = 0;
- bo->purgeable = 0;
- bo->busy = FALSE;
-
- bo->opaque0 = 0;
- bo->opaque1 = 0;
-
- bo->exec = NULL;
- bo->batch_read_domains = 0;
- bo->batch_write_domain = 0;
- cairo_list_init (&bo->link);
-
- create.size = cache_size;
- create.handle = 0;
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_CREATE, &create);
- if (unlikely (ret != 0)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- _cairo_freepool_free (&device->bo_pool, bo);
- return NULL;
- }
-
- bo->base.handle = create.handle;
- bo->full_size = bo->base.size = create.size;
-
- intel_bo_set_real_size (device, bo, real_size);
- CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1);
-DONE:
- bo->tiling = tiling;
- bo->stride = stride;
- return bo;
-}
-
-intel_bo_t *
-intel_bo_create_for_name (intel_device_t *device, uint32_t name)
-{
- struct drm_i915_gem_get_tiling get_tiling;
- cairo_status_t status;
- intel_bo_t *bo;
- int ret;
-
- bo = _cairo_freepool_alloc (&device->bo_pool);
- if (unlikely (bo == NULL)) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- status = _cairo_drm_bo_open_for_name (&device->base, &bo->base, name);
- if (unlikely (status))
- goto FAIL;
-
- CAIRO_REFERENCE_COUNT_INIT (&bo->base.ref_count, 1);
- cairo_list_init (&bo->cache_list);
-
- bo->full_size = bo->base.size;
- bo->offset = 0;
- bo->virtual = NULL;
- bo->purgeable = 0;
- bo->busy = TRUE;
- bo->cpu = FALSE;
-
- bo->opaque0 = 0;
- bo->opaque1 = 0;
-
- bo->exec = NULL;
- bo->batch_read_domains = 0;
- bo->batch_write_domain = 0;
- cairo_list_init (&bo->link);
-
- memset (&get_tiling, 0, sizeof (get_tiling));
- get_tiling.handle = bo->base.handle;
-
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling);
- if (unlikely (ret != 0)) {
- _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR);
- _cairo_drm_bo_close (&device->base, &bo->base);
- goto FAIL;
- }
-
- bo->_tiling = bo->tiling = get_tiling.tiling_mode;
- // bo->stride = get_tiling.stride; /* XXX not available from get_tiling */
-
- return bo;
-
-FAIL:
- _cairo_freepool_free (&device->bo_pool, bo);
- return NULL;
-}
-
-static void
-intel_bo_release (void *_dev, void *_bo)
-{
- intel_device_t *device = _dev;
- intel_bo_t *bo = _bo;
-
- if (bo->virtual != NULL)
- intel_bo_unmap (bo);
-
- assert (bo->exec == NULL);
- assert (cairo_list_is_empty (&bo->cache_list));
-
- _cairo_drm_bo_close (&device->base, &bo->base);
- _cairo_freepool_free (&device->bo_pool, bo);
-}
-
-void
-intel_bo_set_tiling (const intel_device_t *device,
- intel_bo_t *bo)
-{
- struct drm_i915_gem_set_tiling set_tiling;
- int ret;
-
- if (bo->tiling == bo->_tiling &&
- (bo->tiling == I915_TILING_NONE || bo->stride == bo->_stride))
- return;
-
- do {
- set_tiling.handle = bo->base.handle;
- set_tiling.tiling_mode = bo->tiling;
- set_tiling.stride = bo->stride;
-
- ret = ioctl (device->base.fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
- } while (ret == -1 && errno == EINTR);
-
- assert (ret == 0);
- bo->_tiling = bo->tiling;
- bo->_stride = bo->stride;
-}
-
-static cairo_status_t
-_intel_bo_put_a1_image (intel_device_t *device,
- intel_bo_t *bo,
- cairo_image_surface_t *src,
- int src_x, int src_y,
- int width, int height,
- int dst_x, int dst_y)
-{
- uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
- uint8_t *a8 = buf;
- uint8_t *data;
- int x;
-
- data = src->data + src_y * src->stride;
-
- if (bo->tiling == I915_TILING_NONE && width == bo->stride) {
- uint8_t *p;
- int size;
-
- size = bo->stride * height;
- if (size > (int) sizeof (buf)) {
- a8 = _cairo_malloc_ab (bo->stride, height);
- if (a8 == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- p = a8;
- while (height--) {
- for (x = 0; x < width; x++) {
- int i = src_x + x;
- int byte = i / 8;
- int bit = i % 8;
- p[x] = data[byte] & (1 << bit) ? 0xff : 0x00;
- }
-
- data += src->stride;
- p += bo->stride;
- }
-
- intel_bo_write (device, bo,
- dst_y * bo->stride + dst_x, /* XXX bo_offset */
- size, a8);
- } else {
- uint8_t *dst;
-
- if (width > (int) sizeof (buf)) {
- a8 = _cairo_malloc (width);
- if (a8 == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- dst = intel_bo_map (device, bo);
- if (dst == NULL) {
- if (a8 != buf)
- free (a8);
- return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
- }
-
- dst += dst_y * bo->stride + dst_x; /* XXX bo_offset */
- while (height--) {
- for (x = 0; x < width; x++) {
- int i = src_x + x;
- int byte = i / 8;
- int bit = i % 8;
- a8[x] = data[byte] & (1 << bit) ? 0xff : 0x00;
- }
-
- memcpy (dst, a8, width);
- dst += bo->stride;
- data += src->stride;
- }
- }
-
- if (a8 != buf)
- free (a8);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-intel_bo_put_image (intel_device_t *device,
- intel_bo_t *bo,
- cairo_image_surface_t *src,
- int src_x, int src_y,
- int width, int height,
- int dst_x, int dst_y)
-{
- uint8_t *data;
- int size;
- int offset;
-
- intel_bo_set_tiling (device, bo);
-
- offset = dst_y * bo->stride;
- data = src->data + src_y * src->stride;
- switch (src->format) {
- case CAIRO_FORMAT_ARGB32:
- case CAIRO_FORMAT_RGB24:
- offset += 4 * dst_x;
- data += 4 * src_x;
- size = 4 * width;
- break;
- case CAIRO_FORMAT_RGB16_565:
- offset += 2 * dst_x;
- data += 2 * src_x;
- size = 2 * width;
- break;
- case CAIRO_FORMAT_A8:
- offset += dst_x;
- data += src_x;
- size = width;
- break;
- case CAIRO_FORMAT_A1:
- return _intel_bo_put_a1_image (device, bo, src,
- src_x, src_y,
- width, height,
- dst_x, dst_y);
- default:
- case CAIRO_FORMAT_INVALID:
- return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
- }
-
- if (bo->tiling == I915_TILING_NONE && src->stride == bo->stride) {
- intel_bo_write (device, bo, offset, bo->stride * height, data);
- } else {
- uint8_t *dst;
-
- dst = intel_bo_map (device, bo);
- if (unlikely (dst == NULL))
- return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
-
- dst += offset;
- while (height--) {
- memcpy (dst, data, size);
- dst += bo->stride;
- data += src->stride;
- }
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-_intel_snapshot_cache_entry_can_remove (const void *closure)
-{
- return TRUE;
-}
-
-static void
-_intel_snapshot_cache_entry_destroy (void *closure)
-{
- intel_surface_t *surface = cairo_container_of (closure,
- intel_surface_t,
- snapshot_cache_entry);
-
- surface->snapshot_cache_entry.hash = 0;
-}
-
-cairo_status_t
-intel_device_init (intel_device_t *device, int fd)
-{
- struct drm_i915_gem_get_aperture aperture;
- cairo_status_t status;
- size_t size;
- int ret;
- int n;
-
- ret = ioctl (fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
- if (ret != 0)
- return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
-
- CAIRO_MUTEX_INIT (device->mutex);
-
- device->gtt_max_size = aperture.aper_size;
- device->gtt_avail_size = aperture.aper_available_size;
- device->gtt_avail_size -= device->gtt_avail_size >> 5;
-
- size = aperture.aper_size / 8;
- device->snapshot_cache_max_size = size / 4;
- status = _cairo_cache_init (&device->snapshot_cache,
- NULL,
- _intel_snapshot_cache_entry_can_remove,
- _intel_snapshot_cache_entry_destroy,
- size);
- if (unlikely (status))
- return status;
-
- for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++) {
- device->glyph_cache[n].buffer.bo = NULL;
- cairo_list_init (&device->glyph_cache[n].rtree.pinned);
- }
- cairo_list_init (&device->fonts);
-
- device->gradient_cache.size = 0;
-
- device->base.bo.release = intel_bo_release;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_intel_gradient_cache_fini (intel_device_t *device)
-{
- unsigned int n;
-
- for (n = 0; n < device->gradient_cache.size; n++) {
- _cairo_pattern_fini (&device->gradient_cache.cache[n].pattern.base);
- if (device->gradient_cache.cache[n].buffer.bo != NULL)
- cairo_drm_bo_destroy (&device->base.base,
- &device->gradient_cache.cache[n].buffer.bo->base);
- }
-}
-
-static void
-_intel_glyph_cache_fini (intel_device_t *device, intel_buffer_cache_t *cache)
-{
- if (cache->buffer.bo == NULL)
- return;
-
- intel_bo_destroy (device, cache->buffer.bo);
- _cairo_rtree_fini (&cache->rtree);
-}
-
-void
-intel_device_fini (intel_device_t *device)
-{
- cairo_scaled_font_t *scaled_font, *next_scaled_font;
- int n;
-
- cairo_list_foreach_entry_safe (scaled_font,
- next_scaled_font,
- cairo_scaled_font_t,
- &device->fonts,
- link)
- {
- _cairo_scaled_font_revoke_ownership (scaled_font);
- }
-
- for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++)
- _intel_glyph_cache_fini (device, &device->glyph_cache[n]);
-
- _cairo_cache_fini (&device->snapshot_cache);
-
- _intel_gradient_cache_fini (device);
- _cairo_freepool_fini (&device->bo_pool);
-
- _cairo_drm_device_fini (&device->base);
-}
-
-void
-intel_throttle (intel_device_t *device)
-{
- ioctl (device->base.fd, DRM_IOCTL_I915_GEM_THROTTLE);
-}
-
-void
-intel_glyph_cache_unpin (intel_device_t *device)
-{
- int n;
-
- for (n = 0; n < ARRAY_LENGTH (device->glyph_cache); n++)
- _cairo_rtree_unpin (&device->glyph_cache[n].rtree);
-}
-
-static cairo_status_t
-intel_glyph_cache_add_glyph (intel_device_t *device,
- intel_buffer_cache_t *cache,
- cairo_scaled_glyph_t *scaled_glyph)
-{
- cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
- intel_glyph_t *glyph;
- cairo_rtree_node_t *node = NULL;
- double sf_x, sf_y;
- cairo_status_t status;
- uint8_t *dst, *src;
- int width, height;
-
- width = glyph_surface->width;
- if (width < GLYPH_CACHE_MIN_SIZE)
- width = GLYPH_CACHE_MIN_SIZE;
- height = glyph_surface->height;
- if (height < GLYPH_CACHE_MIN_SIZE)
- height = GLYPH_CACHE_MIN_SIZE;
-
- /* search for an available slot */
- status = _cairo_rtree_insert (&cache->rtree, width, height, &node);
- /* search for an unpinned slot */
- if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- status = _cairo_rtree_evict_random (&cache->rtree, width, height, &node);
- if (status == CAIRO_STATUS_SUCCESS)
- status = _cairo_rtree_node_insert (&cache->rtree, node, width, height, &node);
- }
- if (unlikely (status))
- return status;
-
- /* XXX streaming upload? */
-
- height = glyph_surface->height;
- src = glyph_surface->data;
- dst = cache->buffer.bo->virtual;
- if (dst == NULL) {
- dst = intel_bo_map (device, cache->buffer.bo);
- if (unlikely (dst == NULL))
- return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
- }
-
- dst += node->y * cache->buffer.stride;
- switch (glyph_surface->format) {
- case CAIRO_FORMAT_A1: {
- uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
- uint8_t *a8 = buf;
- int x;
-
- if (width > (int) sizeof (buf)) {
- a8 = _cairo_malloc (width);
- if (unlikely (a8 == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- dst += node->x;
- width = glyph_surface->width;
- while (height--) {
- for (x = 0; x < width; x++)
- a8[x] = src[x>>3] & (1 << (x&7)) ? 0xff : 0x00;
-
- memcpy (dst, a8, width);
- dst += cache->buffer.stride;
- src += glyph_surface->stride;
- }
-
- if (a8 != buf)
- free (a8);
- break;
- }
-
- case CAIRO_FORMAT_A8:
- dst += node->x;
- width = glyph_surface->width;
- while (height--) {
- memcpy (dst, src, width);
- dst += cache->buffer.stride;
- src += glyph_surface->stride;
- }
- break;
-
- case CAIRO_FORMAT_ARGB32:
- dst += 4*node->x;
- width = 4*glyph_surface->width;
- while (height--) {
- memcpy (dst, src, width);
- dst += cache->buffer.stride;
- src += glyph_surface->stride;
- }
- break;
- default:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_INVALID:
- ASSERT_NOT_REACHED;
- return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
- }
-
- scaled_glyph->surface_private = node;
-
- glyph= (intel_glyph_t *) node;
- glyph->node.owner = &scaled_glyph->surface_private;
- glyph->cache = cache;
-
- /* compute tex coords: bottom-right, bottom-left, top-left */
- sf_x = 1. / cache->buffer.width;
- sf_y = 1. / cache->buffer.height;
- glyph->texcoord[0] =
- texcoord_2d_16 (sf_x * (node->x + glyph_surface->width),
- sf_y * (node->y + glyph_surface->height));
- glyph->texcoord[1] =
- texcoord_2d_16 (sf_x * node->x,
- sf_y * (node->y + glyph_surface->height));
- glyph->texcoord[2] =
- texcoord_2d_16 (sf_x * node->x,
- sf_y * node->y);
-
- glyph->width = glyph_surface->width;
- glyph->height = glyph_surface->height;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-void
-intel_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_font_t *scaled_font)
-{
- intel_glyph_t *glyph;
-
- glyph = scaled_glyph->surface_private;
- if (glyph != NULL) {
- /* XXX thread-safety? Probably ok due to the frozen scaled-font. */
- glyph->node.owner = NULL;
- if (! glyph->node.pinned)
- _cairo_rtree_node_remove (&glyph->cache->rtree, &glyph->node);
- }
-}
-
-void
-intel_scaled_font_fini (cairo_scaled_font_t *scaled_font)
-{
- cairo_list_del (&scaled_font->link);
-}
-
-static cairo_status_t
-intel_get_glyph_cache (intel_device_t *device,
- cairo_format_t format,
- intel_buffer_cache_t **out)
-{
- intel_buffer_cache_t *cache;
- cairo_status_t status;
-
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- cache = &device->glyph_cache[0];
- format = CAIRO_FORMAT_ARGB32;
- break;
- case CAIRO_FORMAT_A8:
- case CAIRO_FORMAT_A1:
- cache = &device->glyph_cache[1];
- format = CAIRO_FORMAT_A8;
- break;
- default:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_INVALID:
- ASSERT_NOT_REACHED;
- return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
- }
-
- if (unlikely (cache->buffer.bo == NULL)) {
- status = intel_buffer_cache_init (cache, device, format,
- INTEL_GLYPH_CACHE_WIDTH,
- INTEL_GLYPH_CACHE_HEIGHT);
- if (unlikely (status))
- return status;
-
- _cairo_rtree_init (&cache->rtree,
- INTEL_GLYPH_CACHE_WIDTH,
- INTEL_GLYPH_CACHE_HEIGHT,
- 0, sizeof (intel_glyph_t));
- }
-
- *out = cache;
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-intel_get_glyph (intel_device_t *device,
- cairo_scaled_font_t *scaled_font,
- cairo_scaled_glyph_t *scaled_glyph)
-{
- cairo_bool_t own_surface = FALSE;
- intel_buffer_cache_t *cache;
- cairo_status_t status;
-
- if (scaled_glyph->surface == NULL) {
- status =
- scaled_font->backend->scaled_glyph_init (scaled_font,
- scaled_glyph,
- CAIRO_SCALED_GLYPH_INFO_SURFACE);
- if (unlikely (status))
- return status;
-
- if (unlikely (scaled_glyph->surface == NULL))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- own_surface = TRUE;
- }
-
- if (unlikely (scaled_glyph->surface->width == 0 ||
- scaled_glyph->surface->height == 0))
- {
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
- }
-
- if (unlikely (scaled_glyph->surface->width > GLYPH_CACHE_MAX_SIZE ||
- scaled_glyph->surface->height > GLYPH_CACHE_MAX_SIZE))
- {
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- status = intel_get_glyph_cache (device,
- scaled_glyph->surface->format,
- &cache);
- if (unlikely (status))
- return status;
-
- status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph);
- if (unlikely (_cairo_status_is_error (status)))
- return status;
-
- if (unlikely (status == CAIRO_INT_STATUS_UNSUPPORTED)) {
- /* no room, replace entire cache */
-
- assert (cache->buffer.bo->exec != NULL);
-
- _cairo_rtree_reset (&cache->rtree);
- intel_bo_destroy (device, cache->buffer.bo);
- cache->buffer.bo = NULL;
-
- status = intel_buffer_cache_init (cache, device,
- scaled_glyph->surface->format,
- GLYPH_CACHE_WIDTH,
- GLYPH_CACHE_HEIGHT);
- if (unlikely (status))
- return status;
-
- status = intel_glyph_cache_add_glyph (device, cache, scaled_glyph);
- if (unlikely (status))
- return status;
- }
-
- if (own_surface) {
- /* and release the copy of the image from system memory */
- cairo_surface_destroy (&scaled_glyph->surface->base);
- scaled_glyph->surface = NULL;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-intel_buffer_cache_init (intel_buffer_cache_t *cache,
- intel_device_t *device,
- cairo_format_t format,
- int width, int height)
-{
- const uint32_t tiling = I915_TILING_Y;
- uint32_t stride, size;
-
- assert ((width & 3) == 0);
- assert ((height & 1) == 0);
- cache->buffer.format = format;
- cache->buffer.width = width;
- cache->buffer.height = height;
-
- switch (format) {
- default:
- case CAIRO_FORMAT_A1:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_INVALID:
- ASSERT_NOT_REACHED;
- return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
- case CAIRO_FORMAT_ARGB32:
- cache->buffer.map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
- stride = width * 4;
- break;
- case CAIRO_FORMAT_A8:
- cache->buffer.map0 = MAPSURF_8BIT | MT_8BIT_I8;
- stride = width;
- break;
- }
-
- size = height * stride;
- cache->buffer.bo = intel_bo_create (device,
- size, size,
- FALSE, tiling, stride);
- if (unlikely (cache->buffer.bo == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- cache->buffer.stride = stride;
-
- cache->buffer.offset = 0;
- cache->buffer.map0 |= MS3_tiling (tiling);
- cache->buffer.map0 |= ((height - 1) << MS3_HEIGHT_SHIFT) |
- ((width - 1) << MS3_WIDTH_SHIFT);
- cache->buffer.map1 = ((stride / 4) - 1) << MS4_PITCH_SHIFT;
-
- cache->ref_count = 0;
- cairo_list_init (&cache->link);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-intel_snapshot_cache_insert (intel_device_t *device,
- intel_surface_t *surface)
-{
- cairo_status_t status;
-
- surface->snapshot_cache_entry.size = surface->drm.bo->size;
- if (surface->snapshot_cache_entry.size >
- device->snapshot_cache_max_size)
- {
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (device->snapshot_cache.freeze_count == 0)
- _cairo_cache_freeze (&device->snapshot_cache);
-
- surface->snapshot_cache_entry.hash = (unsigned long) surface;
- status = _cairo_cache_insert (&device->snapshot_cache,
- &surface->snapshot_cache_entry);
- if (unlikely (status)) {
- surface->snapshot_cache_entry.hash = 0;
- return status;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-void
-intel_surface_detach_snapshot (cairo_surface_t *abstract_surface)
-{
- intel_surface_t *surface = (intel_surface_t *) abstract_surface;
-
- if (surface->snapshot_cache_entry.hash) {
- intel_device_t *device;
-
- device = (intel_device_t *) surface->drm.base.device;
- _cairo_cache_remove (&device->snapshot_cache,
- &surface->snapshot_cache_entry);
- assert (surface->snapshot_cache_entry.hash == 0);
- }
-}
-
-void
-intel_snapshot_cache_thaw (intel_device_t *device)
-{
- if (device->snapshot_cache.freeze_count)
- _cairo_cache_thaw (&device->snapshot_cache);
-}
-
-static cairo_bool_t
-_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
- const cairo_gradient_pattern_t *b)
-{
- unsigned int n;
-
- if (a->n_stops != b->n_stops)
- return FALSE;
-
- for (n = 0; n < a->n_stops; n++) {
- if (_cairo_fixed_from_double (a->stops[n].offset) !=
- _cairo_fixed_from_double (b->stops[n].offset))
- {
- return FALSE;
- }
-
- if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static uint32_t
-hars_petruska_f54_1_random (void)
-{
-#define rol(x,k) ((x << k) | (x >> (32-k)))
- static uint32_t x;
- return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
-#undef rol
-}
-
-static int
-intel_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
-{
- unsigned int n;
- int width;
-
- width = 8;
- for (n = 1; n < gradient->n_stops; n++) {
- double dx = gradient->stops[n].offset - gradient->stops[n-1].offset;
- double delta, max;
- int ramp;
-
- if (dx == 0)
- continue;
-
- max = gradient->stops[n].color.red -
- gradient->stops[n-1].color.red;
-
- delta = gradient->stops[n].color.green -
- gradient->stops[n-1].color.green;
- if (delta > max)
- max = delta;
-
- delta = gradient->stops[n].color.blue -
- gradient->stops[n-1].color.blue;
- if (delta > max)
- max = delta;
-
- delta = gradient->stops[n].color.alpha -
- gradient->stops[n-1].color.alpha;
- if (delta > max)
- max = delta;
-
- ramp = 128 * max / dx;
- if (ramp > width)
- width = ramp;
- }
-
- width = (width + 7) & -8;
- return MIN (width, 1024);
-}
-
-cairo_status_t
-intel_gradient_render (intel_device_t *device,
- const cairo_gradient_pattern_t *pattern,
- intel_buffer_t *buffer)
-{
- pixman_image_t *gradient, *image;
- pixman_gradient_stop_t pixman_stops_stack[32];
- pixman_gradient_stop_t *pixman_stops;
- pixman_point_fixed_t p1, p2;
- int width;
- unsigned int i;
- cairo_status_t status;
-
- for (i = 0; i < device->gradient_cache.size; i++) {
- if (_gradient_color_stops_equal (pattern,
- &device->gradient_cache.cache[i].pattern.gradient.base)) {
- *buffer = device->gradient_cache.cache[i].buffer;
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
- pixman_stops = pixman_stops_stack;
- if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
- pixman_stops = _cairo_malloc_ab (pattern->n_stops,
- sizeof (pixman_gradient_stop_t));
- if (unlikely (pixman_stops == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- for (i = 0; i < pattern->n_stops; i++) {
- pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
- pixman_stops[i].color.red = pattern->stops[i].color.red_short;
- pixman_stops[i].color.green = pattern->stops[i].color.green_short;
- pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
- pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
- }
-
- width = intel_gradient_sample_width (pattern);
-
- p1.x = 0;
- p1.y = 0;
- p2.x = width << 16;
- p2.y = 0;
-
- gradient = pixman_image_create_linear_gradient (&p1, &p2,
- pixman_stops,
- pattern->n_stops);
- if (pixman_stops != pixman_stops_stack)
- free (pixman_stops);
-
- if (unlikely (gradient == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
- pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
-
- image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1, NULL, 0);
- if (unlikely (image == NULL)) {
- pixman_image_unref (gradient);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- pixman_image_composite32 (PIXMAN_OP_SRC,
- gradient, NULL, image,
- 0, 0,
- 0, 0,
- 0, 0,
- width, 1);
-
- pixman_image_unref (gradient);
-
- buffer->bo = intel_bo_create (device,
- 4*width, 4*width,
- FALSE, I915_TILING_NONE, 4*width);
- if (unlikely (buffer->bo == NULL)) {
- pixman_image_unref (image);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- intel_bo_write (device, buffer->bo, 0, 4*width, pixman_image_get_data (image));
- pixman_image_unref (image);
-
- buffer->offset = 0;
- buffer->width = width;
- buffer->height = 1;
- buffer->stride = 4*width;
- buffer->format = CAIRO_FORMAT_ARGB32;
- buffer->map0 = MAPSURF_32BIT | MT_32BIT_ARGB8888;
- buffer->map0 |= ((width - 1) << MS3_WIDTH_SHIFT);
- buffer->map1 = (width - 1) << MS4_PITCH_SHIFT;
-
- if (device->gradient_cache.size < GRADIENT_CACHE_SIZE) {
- i = device->gradient_cache.size++;
- } else {
- i = hars_petruska_f54_1_random () % GRADIENT_CACHE_SIZE;
- _cairo_pattern_fini (&device->gradient_cache.cache[i].pattern.base);
- intel_bo_destroy (device, device->gradient_cache.cache[i].buffer.bo);
- }
-
- status = _cairo_pattern_init_copy (&device->gradient_cache.cache[i].pattern.base,
- &pattern->base);
- if (unlikely (status)) {
- intel_bo_destroy (device, buffer->bo);
- /* Ensure the cache is correctly initialised for i965_device_destroy */
- _cairo_pattern_init_solid (&device->gradient_cache.cache[i].pattern.solid,
- CAIRO_COLOR_TRANSPARENT);
- return status;
- }
-
- device->gradient_cache.cache[i].buffer = *buffer;
- return CAIRO_STATUS_SUCCESS;
-}