summaryrefslogtreecommitdiff
path: root/libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c')
-rw-r--r--libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c1926
1 files changed, 0 insertions, 1926 deletions
diff --git a/libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c b/libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c
deleted file mode 100644
index 9d29e47..0000000
--- a/libs/cairo-1.16.0/src/drm/cairo-drm-i965-surface.c
+++ /dev/null
@@ -1,1926 +0,0 @@
-/* Cairo - a vector graphics library with display and print output
- *
- * Copyright © 2009 Kristian Høgsberg
- * Copyright © 2009 Chris Wilson
- * Copyright © 2009 Intel Corporation
- *
- * 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.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Kristian Høgsberg.
- *
- * Based on the xf86-intel-driver i965 render acceleration code,
- * authored by:
- * Wang Zhenyu <zhenyu.z.wang@intel.com>
- * Eric Anholt <eric@anholt.net>
- * Carl Worth <cworth@redhat.com>
- * Keith Packard <keithp@keithp.com>
- */
-
-/* XXX
- *
- * FIXME: Use brw_PLN for [DevCTG-B+]
- *
- */
-
-#include "cairoint.h"
-
-#include "cairo-drm-private.h"
-#include "cairo-drm-intel-private.h"
-#include "cairo-drm-intel-command-private.h"
-#include "cairo-drm-intel-ioctl-private.h"
-#include "cairo-drm-i965-private.h"
-
-#include "cairo-boxes-private.h"
-#include "cairo-composite-rectangles-private.h"
-#include "cairo-default-context-private.h"
-#include "cairo-error-private.h"
-#include "cairo-region-private.h"
-#include "cairo-surface-offset-private.h"
-
-#include <sys/ioctl.h>
-#include <errno.h>
-
-#define I965_MAX_SIZE 8192
-
-static const cairo_surface_backend_t i965_surface_backend;
-
-static void
-i965_stream_init (i965_stream_t *stream,
- uint8_t *data, uint32_t size,
- struct i965_pending_relocation *pending, int max_pending,
- struct drm_i915_gem_relocation_entry *relocations, int max_relocations)
-
-{
- stream->used = stream->committed = 0;
- stream->data = data;
- stream->size = size;
- stream->serial = 1;
-
- stream->num_pending_relocations = 0;
- stream->max_pending_relocations = max_pending;
- stream->pending_relocations = pending;
-
- stream->num_relocations = 0;
- stream->max_relocations = max_relocations;
- stream->relocations = relocations;
-}
-
-static void
-i965_add_relocation (i965_device_t *device,
- intel_bo_t *bo,
- uint32_t read_domains,
- uint32_t write_domain)
-{
- if (bo->exec == NULL) {
- int i;
-
- device->exec.gtt_size += bo->base.size;
-
- i = device->exec.count++;
- assert (i < ARRAY_LENGTH (device->exec.exec));
-
- device->exec.exec[i].handle = bo->base.handle;
- device->exec.exec[i].relocation_count = 0;
- device->exec.exec[i].relocs_ptr = 0;
- device->exec.exec[i].alignment = 0;
- device->exec.exec[i].offset = 0;
- device->exec.exec[i].flags = 0;
- device->exec.exec[i].rsvd1 = 0;
- device->exec.exec[i].rsvd2 = 0;
-
- device->exec.bo[i] = intel_bo_reference (bo);
- bo->exec = &device->exec.exec[i];
- }
-
- if (cairo_list_is_empty (&bo->link))
- cairo_list_add_tail (&device->flush, &bo->link);
-
- assert (write_domain == 0 || bo->batch_write_domain == 0 || bo->batch_write_domain == write_domain);
- bo->batch_read_domains |= read_domains;
- bo->batch_write_domain |= write_domain;
-}
-
-void
-i965_emit_relocation (i965_device_t *device,
- i965_stream_t *stream,
- intel_bo_t *target,
- uint32_t target_offset,
- uint32_t read_domains,
- uint32_t write_domain,
- uint32_t offset)
-{
- int n;
-
- assert (target_offset < target->base.size);
-
- i965_add_relocation (device, target, read_domains, write_domain);
-
- n = stream->num_relocations++;
- assert (n < stream->max_relocations);
-
- stream->relocations[n].offset = offset;
- stream->relocations[n].delta = target_offset;
- stream->relocations[n].target_handle = target->base.handle;
- stream->relocations[n].read_domains = read_domains;
- stream->relocations[n].write_domain = write_domain;
- stream->relocations[n].presumed_offset = target->offset;
-}
-
-static void
-i965_stream_reset (i965_stream_t *stream)
-{
- stream->used = stream->committed = 0;
- stream->num_relocations = 0;
- stream->num_pending_relocations = 0;
- if (++stream->serial == 0)
- stream->serial = 1;
-}
-
-void
-i965_stream_commit (i965_device_t *device,
- i965_stream_t *stream)
-{
- intel_bo_t *bo;
- int n;
-
- assert (stream->used);
-
- bo = intel_bo_create (&device->intel,
- stream->used, stream->used,
- FALSE, I915_TILING_NONE, 0);
-
- /* apply pending relocations */
- for (n = 0; n < stream->num_pending_relocations; n++) {
- struct i965_pending_relocation *p = &stream->pending_relocations[n];
-
- i965_emit_relocation (device, &device->batch, bo,
- p->delta,
- p->read_domains,
- p->write_domain,
- p->offset);
- if (bo->offset)
- *(uint32_t *) (device->batch.data + p->offset) = bo->offset + p->delta;
- }
-
- intel_bo_write (&device->intel, bo, 0, stream->used, stream->data);
-
- if (stream->num_relocations) {
- assert (bo->exec != NULL);
- bo->exec->relocs_ptr = (uintptr_t) stream->relocations;
- bo->exec->relocation_count = stream->num_relocations;
- }
-
- intel_bo_destroy (&device->intel, bo);
-
- i965_stream_reset (stream);
-}
-
-static void
-sf_states_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->sf_states, entry);
- _cairo_freelist_free (&device->sf_freelist, entry);
-}
-
-static void
-cc_offsets_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->cc_states, entry);
- _cairo_freelist_free (&device->cc_freelist, entry);
-}
-
-static void
-wm_kernels_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->wm_kernels, entry);
- _cairo_freelist_free (&device->wm_kernel_freelist, entry);
-}
-
-static void
-wm_states_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->wm_states, entry);
- _cairo_freelist_free (&device->wm_state_freelist, entry);
-}
-
-static void
-wm_bindings_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->wm_bindings, entry);
- _cairo_freelist_free (&device->wm_binding_freelist, entry);
-}
-
-static void
-samplers_pluck (void *entry, void *closure)
-{
- i965_device_t *device = closure;
-
- _cairo_hash_table_remove (device->samplers, entry);
- _cairo_freelist_free (&device->sampler_freelist, entry);
-}
-
-void
-i965_general_state_reset (i965_device_t *device)
-{
- _cairo_hash_table_foreach (device->sf_states,
- sf_states_pluck,
- device);
-
- _cairo_hash_table_foreach (device->cc_states,
- cc_offsets_pluck,
- device);
-
- _cairo_hash_table_foreach (device->wm_kernels,
- wm_kernels_pluck,
- device);
-
- _cairo_hash_table_foreach (device->wm_states,
- wm_states_pluck,
- device);
-
- _cairo_hash_table_foreach (device->wm_bindings,
- wm_bindings_pluck,
- device);
-
- _cairo_hash_table_foreach (device->samplers,
- samplers_pluck,
- device);
-
- device->vs_offset = (uint32_t) -1;
- device->border_color_offset = (uint32_t) -1;
-
- if (device->general_state != NULL) {
- intel_bo_destroy (&device->intel, device->general_state);
- device->general_state = NULL;
- }
-}
-
-static void
-i965_device_reset (i965_device_t *device)
-{
- device->exec.count = 0;
- device->exec.gtt_size = I965_VERTEX_SIZE +
- I965_SURFACE_SIZE +
- I965_GENERAL_SIZE +
- I965_BATCH_SIZE;
-
- device->sf_state.entry.hash = (uint32_t) -1;
- device->wm_state.entry.hash = (uint32_t) -1;
- device->wm_binding.entry.hash = (uint32_t) -1;
- device->cc_state.entry.hash = (uint32_t) -1;
-
- device->target = NULL;
- device->source = NULL;
- device->mask = NULL;
- device->clip = NULL;
-
- device->draw_rectangle = (uint32_t) -1;
-
- device->vertex_type = (uint32_t) -1;
- device->vertex_size = 0;
- device->rectangle_size = 0;
- device->last_vertex_size = 0;
-
- device->constants = NULL;
- device->constants_size = 0;
-
- device->have_urb_fences = FALSE;
-}
-
-static cairo_status_t
-i965_exec (i965_device_t *device, uint32_t offset)
-{
- struct drm_i915_gem_execbuffer2 execbuf;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- int ret, i;
-
- execbuf.buffers_ptr = (uintptr_t) device->exec.exec;
- execbuf.buffer_count = device->exec.count;
- execbuf.batch_start_offset = offset;
- execbuf.batch_len = device->batch.used;
- execbuf.DR1 = 0;
- execbuf.DR4 = 0;
- execbuf.num_cliprects = 0;
- execbuf.cliprects_ptr = 0;
- execbuf.flags = I915_GEM_3D_PIPELINE;
- execbuf.rsvd1 = 0;
- execbuf.rsvd2 = 0;
-
-#if 0
- printf ("exec: offset=%d, length=%d, buffers=%d\n",
- offset, device->batch.used, device->exec.count);
- intel_dump_batchbuffer ((uint32_t *) device->batch.data,
- device->batch.used,
- device->intel.base.chip_id);
-#endif
-
- ret = 0;
- do {
- ret = ioctl (device->intel.base.fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf);
- } while (ret != 0 && errno == EINTR);
- if (unlikely (ret)) {
- if (errno == ENOMEM)
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- else
- status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
-
- fprintf (stderr, "Batch submission failed: %d\n", errno);
- fprintf (stderr, " gtt size: %zd/%zd\n",
- device->exec.gtt_size, device->intel.gtt_avail_size);
-
- fprintf (stderr, " %d buffers:\n",
- device->exec.count);
- for (i = 0; i < device->exec.count; i++) {
- fprintf (stderr, " exec[%d] = %d\n",
- i, device->exec.bo[i]->base.size);
- }
-
- intel_dump_batchbuffer ((uint32_t *) device->batch.data,
- device->batch.used,
- device->intel.base.chip_id);
- }
-
- /* XXX any write target within the batch should now be in error */
- for (i = 0; i < device->exec.count; i++) {
- intel_bo_t *bo = device->exec.bo[i];
- cairo_bool_t ret;
-
- bo->offset = device->exec.exec[i].offset;
- bo->exec = NULL;
- bo->batch_read_domains = 0;
- bo->batch_write_domain = 0;
-
- if (bo->virtual)
- intel_bo_unmap (bo);
- bo->cpu = FALSE;
-
- if (bo->purgeable)
- ret = intel_bo_madvise (&device->intel, bo, I915_MADV_DONTNEED);
- /* ignore immediate notification of purging */
-
- cairo_list_del (&bo->cache_list);
- cairo_list_init (&bo->link);
- intel_bo_destroy (&device->intel, bo);
- }
- cairo_list_init (&device->flush);
-
- device->exec.count = 0;
-
- return status;
-}
-
-static inline uint32_t
-next_bo_size (uint32_t v)
-{
- v = (v + 8191) / 8192;
-
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
-
- return v * 8192;
-}
-
-static void
-_copy_to_bo_and_apply_relocations (i965_device_t *device,
- intel_bo_t *bo,
- i965_stream_t *stream,
- uint32_t offset)
-{
- int n;
-
- intel_bo_write (&device->intel, bo,
- offset, stream->used,
- stream->data);
-
- for (n = 0; n < stream->num_pending_relocations; n++) {
- struct i965_pending_relocation *p = &stream->pending_relocations[n];
-
- i965_emit_relocation (device, &device->batch, bo,
- p->delta + offset,
- p->read_domains,
- p->write_domain,
- p->offset);
-
- if (bo->offset) {
- *(uint32_t *) (device->batch.data + p->offset) =
- bo->offset + p->delta + offset;
- }
- }
-}
-
-cairo_status_t
-i965_device_flush (i965_device_t *device)
-{
- cairo_status_t status;
- uint32_t aligned, max;
- intel_bo_t *bo;
- int n;
-
- if (device->batch.used == 0)
- return CAIRO_STATUS_SUCCESS;
-
- i965_flush_vertices (device);
-
- OUT_BATCH (MI_BATCH_BUFFER_END);
- /* Emit a padding dword if we aren't going to be quad-word aligned. */
- if (device->batch.used & 4)
- OUT_BATCH (MI_NOOP);
-
-#if 0
- printf ("device flush: vertex=%d, constant=%d, surface=%d, general=%d, batch=%d\n",
- device->vertex.used,
- device->constant.used,
- device->surface.used,
- device->general.used,
- device->batch.used);
-#endif
-
- /* can we pack the surface state into the tail of the general state? */
- if (device->general.used == device->general.committed) {
- if (device->general.used) {
- assert (device->general.num_pending_relocations == 1);
- assert (device->general_state != NULL);
- i965_emit_relocation (device, &device->batch,
- device->general_state,
- device->general.pending_relocations[0].delta,
- device->general.pending_relocations[0].read_domains,
- device->general.pending_relocations[0].write_domain,
- device->general.pending_relocations[0].offset);
-
- if (device->general_state->offset) {
- *(uint32_t *) (device->batch.data +
- device->general.pending_relocations[0].offset) =
- device->general_state->offset +
- device->general.pending_relocations[0].delta;
- }
- }
- } else {
- assert (device->general.num_pending_relocations == 1);
- if (device->general_state != NULL) {
- intel_bo_destroy (&device->intel, device->general_state);
- device->general_state = NULL;
- }
-
- bo = intel_bo_create (&device->intel,
- device->general.used,
- device->general.used,
- FALSE, I915_TILING_NONE, 0);
- if (unlikely (bo == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- aligned = (device->general.used + 31) & -32;
- if (device->surface.used &&
- aligned + device->surface.used <= bo->base.size)
- {
- _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0);
- _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
-
- if (device->surface.num_relocations) {
- for (n = 0; n < device->surface.num_relocations; n++)
- device->surface.relocations[n].offset += aligned;
-
- assert (bo->exec != NULL);
- bo->exec->relocs_ptr = (uintptr_t) device->surface.relocations;
- bo->exec->relocation_count = device->surface.num_relocations;
- }
-
- i965_stream_reset (&device->surface);
- }
- else
- {
- _copy_to_bo_and_apply_relocations (device, bo, &device->general, 0);
- }
-
- /* Note we don't reset the general state, just mark what data we've committed. */
- device->general.committed = device->general.used;
- device->general_state = bo;
- }
- device->general.num_pending_relocations = 0;
-
- /* Combine vertex+constant+surface+batch streams? */
- max = aligned = device->vertex.used;
- if (device->surface.used) {
- aligned = (aligned + 63) & -64;
- aligned += device->surface.used;
- if (device->surface.used > max)
- max = device->surface.used;
- }
- aligned = (aligned + 63) & -64;
- aligned += device->batch.used;
- if (device->batch.used > max)
- max = device->batch.used;
- if (aligned <= next_bo_size (max)) {
- int batch_num_relocations;
-
- if (aligned <= 8192)
- max = aligned;
-
- bo = intel_bo_create (&device->intel,
- max, max,
- FALSE, I915_TILING_NONE, 0);
- if (unlikely (bo == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- assert (aligned <= bo->base.size);
-
- if (device->vertex.used)
- _copy_to_bo_and_apply_relocations (device, bo, &device->vertex, 0);
-
- aligned = device->vertex.used;
-
- batch_num_relocations = device->batch.num_relocations;
- if (device->surface.used) {
- aligned = (aligned + 63) & -64;
- _copy_to_bo_and_apply_relocations (device, bo, &device->surface, aligned);
-
- batch_num_relocations = device->batch.num_relocations;
- if (device->surface.num_relocations) {
- assert (device->batch.num_relocations + device->surface.num_relocations < device->batch.max_relocations);
-
- memcpy (device->batch.relocations + device->batch.num_relocations,
- device->surface.relocations,
- sizeof (device->surface.relocations[0]) * device->surface.num_relocations);
-
- for (n = 0; n < device->surface.num_relocations; n++)
- device->batch.relocations[device->batch.num_relocations + n].offset += aligned;
-
- device->batch.num_relocations += device->surface.num_relocations;
- }
-
- aligned += device->surface.used;
- }
-
- aligned = (aligned + 63) & -64;
- intel_bo_write (&device->intel, bo,
- aligned, device->batch.used,
- device->batch.data);
-
- for (n = 0; n < batch_num_relocations; n++)
- device->batch.relocations[n].offset += aligned;
-
- if (device->exec.bo[device->exec.count-1] == bo) {
- assert (bo->exec == &device->exec.exec[device->exec.count-1]);
-
- bo->exec->relocation_count = device->batch.num_relocations;
- bo->exec->relocs_ptr = (uintptr_t) device->batch.relocations;
- intel_bo_destroy (&device->intel, bo);
- } else {
- assert (bo->exec == NULL);
-
- n = device->exec.count++;
- device->exec.exec[n].handle = bo->base.handle;
- device->exec.exec[n].relocation_count = device->batch.num_relocations;
- device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations;
- device->exec.exec[n].alignment = 0;
- device->exec.exec[n].offset = 0;
- device->exec.exec[n].flags = 0;
- device->exec.exec[n].rsvd1 = 0;
- device->exec.exec[n].rsvd2 = 0;
-
- /* transfer ownership to the exec */
- device->exec.bo[n] = bo;
- }
- } else {
- i965_stream_commit (device, &device->vertex);
- if (device->surface.used)
- i965_stream_commit (device, &device->surface);
-
- bo = intel_bo_create (&device->intel,
- device->batch.used, device->batch.used,
- FALSE, I915_TILING_NONE, 0);
- if (unlikely (bo == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- intel_bo_write (&device->intel, bo,
- 0, device->batch.used,
- device->batch.data);
-
- n = device->exec.count++;
- device->exec.exec[n].handle = bo->base.handle;
- device->exec.exec[n].relocation_count = device->batch.num_relocations;
- device->exec.exec[n].relocs_ptr = (uintptr_t) device->batch.relocations;
- device->exec.exec[n].alignment = 0;
- device->exec.exec[n].offset = 0;
- device->exec.exec[n].flags = 0;
- device->exec.exec[n].rsvd1 = 0;
- device->exec.exec[n].rsvd2 = 0;
-
- /* transfer ownership to the exec */
- device->exec.bo[n] = bo;
- aligned = 0;
- }
-
- status = i965_exec (device, aligned);
-
- i965_stream_reset (&device->vertex);
- i965_stream_reset (&device->surface);
- i965_stream_reset (&device->batch);
-
- intel_glyph_cache_unpin (&device->intel);
- intel_snapshot_cache_thaw (&device->intel);
-
- i965_device_reset (device);
-
- return status;
-}
-
-static cairo_surface_t *
-i965_surface_create_similar (void *abstract_other,
- cairo_content_t content,
- int width, int height)
-{
- i965_surface_t *other;
- cairo_format_t format;
-
- if (width > 8192 || height > 8192)
- return NULL;
-
- other = abstract_other;
- if (content == other->intel.drm.base.content)
- format = other->intel.drm.format;
- else
- format = _cairo_format_from_content (content);
-
- return i965_surface_create_internal ((cairo_drm_device_t *) other->intel.drm.base.device,
- format,
- width, height,
- I965_TILING_DEFAULT, TRUE);
-}
-
-static cairo_status_t
-i965_surface_finish (void *abstract_surface)
-{
- i965_surface_t *surface = abstract_surface;
-
- return intel_surface_finish (&surface->intel);
-}
-
-static cairo_status_t
-i965_surface_flush (void *abstract_surface, unsigned flags)
-{
- i965_surface_t *surface = abstract_surface;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
-
- if (flags)
- return CAIRO_STATUS_SUCCESS;
-
- if (surface->intel.drm.fallback != NULL)
- return intel_surface_flush (abstract_surface);
-
- /* Forgo flushing on finish as the user cannot access the surface directly. */
- if (! surface->intel.drm.base.finished &&
- to_intel_bo (surface->intel.drm.bo)->exec != NULL)
- {
- status = cairo_device_acquire (surface->intel.drm.base.device);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- i965_device_t *device;
-
- device = i965_device (surface);
- status = i965_device_flush (device);
- cairo_device_release (&device->intel.base.base);
- }
- }
-
- return status;
-}
-
-/* rasterisation */
-
-static cairo_status_t
-_composite_boxes_spans (void *closure,
- cairo_span_renderer_t *renderer,
- const cairo_rectangle_int_t *extents)
-{
- cairo_boxes_t *boxes = closure;
- cairo_rectangular_scan_converter_t converter;
- struct _cairo_boxes_chunk *chunk;
- cairo_status_t status;
-
- _cairo_rectangular_scan_converter_init (&converter, extents);
- for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
- cairo_box_t *box = chunk->base;
- int i;
-
- for (i = 0; i < chunk->count; i++) {
- status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
- if (unlikely (status))
- goto CLEANUP;
- }
- }
-
- status = converter.base.generate (&converter.base, renderer);
-
- CLEANUP:
- converter.base.destroy (&converter.base);
- return status;
-}
-
-cairo_status_t
-i965_fixup_unbounded (i965_surface_t *dst,
- const cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
-{
- i965_shader_t shader;
- i965_device_t *device;
- cairo_status_t status;
-
- i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR);
-
- if (clip != NULL) {
- cairo_region_t *clip_region = NULL;
-
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
- assert (clip_region == NULL);
-
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- i965_shader_set_clip (&shader, clip);
- } else {
- if (extents->bounded.width == extents->unbounded.width &&
- extents->bounded.height == extents->unbounded.height)
- {
- return CAIRO_STATUS_SUCCESS;
- }
- }
-
- status = i965_shader_acquire_pattern (&shader,
- &shader.source,
- &_cairo_pattern_clear.base,
- &extents->unbounded);
- if (unlikely (status)) {
- i965_shader_fini (&shader);
- return status;
- }
-
- device = i965_device (dst);
- status = cairo_device_acquire (&device->intel.base.base);
- if (unlikely (status))
- return status;
-
- status = i965_shader_commit (&shader, device);
- if (unlikely (status)) {
- goto BAIL;
- }
-
- if (extents->bounded.width == 0 || extents->bounded.height == 0) {
- i965_shader_add_rectangle (&shader,
- extents->unbounded.x,
- extents->unbounded.y,
- extents->unbounded.width,
- extents->unbounded.height);
- } else { /* top */
- if (extents->bounded.y != extents->unbounded.y) {
- cairo_rectangle_int_t rect;
-
- rect.x = extents->unbounded.x;
- rect.y = extents->unbounded.y;
- rect.width = extents->unbounded.width;
- rect.height = extents->bounded.y - rect.y;
-
- i965_shader_add_rectangle (&shader,
- rect.x, rect.y,
- rect.width, rect.height);
- }
-
- /* left */
- if (extents->bounded.x != extents->unbounded.x) {
- cairo_rectangle_int_t rect;
-
- rect.x = extents->unbounded.x;
- rect.y = extents->bounded.y;
- rect.width = extents->bounded.x - extents->unbounded.x;
- rect.height = extents->bounded.height;
-
- i965_shader_add_rectangle (&shader,
- rect.x, rect.y,
- rect.width, rect.height);
- }
-
- /* right */
- if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
- cairo_rectangle_int_t rect;
-
- rect.x = extents->bounded.x + extents->bounded.width;
- rect.y = extents->bounded.y;
- rect.width = extents->unbounded.x + extents->unbounded.width - rect.x;
- rect.height = extents->bounded.height;
-
- i965_shader_add_rectangle (&shader,
- rect.x, rect.y,
- rect.width, rect.height);
- }
-
- /* bottom */
- if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
- cairo_rectangle_int_t rect;
-
- rect.x = extents->unbounded.x;
- rect.y = extents->bounded.y + extents->bounded.height;
- rect.width = extents->unbounded.width;
- rect.height = extents->unbounded.y + extents->unbounded.height - rect.y;
-
- i965_shader_add_rectangle (&shader,
- rect.x, rect.y,
- rect.width, rect.height);
- }
- }
-
- i965_shader_fini (&shader);
- BAIL:
- cairo_device_release (&device->intel.base.base);
- return status;
-}
-
-static cairo_status_t
-i965_fixup_unbounded_boxes (i965_surface_t *dst,
- const cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip,
- cairo_boxes_t *boxes)
-{
- cairo_boxes_t clear;
- cairo_box_t box;
- cairo_region_t *clip_region = NULL;
- cairo_status_t status;
- struct _cairo_boxes_chunk *chunk;
- i965_shader_t shader;
- int i;
-
- if (boxes->num_boxes <= 1)
- return i965_fixup_unbounded (dst, extents, clip);
-
- i965_shader_init (&shader, dst, CAIRO_OPERATOR_CLEAR);
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
- if (status == CAIRO_INT_STATUS_UNSUPPORTED)
- i965_shader_set_clip (&shader, clip);
- }
-
- status = i965_shader_acquire_pattern (&shader,
- &shader.source,
- &_cairo_pattern_clear.base,
- &extents->unbounded);
- if (unlikely (status)) {
- i965_shader_fini (&shader);
- return status;
- }
-
- _cairo_boxes_init (&clear);
-
- box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
- box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
- box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
- box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
-
- if (clip_region == NULL) {
- cairo_boxes_t tmp;
-
- _cairo_boxes_init (&tmp);
-
- status = _cairo_boxes_add (&tmp, &box);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- tmp.chunks.next = &boxes->chunks;
- tmp.num_boxes += boxes->num_boxes;
-
- status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
- CAIRO_FILL_RULE_WINDING,
- &clear);
-
- tmp.chunks.next = NULL;
- } else {
- pixman_box32_t *pbox;
-
- pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
- _cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
-
- status = _cairo_boxes_add (&clear, &box);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
- for (i = 0; i < chunk->count; i++) {
- status = _cairo_boxes_add (&clear, &chunk->base[i]);
- if (unlikely (status)) {
- _cairo_boxes_fini (&clear);
- return status;
- }
- }
- }
-
- status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
- CAIRO_FILL_RULE_WINDING,
- &clear);
- }
-
- if (likely (status == CAIRO_STATUS_SUCCESS && clear.num_boxes)) {
- i965_device_t *device;
-
- device = i965_device (dst);
- status = cairo_device_acquire (&device->intel.base.base);
- if (unlikely (status))
- goto err_shader;
-
- status = i965_shader_commit (&shader, device);
- if (unlikely (status))
- goto err_device;
-
- for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
- for (i = 0; i < chunk->count; i++) {
- int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
- int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
- int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
- int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
-
- i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
- }
- }
-
-err_device:
- cairo_device_release (&device->intel.base.base);
-err_shader:
- i965_shader_fini (&shader);
- }
-
- _cairo_boxes_fini (&clear);
-
- return status;
-}
-
-static cairo_status_t
-_composite_boxes (i965_surface_t *dst,
- cairo_operator_t op,
- const cairo_pattern_t *pattern,
- cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- cairo_clip_t *clip,
- const cairo_composite_rectangles_t *extents)
-{
- cairo_bool_t need_clip_surface = FALSE;
- cairo_region_t *clip_region = NULL;
- const struct _cairo_boxes_chunk *chunk;
- cairo_status_t status;
- i965_shader_t shader;
- i965_device_t *device;
- int i;
-
- /* If the boxes are not pixel-aligned, we will need to compute a real mask */
- if (antialias != CAIRO_ANTIALIAS_NONE) {
- if (! boxes->is_pixel_aligned)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- i965_shader_init (&shader, dst, op);
-
- status = i965_shader_acquire_pattern (&shader,
- &shader.source,
- pattern,
- &extents->bounded);
- if (unlikely (status))
- return status;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- if (need_clip_surface)
- i965_shader_set_clip (&shader, clip);
- }
-
- device = i965_device (dst);
- status = cairo_device_acquire (&device->intel.base.base);
- if (unlikely (status))
- goto err_shader;
-
- status = i965_shader_commit (&shader, i965_device (dst));
- if (unlikely (status))
- goto err_device;
-
- for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
- cairo_box_t *box = chunk->base;
- for (i = 0; i < chunk->count; i++) {
- int x1 = _cairo_fixed_integer_round (box[i].p1.x);
- int y1 = _cairo_fixed_integer_round (box[i].p1.y);
- int x2 = _cairo_fixed_integer_round (box[i].p2.x);
- int y2 = _cairo_fixed_integer_round (box[i].p2.y);
-
- if (x2 > x1 && y2 > y1)
- i965_shader_add_rectangle (&shader, x1, y1, x2 - x1, y2 - y1);
- }
- }
-
- if (! extents->is_bounded)
- status = i965_fixup_unbounded_boxes (dst, extents, clip, boxes);
-
- err_device:
- cairo_device_release (&device->intel.base.base);
- err_shader:
- i965_shader_fini (&shader);
-
- return status;
-}
-
-static cairo_status_t
-_clip_and_composite_boxes (i965_surface_t *dst,
- cairo_operator_t op,
- const cairo_pattern_t *src,
- cairo_boxes_t *boxes,
- cairo_antialias_t antialias,
- const cairo_composite_rectangles_t *extents,
- cairo_clip_t *clip)
-{
- cairo_status_t status;
-
- if (boxes->num_boxes == 0) {
- if (extents->is_bounded)
- return CAIRO_STATUS_SUCCESS;
-
- return i965_fixup_unbounded (dst, extents, clip);
- }
-
- /* Use a fast path if the boxes are pixel aligned */
- status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- /* Otherwise render the boxes via an implicit mask and composite in the usual
- * fashion.
- */
- return i965_clip_and_composite_spans (dst, op, src, antialias,
- _composite_boxes_spans, boxes,
- extents, clip);
-}
-
-static cairo_int_status_t
-i965_surface_paint (void *abstract_dst,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_clip_t *clip)
-{
- i965_surface_t *dst = abstract_dst;
- cairo_composite_rectangles_t extents;
- cairo_boxes_t boxes;
- cairo_box_t *clip_boxes = boxes.boxes_embedded;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- int num_boxes = ARRAY_LENGTH (boxes.boxes_embedded);
- cairo_status_t status;
-
- /* XXX unsupported operators? use pixel shader blending, eventually */
-
- status = _cairo_composite_rectangles_init_for_paint (&extents,
- dst->intel.drm.width,
- dst->intel.drm.height,
- op, source,
- clip);
- if (unlikely (status))
- return status;
-
- if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- _cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
- status = _clip_and_composite_boxes (dst, op, source,
- &boxes, CAIRO_ANTIALIAS_DEFAULT,
- &extents, clip);
- if (clip_boxes != boxes.boxes_embedded)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-i965_surface_mask (void *abstract_dst,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- cairo_clip_t *clip)
-{
- i965_surface_t *dst = abstract_dst;
- cairo_composite_rectangles_t extents;
- i965_shader_t shader;
- i965_device_t *device;
- cairo_clip_t local_clip;
- cairo_region_t *clip_region = NULL;
- cairo_bool_t need_clip_surface = FALSE;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
-
- status = _cairo_composite_rectangles_init_for_mask (&extents,
- dst->intel.drm.width,
- dst->intel.drm.height,
- op, source, mask, clip);
- if (unlikely (status))
- return status;
-
- if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL && extents.is_bounded) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- status = _cairo_clip_rectangle (clip, &extents.bounded);
- if (unlikely (status)) {
- _cairo_clip_fini (&local_clip);
- return status;
- }
-
- have_clip = TRUE;
- }
-
- i965_shader_init (&shader, dst, op);
-
- status = i965_shader_acquire_pattern (&shader,
- &shader.source,
- source,
- &extents.bounded);
- if (unlikely (status))
- goto err_shader;
-
- status = i965_shader_acquire_pattern (&shader,
- &shader.mask,
- mask,
- &extents.bounded);
- if (unlikely (status))
- goto err_shader;
-
- if (clip != NULL) {
- status = _cairo_clip_get_region (clip, &clip_region);
- assert (status == CAIRO_STATUS_SUCCESS || CAIRO_INT_STATUS_UNSUPPORTED);
- need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
- if (need_clip_surface)
- i965_shader_set_clip (&shader, clip);
- }
-
- device = i965_device (dst);
- status = cairo_device_acquire (&device->intel.base.base);
- if (unlikely (status))
- goto err_shader;
-
- status = i965_shader_commit (&shader, device);
- if (unlikely (status))
- goto err_device;
-
- if (clip_region != NULL) {
- unsigned int n, num_rectangles;
-
- num_rectangles = cairo_region_num_rectangles (clip_region);
- for (n = 0; n < num_rectangles; n++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (clip_region, n, &rect);
-
- i965_shader_add_rectangle (&shader,
- rect.x, rect.y,
- rect.width, rect.height);
- }
- } else {
- i965_shader_add_rectangle (&shader,
- extents.bounded.x,
- extents.bounded.y,
- extents.bounded.width,
- extents.bounded.height);
- }
-
- if (! extents.is_bounded)
- status = i965_fixup_unbounded (dst, &extents, clip);
-
- err_device:
- cairo_device_release (&device->intel.base.base);
- err_shader:
- i965_shader_fini (&shader);
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
-}
-
-typedef struct {
- cairo_polygon_t polygon;
- cairo_fill_rule_t fill_rule;
- cairo_antialias_t antialias;
-} composite_polygon_info_t;
-
-static cairo_status_t
-_composite_polygon_spans (void *closure,
- cairo_span_renderer_t *renderer,
- const cairo_rectangle_int_t *extents)
-{
- composite_polygon_info_t *info = closure;
- cairo_botor_scan_converter_t converter;
- cairo_status_t status;
- cairo_box_t box;
-
- box.p1.x = _cairo_fixed_from_int (extents->x);
- box.p1.y = _cairo_fixed_from_int (extents->y);
- box.p2.x = _cairo_fixed_from_int (extents->x + extents->width);
- box.p2.y = _cairo_fixed_from_int (extents->y + extents->height);
-
- _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule);
-
- status = converter.base.add_polygon (&converter.base, &info->polygon);
- if (likely (status == CAIRO_STATUS_SUCCESS))
- status = converter.base.generate (&converter.base, renderer);
-
- converter.base.destroy (&converter.base);
-
- return status;
-}
-
-static cairo_int_status_t
-i965_surface_stroke (void *abstract_dst,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- const cairo_stroke_style_t *stroke_style,
- const cairo_matrix_t *ctm,
- const cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip)
-{
- i965_surface_t *dst = abstract_dst;
- cairo_composite_rectangles_t extents;
- composite_polygon_info_t info;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- cairo_status_t status;
-
- status = _cairo_composite_rectangles_init_for_stroke (&extents,
- dst->intel.drm.width,
- dst->intel.drm.height,
- op, source,
- path, stroke_style, ctm,
- clip);
- if (unlikely (status))
- return status;
-
- if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
- cairo_boxes_t boxes;
-
- _cairo_boxes_init (&boxes);
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
- status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
- stroke_style,
- ctm,
- &boxes);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- status = _clip_and_composite_boxes (dst, op, source,
- &boxes, antialias,
- &extents, clip);
- }
-
- _cairo_boxes_fini (&boxes);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto CLEANUP_BOXES;
- }
-
- _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
-
- status = _cairo_path_fixed_stroke_to_polygon (path,
- stroke_style,
- ctm, ctm_inverse,
- tolerance,
- &info.polygon);
- if (unlikely (status))
- goto CLEANUP_POLYGON;
-
- if (extents.is_bounded) {
- cairo_rectangle_int_t rect;
-
- _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
- if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
- goto CLEANUP_POLYGON;
- }
-
- if (info.polygon.num_edges == 0) {
- if (! extents.is_bounded)
- status = i965_fixup_unbounded (dst, &extents, clip);
- } else {
- info.fill_rule = CAIRO_FILL_RULE_WINDING;
- info.antialias = antialias;
- status = i965_clip_and_composite_spans (dst, op, source, antialias,
- _composite_polygon_spans, &info,
- &extents, clip);
- }
-
-CLEANUP_POLYGON:
- _cairo_polygon_fini (&info.polygon);
-
-CLEANUP_BOXES:
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-i965_surface_fill (void *abstract_dst,
- cairo_operator_t op,
- const cairo_pattern_t*source,
- cairo_path_fixed_t *path,
- cairo_fill_rule_t fill_rule,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip)
-{
- i965_surface_t *dst = abstract_dst;
- cairo_composite_rectangles_t extents;
- composite_polygon_info_t info;
- cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
- cairo_clip_t local_clip;
- cairo_bool_t have_clip = FALSE;
- int num_boxes = ARRAY_LENGTH (boxes_stack);
- cairo_status_t status;
-
- status = _cairo_composite_rectangles_init_for_fill (&extents,
- dst->intel.drm.width,
- dst->intel.drm.height,
- op, source, path,
- clip);
- if (unlikely (status))
- return status;
-
- if (clip != NULL && _cairo_clip_contains_extents (clip, &extents))
- clip = NULL;
-
- if (clip != NULL) {
- clip = _cairo_clip_init_copy (&local_clip, clip);
- have_clip = TRUE;
- }
-
- status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
- if (unlikely (status)) {
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
- }
-
- assert (! _cairo_path_fixed_fill_is_empty (path));
-
- if (_cairo_path_fixed_fill_is_rectilinear (path)) {
- cairo_boxes_t boxes;
-
- _cairo_boxes_init (&boxes);
- _cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
- status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
- fill_rule,
- &boxes);
- if (likely (status == CAIRO_STATUS_SUCCESS)) {
- status = _clip_and_composite_boxes (dst, op, source,
- &boxes, antialias,
- &extents, clip);
- }
-
- _cairo_boxes_fini (&boxes);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto CLEANUP_BOXES;
- }
-
- _cairo_polygon_init (&info.polygon, clip_boxes, num_boxes);
-
- status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &info.polygon);
- if (unlikely (status))
- goto CLEANUP_POLYGON;
-
- if (extents.is_bounded) {
- cairo_rectangle_int_t rect;
-
- _cairo_box_round_to_rectangle (&info.polygon.extents, &rect);
- if (! _cairo_rectangle_intersect (&extents.bounded, &rect))
- goto CLEANUP_POLYGON;
- }
-
- if (info.polygon.num_edges == 0) {
- if (! extents.is_bounded)
- status = i965_fixup_unbounded (dst, &extents, clip);
- } else {
- info.fill_rule = fill_rule;
- info.antialias = antialias;
- status = i965_clip_and_composite_spans (dst, op, source, antialias,
- _composite_polygon_spans, &info,
- &extents, clip);
- }
-
-CLEANUP_POLYGON:
- _cairo_polygon_fini (&info.polygon);
-
-CLEANUP_BOXES:
- if (clip_boxes != boxes_stack)
- free (clip_boxes);
-
- if (have_clip)
- _cairo_clip_fini (&local_clip);
-
- return status;
-}
-
-static const cairo_surface_backend_t i965_surface_backend = {
- CAIRO_SURFACE_TYPE_DRM,
- _cairo_default_context_create,
-
- i965_surface_create_similar,
- i965_surface_finish,
-
- NULL,
- intel_surface_acquire_source_image,
- intel_surface_release_source_image,
-
- NULL, NULL, NULL,
- NULL, /* composite */
- NULL, /* fill */
- NULL, /* trapezoids */
- NULL, /* span */
- NULL, /* check-span */
-
- NULL, /* copy_page */
- NULL, /* show_page */
- _cairo_drm_surface_get_extents,
- NULL, /* old-glyphs */
- _cairo_drm_surface_get_font_options,
-
- i965_surface_flush,
- NULL, /* mark_dirty */
- intel_scaled_font_fini,
- intel_scaled_glyph_fini,
-
- i965_surface_paint,
- i965_surface_mask,
- i965_surface_stroke,
- i965_surface_fill,
- i965_surface_glyphs,
-};
-
-static void
-i965_surface_init (i965_surface_t *surface,
- cairo_drm_device_t *device,
- cairo_format_t format,
- int width, int height)
-{
- intel_surface_init (&surface->intel, &i965_surface_backend, device,
- format, width, height);
- surface->stream = 0;
-}
-
-static inline int cairo_const
-i965_tiling_stride (uint32_t tiling, int stride)
-{
- if (tiling == I915_TILING_NONE)
- return stride;
-
- return (stride + 127) & -128;
-}
-
-static inline int cairo_const
-i965_tiling_height (uint32_t tiling, int height)
-{
- switch (tiling) {
- default:
- case I915_TILING_NONE: return (height + 1) & -2;
- case I915_TILING_X: return (height + 7) & -8;
- case I915_TILING_Y: return (height + 31) & -32;
- }
-}
-
-cairo_surface_t *
-i965_surface_create_internal (cairo_drm_device_t *base_dev,
- cairo_format_t format,
- int width, int height,
- uint32_t tiling,
- cairo_bool_t gpu_target)
-{
- i965_surface_t *surface;
- cairo_status_t status_ignored;
-
- surface = _cairo_malloc (sizeof (i965_surface_t));
- if (unlikely (surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- i965_surface_init (surface, base_dev, format, width, height);
-
- if (width && height) {
- uint32_t size, stride;
- intel_bo_t *bo;
-
- width = (width + 3) & -4;
- stride = cairo_format_stride_for_width (surface->intel.drm.format, width);
- stride = (stride + 63) & ~63;
- stride = i965_tiling_stride (tiling, stride);
- surface->intel.drm.stride = stride;
-
- height = i965_tiling_height (tiling, height);
- assert (height <= I965_MAX_SIZE);
-
- size = stride * height;
- bo = intel_bo_create (to_intel_device (&base_dev->base),
- size, size,
- gpu_target, tiling, stride);
- if (bo == NULL) {
- status_ignored = _cairo_drm_surface_finish (&surface->intel.drm);
- free (surface);
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- bo->tiling = tiling;
- bo->stride = stride;
- surface->intel.drm.bo = &bo->base;
-
- assert (bo->base.size >= (size_t) stride*height);
- }
-
- return &surface->intel.drm.base;
-}
-
-static cairo_surface_t *
-i965_surface_create (cairo_drm_device_t *device,
- cairo_format_t format, int width, int height)
-{
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_A8:
- break;
- case CAIRO_FORMAT_INVALID:
- default:
- case CAIRO_FORMAT_A1:
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
- }
-
- return i965_surface_create_internal (device, format, width, height,
- I965_TILING_DEFAULT, TRUE);
-}
-
-static cairo_surface_t *
-i965_surface_create_for_name (cairo_drm_device_t *base_dev,
- unsigned int name,
- cairo_format_t format,
- int width, int height, int stride)
-{
- i965_device_t *device;
- i965_surface_t *surface;
- cairo_status_t status_ignored;
- int min_stride;
-
- min_stride = cairo_format_stride_for_width (format, (width + 3) & -4);
- if (stride < min_stride || stride & 63)
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
-
- if (format == CAIRO_FORMAT_A1)
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
-
- switch (format) {
- case CAIRO_FORMAT_ARGB32:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_A8:
- break;
- case CAIRO_FORMAT_INVALID:
- default:
- case CAIRO_FORMAT_A1:
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
- }
-
- surface = _cairo_malloc (sizeof (i965_surface_t));
- if (unlikely (surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- i965_surface_init (surface, base_dev, format, width, height);
-
- device = (i965_device_t *) base_dev;
- surface->intel.drm.bo = &intel_bo_create_for_name (&device->intel, name)->base;
- if (unlikely (surface->intel.drm.bo == NULL)) {
- status_ignored = _cairo_drm_surface_finish (&surface->intel.drm);
- free (surface);
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- surface->intel.drm.stride = stride;
-
- return &surface->intel.drm.base;
-}
-
-static cairo_status_t
-i965_surface_enable_scan_out (void *abstract_surface)
-{
- i965_surface_t *surface = abstract_surface;
- intel_bo_t *bo;
-
- if (unlikely (surface->intel.drm.bo == NULL))
- return _cairo_error (CAIRO_STATUS_INVALID_SIZE);
-
- bo = to_intel_bo (surface->intel.drm.bo);
- if (bo->tiling != I915_TILING_X) {
- i965_device_t *device = i965_device (surface);
- cairo_surface_pattern_t pattern;
- cairo_surface_t *clone;
- cairo_status_t status;
-
- clone = i965_surface_create_internal (&device->intel.base,
- surface->intel.drm.base.content,
- surface->intel.drm.width,
- surface->intel.drm.height,
- I915_TILING_X,
- TRUE);
- if (unlikely (clone->status))
- return clone->status;
-
- /* 2D blit? */
- _cairo_pattern_init_for_surface (&pattern, &surface->intel.drm.base);
- pattern.base.filter = CAIRO_FILTER_NEAREST;
-
- status = _cairo_surface_paint (clone,
- CAIRO_OPERATOR_SOURCE,
- &pattern.base,
- NULL);
-
- _cairo_pattern_fini (&pattern.base);
-
- if (unlikely (status)) {
- cairo_surface_destroy (clone);
- return status;
- }
-
- /* swap buffer objects */
- surface->intel.drm.bo = ((cairo_drm_surface_t *) clone)->bo;
- ((cairo_drm_surface_t *) clone)->bo = &bo->base;
- bo = to_intel_bo (surface->intel.drm.bo);
-
- cairo_surface_destroy (clone);
- }
-
- if (unlikely (bo->tiling == I915_TILING_Y))
- return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); /* XXX */
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_i965_device_flush (cairo_drm_device_t *device)
-{
- cairo_status_t status;
-
- if (unlikely (device->base.finished))
- return CAIRO_STATUS_SUCCESS;
-
- status = cairo_device_acquire (&device->base);
- if (likely (status == CAIRO_STATUS_SUCCESS))
- status = i965_device_flush ((i965_device_t *) device);
-
- cairo_device_release (&device->base);
-
- return status;
-}
-
-static cairo_int_status_t
-_i965_device_throttle (cairo_drm_device_t *device)
-{
- cairo_status_t status;
-
- status = cairo_device_acquire (&device->base);
- if (unlikely (status))
- return status;
-
- status = i965_device_flush ((i965_device_t *) device);
- intel_throttle ((intel_device_t *) device);
-
- cairo_device_release (&device->base);
-
- return status;
-}
-
-static void
-_i965_device_destroy (void *base)
-{
- i965_device_t *device = base;
-
- i965_device_reset (device);
- i965_general_state_reset (device);
-
- _cairo_hash_table_destroy (device->sf_states);
- _cairo_hash_table_destroy (device->samplers);
- _cairo_hash_table_destroy (device->cc_states);
- _cairo_hash_table_destroy (device->wm_kernels);
- _cairo_hash_table_destroy (device->wm_states);
- _cairo_hash_table_destroy (device->wm_bindings);
-
- _cairo_freelist_fini (&device->sf_freelist);
- _cairo_freelist_fini (&device->cc_freelist);
- _cairo_freelist_fini (&device->wm_kernel_freelist);
- _cairo_freelist_fini (&device->wm_state_freelist);
- _cairo_freelist_fini (&device->wm_binding_freelist);
- _cairo_freelist_fini (&device->sampler_freelist);
-
- intel_device_fini (&device->intel);
- free (device);
-}
-
-static cairo_bool_t
-hash_equal (const void *A, const void *B)
-{
- const cairo_hash_entry_t *a = A, *b = B;
- return a->hash == b->hash;
-}
-
-cairo_drm_device_t *
-_cairo_drm_i965_device_create (int fd, dev_t dev, int vendor_id, int chip_id)
-{
- i965_device_t *device;
- uint64_t gtt_size;
- cairo_status_t status;
-
- if (! intel_info (fd, &gtt_size))
- return NULL;
-
- device = _cairo_malloc (sizeof (i965_device_t));
- if (unlikely (device == NULL))
- return (cairo_drm_device_t *) _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
-
- status = intel_device_init (&device->intel, fd);
- if (unlikely (status))
- goto CLEANUP;
-
- device->is_g4x = IS_G4X (chip_id);
- //device->is_g5x = IS_G5X (chip_id);
-
- device->intel.base.surface.create = i965_surface_create;
- device->intel.base.surface.create_for_name = i965_surface_create_for_name;
- device->intel.base.surface.create_from_cacheable_image = NULL;
- device->intel.base.surface.enable_scan_out = i965_surface_enable_scan_out;
-
- device->intel.base.device.flush = _i965_device_flush;
- device->intel.base.device.throttle = _i965_device_throttle;
- device->intel.base.device.destroy = _i965_device_destroy;
-
- device->sf_states = _cairo_hash_table_create (i965_sf_state_equal);
- if (unlikely (device->sf_states == NULL))
- goto CLEANUP_INTEL;
-
- _cairo_freelist_init (&device->sf_freelist,
- sizeof (struct i965_sf_state));
-
-
- device->cc_states = _cairo_hash_table_create (i965_cc_state_equal);
- if (unlikely (device->cc_states == NULL))
- goto CLEANUP_SF;
-
- _cairo_freelist_init (&device->cc_freelist,
- sizeof (struct i965_cc_state));
-
-
- device->wm_kernels = _cairo_hash_table_create (hash_equal);
- if (unlikely (device->wm_kernels == NULL))
- goto CLEANUP_CC;
-
- _cairo_freelist_init (&device->wm_kernel_freelist,
- sizeof (struct i965_wm_kernel));
-
- device->wm_states = _cairo_hash_table_create (i965_wm_state_equal);
- if (unlikely (device->wm_states == NULL))
- goto CLEANUP_WM_KERNEL;
-
- _cairo_freelist_init (&device->wm_state_freelist,
- sizeof (struct i965_wm_state));
-
-
- device->wm_bindings = _cairo_hash_table_create (i965_wm_binding_equal);
- if (unlikely (device->wm_bindings == NULL))
- goto CLEANUP_WM_STATE;
-
- _cairo_freelist_init (&device->wm_binding_freelist,
- sizeof (struct i965_wm_binding));
-
- device->samplers = _cairo_hash_table_create (hash_equal);
- if (unlikely (device->samplers == NULL))
- goto CLEANUP_WM_BINDING;
-
- _cairo_freelist_init (&device->sampler_freelist,
- sizeof (struct i965_sampler));
-
- i965_stream_init (&device->batch,
- device->batch_base, sizeof (device->batch_base),
- NULL, 0,
- device->batch_relocations,
- ARRAY_LENGTH (device->batch_relocations));
-
- i965_stream_init (&device->surface,
- device->surface_base, sizeof (device->surface_base),
- device->surface_pending_relocations,
- ARRAY_LENGTH (device->surface_pending_relocations),
- device->surface_relocations,
- ARRAY_LENGTH (device->surface_relocations));
-
- i965_stream_init (&device->general,
- device->general_base, sizeof (device->general_base),
- device->general_pending_relocations,
- ARRAY_LENGTH (device->general_pending_relocations),
- NULL, 0);
-
- i965_stream_init (&device->vertex,
- device->vertex_base, sizeof (device->vertex_base),
- device->vertex_pending_relocations,
- ARRAY_LENGTH (device->vertex_pending_relocations),
- NULL, 0);
-
- cairo_list_init (&device->flush);
- i965_device_reset (device);
- device->vs_offset = (uint32_t) -1;
- device->border_color_offset = (uint32_t) -1;
- device->general_state = NULL;
-
- return _cairo_drm_device_init (&device->intel.base,
- fd, dev, vendor_id, chip_id,
- I965_MAX_SIZE);
-
- CLEANUP_WM_BINDING:
- _cairo_hash_table_destroy (device->wm_bindings);
- CLEANUP_WM_STATE:
- _cairo_hash_table_destroy (device->wm_states);
- CLEANUP_WM_KERNEL:
- _cairo_hash_table_destroy (device->wm_kernels);
- CLEANUP_CC:
- _cairo_hash_table_destroy (device->cc_states);
- CLEANUP_SF:
- _cairo_hash_table_destroy (device->sf_states);
- CLEANUP_INTEL:
- intel_device_fini (&device->intel);
- CLEANUP:
- free (device);
- return (cairo_drm_device_t *) _cairo_device_create_in_error (status);
-}