summaryrefslogtreecommitdiff
path: root/Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c')
-rw-r--r--Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c1459
1 files changed, 0 insertions, 1459 deletions
diff --git a/Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c b/Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c
deleted file mode 100644
index fa7d3eb9b28..00000000000
--- a/Build/source/libs/cairo/cairo-1.12.16/src/cairo-xlib-surface-shm.c
+++ /dev/null
@@ -1,1459 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2012 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 University of Southern
- * California.
- *
- * Contributor(s):
- * Chris Wilson <chris@chris-wilson.co.uk>
- */
-
-#include "cairoint.h"
-
-#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
-
-#include "cairo-xlib-private.h"
-#include "cairo-xlib-surface-private.h"
-
-#if !HAVE_X11_EXTENSIONS_XSHM_H || !(HAVE_X11_EXTENSIONS_SHMPROTO_H || HAVE_X11_EXTENSIONS_SHMSTR_H)
-void _cairo_xlib_display_init_shm (cairo_xlib_display_t *display) {}
-
-cairo_surface_t *
-_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
- cairo_bool_t overwrite)
-{
- return NULL;
-}
-
-cairo_int_status_t
-_cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface)
-{
- assert (!surface->fallback);
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_shm (cairo_xlib_surface_t *other,
- pixman_format_code_t format,
- int width, int height)
-{
- return NULL;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_shm__image (cairo_xlib_surface_t *surface,
- pixman_format_code_t format,
- int width, int height)
-{
- return NULL;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_similar_shm (void *other,
- cairo_format_t format,
- int width, int height)
-{
- return cairo_image_surface_create (format, width, height);
-}
-
-void
-_cairo_xlib_shm_surface_mark_active (cairo_surface_t *_shm)
-{
- ASSERT_NOT_REACHED;
-}
-
-void
-_cairo_xlib_shm_surface_get_ximage (cairo_surface_t *surface,
- XImage *ximage)
-{
- ASSERT_NOT_REACHED;
-}
-
-void *
-_cairo_xlib_shm_surface_get_obdata (cairo_surface_t *surface)
-{
- ASSERT_NOT_REACHED;
- return NULL;
-}
-
-Pixmap
-_cairo_xlib_shm_surface_get_pixmap (cairo_surface_t *surface)
-{
- ASSERT_NOT_REACHED;
- return 0;
-}
-
-XRenderPictFormat *
-_cairo_xlib_shm_surface_get_xrender_format (cairo_surface_t *surface)
-{
- ASSERT_NOT_REACHED;
- return NULL;
-}
-
-cairo_bool_t
-_cairo_xlib_shm_surface_is_active (cairo_surface_t *surface)
-{
- ASSERT_NOT_REACHED;
- return FALSE;
-}
-
-cairo_bool_t
-_cairo_xlib_shm_surface_is_idle (cairo_surface_t *surface)
-{
- ASSERT_NOT_REACHED;
- return TRUE;
-}
-
-void _cairo_xlib_display_fini_shm (cairo_xlib_display_t *display) {}
-
-#else
-
-#include "cairo-damage-private.h"
-#include "cairo-default-context-private.h"
-#include "cairo-image-surface-private.h"
-#include "cairo-list-inline.h"
-#include "cairo-mempool-private.h"
-
-#include <X11/Xlibint.h>
-#include <X11/Xproto.h>
-#include <X11/extensions/XShm.h>
-#if HAVE_X11_EXTENSIONS_SHMPROTO_H
-#include <X11/extensions/shmproto.h>
-#elif HAVE_X11_EXTENSIONS_SHMSTR_H
-#include <X11/extensions/shmstr.h>
-#endif
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-#define MIN_PIXMAP_SIZE 4096
-
-#define MIN_BITS 8
-#define MIN_SIZE (1<<(MIN_BITS-1))
-
-typedef struct _cairo_xlib_shm cairo_xlib_shm_t;
-typedef struct _cairo_xlib_shm_info cairo_xlib_shm_info_t;
-typedef struct _cairo_xlib_shm_surface cairo_xlib_shm_surface_t;
-
-struct _cairo_xlib_shm {
- cairo_mempool_t mem;
-
- XShmSegmentInfo shm;
- unsigned long attached;
- cairo_list_t link;
-};
-
-struct _cairo_xlib_shm_info {
- unsigned long last_request;
- void *mem;
- size_t size;
- cairo_xlib_shm_t *pool;
-};
-
-struct _cairo_xlib_shm_surface {
- cairo_image_surface_t image;
-
- cairo_list_t link;
- cairo_xlib_shm_info_t *info;
- Pixmap pixmap;
- unsigned long active;
- int idle;
-};
-
-/* the parent is always given by index/2 */
-#define PQ_PARENT_INDEX(i) ((i) >> 1)
-#define PQ_FIRST_ENTRY 1
-
-/* left and right children are index * 2 and (index * 2) +1 respectively */
-#define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
-
-#define PQ_TOP(pq) ((pq)->elements[PQ_FIRST_ENTRY])
-
-struct pqueue {
- int size, max_size;
- cairo_xlib_shm_info_t **elements;
-};
-
-struct _cairo_xlib_shm_display {
- int has_pixmaps;
- int opcode;
- int event;
-
- Window window;
- unsigned long last_request;
- unsigned long last_event;
-
- cairo_list_t surfaces;
-
- cairo_list_t pool;
- struct pqueue info;
-};
-
-static inline cairo_bool_t
-seqno_passed (unsigned long a, unsigned long b)
-{
- return (long)(b - a) >= 0;
-}
-
-static inline cairo_bool_t
-seqno_before (unsigned long a, unsigned long b)
-{
- return (long)(b - a) > 0;
-}
-
-static inline cairo_bool_t
-seqno_after (unsigned long a, unsigned long b)
-{
- return (long)(a - b) > 0;
-}
-
-static inline cairo_status_t
-_pqueue_init (struct pqueue *pq)
-{
- pq->max_size = 32;
- pq->size = 0;
-
- pq->elements = _cairo_malloc_ab (pq->max_size,
- sizeof (cairo_xlib_shm_info_t *));
- if (unlikely (pq->elements == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- PQ_TOP(pq) = NULL;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline void
-_pqueue_fini (struct pqueue *pq)
-{
- free (pq->elements);
-}
-
-static cairo_status_t
-_pqueue_grow (struct pqueue *pq)
-{
- cairo_xlib_shm_info_t **new_elements;
-
- new_elements = _cairo_realloc_ab (pq->elements,
- 2 * pq->max_size,
- sizeof (cairo_xlib_shm_info_t *));
- if (unlikely (new_elements == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- pq->elements = new_elements;
- pq->max_size *= 2;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_pqueue_shrink (struct pqueue *pq, int min_size)
-{
- cairo_xlib_shm_info_t **new_elements;
-
- if (min_size > pq->max_size)
- return;
-
- new_elements = _cairo_realloc_ab (pq->elements,
- min_size,
- sizeof (cairo_xlib_shm_info_t *));
- if (unlikely (new_elements == NULL))
- return;
-
- pq->elements = new_elements;
- pq->max_size = min_size;
-}
-
-static inline cairo_status_t
-_pqueue_push (struct pqueue *pq, cairo_xlib_shm_info_t *info)
-{
- cairo_xlib_shm_info_t **elements;
- int i, parent;
-
- if (unlikely (pq->size + 1 == pq->max_size)) {
- cairo_status_t status;
-
- status = _pqueue_grow (pq);
- if (unlikely (status))
- return status;
- }
-
- elements = pq->elements;
-
- for (i = ++pq->size;
- i != PQ_FIRST_ENTRY &&
- info->last_request < elements[parent = PQ_PARENT_INDEX (i)]->last_request;
- i = parent)
- {
- elements[i] = elements[parent];
- }
-
- elements[i] = info;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline void
-_pqueue_pop (struct pqueue *pq)
-{
- cairo_xlib_shm_info_t **elements = pq->elements;
- cairo_xlib_shm_info_t *tail;
- int child, i;
-
- tail = elements[pq->size--];
- if (pq->size == 0) {
- elements[PQ_FIRST_ENTRY] = NULL;
- _pqueue_shrink (pq, 32);
- return;
- }
-
- for (i = PQ_FIRST_ENTRY;
- (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
- i = child)
- {
- if (child != pq->size &&
- elements[child+1]->last_request < elements[child]->last_request)
- {
- child++;
- }
-
- if (elements[child]->last_request >= tail->last_request)
- break;
-
- elements[i] = elements[child];
- }
- elements[i] = tail;
-}
-
-static cairo_bool_t _x_error_occurred;
-
-static int
-_check_error_handler (Display *display,
- XErrorEvent *event)
-{
- _x_error_occurred = TRUE;
- return False; /* ignored */
-}
-
-static cairo_bool_t
-can_use_shm (Display *dpy, int *has_pixmap)
-{
- XShmSegmentInfo shm;
- int (*old_handler) (Display *display, XErrorEvent *event);
- Status success;
- int major, minor;
-
- if (! XShmQueryExtension (dpy))
- return FALSE;
-
- XShmQueryVersion (dpy, &major, &minor, has_pixmap);
-
- shm.shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
- if (shm.shmid == -1)
- return FALSE;
-
- shm.readOnly = FALSE;
- shm.shmaddr = shmat (shm.shmid, NULL, 0);
- if (shm.shmaddr == (char *) -1) {
- shmctl (shm.shmid, IPC_RMID, NULL);
- return FALSE;
- }
-
- assert (CAIRO_MUTEX_IS_LOCKED (_cairo_xlib_display_mutex));
- _x_error_occurred = FALSE;
-
- XLockDisplay (dpy);
- XSync (dpy, False);
- old_handler = XSetErrorHandler (_check_error_handler);
-
- success = XShmAttach (dpy, &shm);
- if (success)
- XShmDetach (dpy, &shm);
-
- XSync (dpy, False);
- XSetErrorHandler (old_handler);
- XUnlockDisplay (dpy);
-
- shmctl (shm.shmid, IPC_RMID, NULL);
- shmdt (shm.shmaddr);
-
- return success && ! _x_error_occurred;
-}
-
-static inline Display *
-peek_display (cairo_device_t *device)
-{
- return ((cairo_xlib_display_t *)device)->display;
-}
-
-static inline unsigned long
-peek_processed (cairo_device_t *device)
-{
- return LastKnownRequestProcessed (peek_display(device));
-}
-
-static void
-_cairo_xlib_display_shm_pool_destroy (cairo_xlib_display_t *display,
- cairo_xlib_shm_t *pool)
-{
- shmdt (pool->shm.shmaddr);
- if (display->display) /* may be called after CloseDisplay */
- XShmDetach (display->display, &pool->shm);
-
- _cairo_mempool_fini (&pool->mem);
-
- cairo_list_del (&pool->link);
- free (pool);
-}
-
-static void send_event(cairo_xlib_display_t *display,
- cairo_xlib_shm_info_t *info,
- unsigned long seqno)
-{
- XShmCompletionEvent ev;
-
- if (! seqno_after (seqno, display->shm->last_event))
- return;
-
- ev.type = display->shm->event;
- ev.send_event = 1; /* XXX or lie? */
- ev.serial = NextRequest (display->display);
- ev.drawable = display->shm->window;
- ev.major_code = display->shm->opcode;
- ev.minor_code = X_ShmPutImage;
- ev.shmseg = info->pool->shm.shmid;
- ev.offset = (char *)info->mem - (char *)info->pool->shm.shmaddr;
-
- XSendEvent (display->display, ev.drawable, False, 0, (XEvent *)&ev);
-
- display->shm->last_event = ev.serial;
-}
-
-static void sync (cairo_xlib_display_t *display)
-{
- cairo_xlib_shm_info_t *info;
- struct pqueue *pq = &display->shm->info;
-
- XSync (display->display, False);
-
- while ((info = PQ_TOP(pq))) {
- _cairo_mempool_free (&info->pool->mem, info->mem);
- _pqueue_pop (&display->shm->info);
- free (info);
- }
-}
-
-static void
-_cairo_xlib_shm_info_cleanup (cairo_xlib_display_t *display)
-{
- cairo_xlib_shm_info_t *info;
- Display *dpy = display->display;
- struct pqueue *pq = &display->shm->info;
- unsigned long processed;
-
- if (PQ_TOP(pq) == NULL)
- return;
-
- XEventsQueued (dpy, QueuedAfterReading);
- processed = LastKnownRequestProcessed (dpy);
-
- info = PQ_TOP(pq);
- do {
- if (! seqno_passed (info->last_request, processed)) {
- send_event (display, info, display->shm->last_request);
- return;
- }
-
- _cairo_mempool_free (&info->pool->mem, info->mem);
- _pqueue_pop (&display->shm->info);
- free (info);
- } while ((info = PQ_TOP(pq)));
-}
-
-static cairo_xlib_shm_t *
-_cairo_xlib_shm_info_find (cairo_xlib_display_t *display, size_t size,
- void **ptr, unsigned long *last_request)
-{
- cairo_xlib_shm_info_t *info;
- struct pqueue *pq = &display->shm->info;
-
- if (PQ_TOP(pq) == NULL)
- return NULL;
-
- info = PQ_TOP(pq);
- do {
- cairo_xlib_shm_t *pool = info->pool;
-
- *last_request = info->last_request;
-
- _pqueue_pop (&display->shm->info);
- _cairo_mempool_free (&pool->mem, info->mem);
- free (info);
-
- if (pool->mem.free_bytes >= size) {
- void *mem = _cairo_mempool_alloc (&pool->mem, size);
- if (mem != NULL) {
- *ptr = mem;
- return pool;
- }
- }
- } while ((info = PQ_TOP(pq)));
-
- return NULL;
-}
-
-static cairo_xlib_shm_t *
-_cairo_xlib_shm_pool_find (cairo_xlib_display_t *display,
- size_t size,
- void **ptr)
-{
- cairo_xlib_shm_t *pool;
-
- cairo_list_foreach_entry (pool, cairo_xlib_shm_t, &display->shm->pool, link) {
- if (pool->mem.free_bytes >= size) {
- void *mem = _cairo_mempool_alloc (&pool->mem, size);
- if (mem != NULL) {
- *ptr = mem;
- return pool;
- }
- }
- }
-
- return NULL;
-}
-
-static void
-_cairo_xlib_shm_pool_cleanup (cairo_xlib_display_t *display)
-{
- cairo_xlib_shm_t *pool, *next;
- unsigned long processed;
-
- processed = LastKnownRequestProcessed (display->display);
-
- cairo_list_foreach_entry_safe (pool, next, cairo_xlib_shm_t,
- &display->shm->pool, link) {
- if (! seqno_passed (pool->attached, processed))
- break;
-
- if (pool->mem.free_bytes == pool->mem.max_bytes)
- _cairo_xlib_display_shm_pool_destroy (display, pool);
- }
-}
-
-static cairo_xlib_shm_t *
-_cairo_xlib_shm_pool_create(cairo_xlib_display_t *display,
- size_t size, void **ptr)
-{
- Display *dpy = display->display;
- cairo_xlib_shm_t *pool;
- size_t bytes, maxbits = 16, minbits = MIN_BITS;
- Status success;
-
- pool = malloc (sizeof (cairo_xlib_shm_t));
- if (pool == NULL)
- return NULL;
-
- bytes = 1 << maxbits;
- while (bytes <= size)
- bytes <<= 1, maxbits++;
- bytes <<= 3;
-
- minbits += (maxbits - 16) / 2;
-
- pool->shm.shmid = shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
- while (pool->shm.shmid == -1 && bytes >= 2*size) {
- bytes >>= 1;
- pool->shm.shmid = shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
- }
- if (pool->shm.shmid == -1)
- goto cleanup;
-
- pool->shm.readOnly = FALSE;
- pool->shm.shmaddr = shmat (pool->shm.shmid, NULL, 0);
- if (pool->shm.shmaddr == (char *) -1) {
- shmctl (pool->shm.shmid, IPC_RMID, NULL);
- goto cleanup;
- }
-
- pool->attached = NextRequest (dpy);
- success = XShmAttach (dpy, &pool->shm);
-#if !IPC_RMID_DEFERRED_RELEASE
- XSync (dpy, FALSE);
-#endif
- shmctl (pool->shm.shmid, IPC_RMID, NULL);
-
- if (! success)
- goto cleanup_shm;
-
- if (_cairo_mempool_init (&pool->mem, pool->shm.shmaddr, bytes,
- minbits, maxbits - minbits + 1))
- goto cleanup_detach;
-
- cairo_list_add (&pool->link, &display->shm->pool);
-
- *ptr = _cairo_mempool_alloc (&pool->mem, size);
- assert (*ptr != NULL);
- return pool;
-
-cleanup_detach:
- XShmDetach (dpy, &pool->shm);
-cleanup_shm:
- shmdt (pool->shm.shmaddr);
-cleanup:
- free (pool);
- return NULL;
-}
-
-static cairo_xlib_shm_info_t *
-_cairo_xlib_shm_info_create (cairo_xlib_display_t *display,
- size_t size, cairo_bool_t will_sync)
-{
- cairo_xlib_shm_info_t *info;
- cairo_xlib_shm_t *pool;
- unsigned long last_request = 0;
- void *mem = NULL;
-
- _cairo_xlib_shm_info_cleanup (display);
- pool = _cairo_xlib_shm_pool_find (display, size, &mem);
- _cairo_xlib_shm_pool_cleanup (display);
-
- if (pool == NULL && will_sync)
- pool = _cairo_xlib_shm_info_find (display, size, &mem, &last_request);
- if (pool == NULL)
- pool = _cairo_xlib_shm_pool_create (display, size, &mem);
- if (pool == NULL)
- return NULL;
-
- assert (mem != NULL);
-
- info = malloc (sizeof (*info));
- if (info == NULL) {
- _cairo_mempool_free (&pool->mem, mem);
- return NULL;
- }
-
- info->pool = pool;
- info->mem = mem;
- info->size = size;
- info->last_request = last_request;
-
- return info;
-}
-
-static cairo_status_t
-_cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
-{
- cairo_xlib_shm_surface_t *shm = abstract_surface;
- cairo_xlib_display_t *display;
- Display *dpy;
- cairo_status_t status;
-
- if (shm->active == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (shm->image.base._finishing)
- return CAIRO_STATUS_SUCCESS;
-
- if (seqno_passed (shm->active, peek_processed (shm->image.base.device))) {
- shm->active = 0;
- return CAIRO_STATUS_SUCCESS;
- }
-
- status = _cairo_xlib_display_acquire (shm->image.base.device, &display);
- if (unlikely (status))
- return status;
-
- send_event (display, shm->info, shm->active);
-
- dpy = display->display;
- XEventsQueued (dpy, QueuedAfterReading);
- while (! seqno_passed (shm->active, LastKnownRequestProcessed (dpy))) {
- LockDisplay(dpy);
- _XReadEvents(dpy);
- UnlockDisplay(dpy);
- }
-
- cairo_device_release (&display->base);
- shm->active = 0;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline cairo_bool_t
-active (cairo_xlib_shm_surface_t *shm, Display *dpy)
-{
- return (shm->active &&
- ! seqno_passed (shm->active, LastKnownRequestProcessed (dpy)));
-}
-
-static cairo_status_t
-_cairo_xlib_shm_surface_finish (void *abstract_surface)
-{
- cairo_xlib_shm_surface_t *shm = abstract_surface;
- cairo_xlib_display_t *display;
- cairo_status_t status;
-
- if (shm->image.base.damage) {
- _cairo_damage_destroy (shm->image.base.damage);
- shm->image.base.damage = _cairo_damage_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
- }
-
- status = _cairo_xlib_display_acquire (shm->image.base.device, &display);
- if (unlikely (status))
- return status;
-
- if (shm->pixmap)
- XFreePixmap (display->display, shm->pixmap);
-
- if (active (shm, display->display)) {
- shm->info->last_request = shm->active;
- _pqueue_push (&display->shm->info, shm->info);
- if (seqno_before (display->shm->last_request, shm->active))
- display->shm->last_request = shm->active;
- } else {
- _cairo_mempool_free (&shm->info->pool->mem, shm->info->mem);
- free (shm->info);
-
- _cairo_xlib_shm_pool_cleanup (display);
- }
-
- cairo_list_del (&shm->link);
-
- cairo_device_release (&display->base);
- return _cairo_image_surface_finish (abstract_surface);
-}
-
-static const cairo_surface_backend_t cairo_xlib_shm_surface_backend = {
- CAIRO_SURFACE_TYPE_IMAGE,
- _cairo_xlib_shm_surface_finish,
-
- _cairo_default_context_create,
-
- _cairo_image_surface_create_similar,
- NULL, /* create similar image */
- _cairo_image_surface_map_to_image,
- _cairo_image_surface_unmap_image,
-
- _cairo_image_surface_source,
- _cairo_image_surface_acquire_source_image,
- _cairo_image_surface_release_source_image,
- _cairo_image_surface_snapshot,
-
- NULL, /* copy_page */
- NULL, /* show_page */
-
- _cairo_image_surface_get_extents,
- _cairo_image_surface_get_font_options,
-
- _cairo_xlib_shm_surface_flush,
- NULL,
-
- _cairo_image_surface_paint,
- _cairo_image_surface_mask,
- _cairo_image_surface_stroke,
- _cairo_image_surface_fill,
- NULL, /* fill-stroke */
- _cairo_image_surface_glyphs,
-};
-
-static cairo_bool_t
-has_shm (cairo_xlib_surface_t *surface)
-{
- cairo_xlib_display_t *display = (cairo_xlib_display_t *)surface->base.device;
- return display->shm != NULL;
-}
-
-static int
-has_shm_pixmaps (cairo_xlib_surface_t *surface)
-{
- cairo_xlib_display_t *display = (cairo_xlib_display_t *)surface->base.device;
- if (!display->shm)
- return 0;
-
- return display->shm->has_pixmaps;
-}
-
-static cairo_xlib_shm_surface_t *
-_cairo_xlib_shm_surface_create (cairo_xlib_surface_t *other,
- pixman_format_code_t format,
- int width, int height,
- cairo_bool_t will_sync,
- int create_pixmap)
-{
- cairo_xlib_shm_surface_t *shm;
- cairo_xlib_display_t *display;
- pixman_image_t *image;
- int stride, size;
-
- stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP(format));
- size = stride * height;
- if (size < MIN_SIZE)
- return NULL;
-
- shm = malloc (sizeof (*shm));
- if (unlikely (shm == NULL))
- return (cairo_xlib_shm_surface_t *)_cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
-
- _cairo_surface_init (&shm->image.base,
- &cairo_xlib_shm_surface_backend,
- other->base.device,
- _cairo_content_from_pixman_format (format));
-
- if (_cairo_xlib_display_acquire (other->base.device, &display))
- goto cleanup_shm;
-
- shm->info = _cairo_xlib_shm_info_create (display, size, will_sync);
- if (shm->info == NULL)
- goto cleanup_display;
-
- image = pixman_image_create_bits (format, width, height,
- (uint32_t *) shm->info->mem, stride);
- if (image == NULL)
- goto cleanup_info;
-
- _cairo_image_surface_init (&shm->image, image, format);
-
- shm->pixmap = 0;
- if (create_pixmap && size >= create_pixmap) {
- shm->pixmap = XShmCreatePixmap (display->display,
- other->drawable,
- shm->info->mem,
- &shm->info->pool->shm,
- shm->image.width,
- shm->image.height,
- shm->image.depth);
- }
- shm->active = shm->info->last_request;
- shm->idle = -5;
-
- assert (shm->active == 0 || will_sync);
-
- cairo_list_add (&shm->link, &display->shm->surfaces);
-
- cairo_device_release (&display->base);
-
- return shm;
-
-cleanup_info:
- _cairo_mempool_free (&shm->info->pool->mem, shm->info->mem);
- free(shm->info);
-cleanup_display:
- cairo_device_release (&display->base);
-cleanup_shm:
- free (shm);
- return NULL;
-}
-
-static void
-_cairo_xlib_surface_update_shm (cairo_xlib_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *)surface->shm;
- cairo_xlib_display_t *display;
- cairo_damage_t *damage;
- GC gc;
-
- damage = _cairo_damage_reduce (surface->base.damage);
- surface->base.damage = _cairo_damage_create();
-
- if (_cairo_xlib_display_acquire (surface->base.device, &display))
- goto cleanup_damage;
-
- if (_cairo_xlib_surface_get_gc (display, surface, &gc))
- goto cleanup_display;
-
- if (! surface->owns_pixmap) {
- XGCValues gcv;
-
- gcv.subwindow_mode = IncludeInferiors;
- XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
- }
-
- if (damage->region) {
- XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (sizeof (XRectangle))];
- XRectangle *rects = stack_rects;
- cairo_rectangle_int_t r;
- int n_rects, i;
-
- n_rects = cairo_region_num_rectangles (damage->region);
- if (n_rects == 0) {
- } else if (n_rects == 1) {
- cairo_region_get_rectangle (damage->region, 0, &r);
- XCopyArea (display->display,
- surface->drawable, shm->pixmap, gc,
- r.x, r.y,
- r.width, r.height,
- r.x, r.y);
- } else {
- if (n_rects > ARRAY_LENGTH (stack_rects)) {
- rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
- if (unlikely (rects == NULL)) {
- rects = stack_rects;
- n_rects = ARRAY_LENGTH (stack_rects);
- }
- }
- for (i = 0; i < n_rects; i++) {
- cairo_region_get_rectangle (damage->region, i, &r);
-
- rects[i].x = r.x;
- rects[i].y = r.y;
- rects[i].width = r.width;
- rects[i].height = r.height;
- }
- XSetClipRectangles (display->display, gc, 0, 0, rects, i, YXBanded);
-
- XCopyArea (display->display,
- surface->drawable, shm->pixmap, gc,
- 0, 0,
- shm->image.width, shm->image.height,
- 0, 0);
-
- if (damage->status == CAIRO_STATUS_SUCCESS && damage->region)
- XSetClipMask (display->display, gc, None);
- }
- } else {
- XCopyArea (display->display,
- surface->drawable, shm->pixmap, gc,
- 0, 0,
- shm->image.width, shm->image.height,
- 0, 0);
- }
-
- if (! surface->owns_pixmap) {
- XGCValues gcv;
-
- gcv.subwindow_mode = ClipByChildren;
- XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
- }
-
- sync (display);
- shm->active = 0;
- shm->idle--;
-
- _cairo_xlib_surface_put_gc (display, surface, gc);
-cleanup_display:
- cairo_device_release (&display->base);
-cleanup_damage:
- _cairo_damage_destroy (damage);
-}
-
-static void
-_cairo_xlib_surface_clear_shm (cairo_xlib_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *)surface->shm;
-
- assert (shm->active == 0);
-
- _cairo_damage_destroy (surface->base.damage);
- surface->base.damage = _cairo_damage_create();
-
- memset (shm->image.data, 0, shm->image.stride * shm->image.height);
- shm->image.base.is_clear = TRUE;
-}
-
-static void inc_idle (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *)surface;
- shm->idle++;
-}
-
-static void dec_idle (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *)surface;
- shm->idle--;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_get_shm (cairo_xlib_surface_t *surface,
- cairo_bool_t overwrite)
-{
- if (surface->fallback) {
- assert (surface->base.damage);
- assert (surface->shm);
- assert (surface->shm->damage);
- goto done;
- }
-
- if (surface->shm == NULL) {
- pixman_format_code_t pixman_format;
- cairo_bool_t will_sync;
-
- if (! has_shm_pixmaps (surface))
- return NULL;
-
- if ((surface->width | surface->height) < 32)
- return NULL;
-
- pixman_format = _pixman_format_for_xlib_surface (surface);
- if (pixman_format == 0)
- return NULL;
-
- will_sync = !surface->base.is_clear && !overwrite;
-
- surface->shm =
- &_cairo_xlib_shm_surface_create (surface, pixman_format,
- surface->width, surface->height,
- will_sync, 1)->image.base;
- if (surface->shm == NULL)
- return NULL;
-
- assert (surface->base.damage == NULL);
- if (surface->base.serial || !surface->owns_pixmap) {
- cairo_rectangle_int_t rect;
-
- rect.x = rect.y = 0;
- rect.width = surface->width;
- rect.height = surface->height;
-
- surface->base.damage =
- _cairo_damage_add_rectangle (NULL, &rect);
- } else
- surface->base.damage = _cairo_damage_create ();
-
- surface->shm->damage = _cairo_damage_create ();
- }
-
- if (overwrite) {
- _cairo_damage_destroy (surface->base.damage);
- surface->base.damage = _cairo_damage_create ();
- }
-
- if (!surface->base.is_clear && surface->base.damage->dirty)
- _cairo_xlib_surface_update_shm (surface);
-
- _cairo_xlib_shm_surface_flush (surface->shm, 1);
-
- if (surface->base.is_clear && surface->base.damage->dirty)
- _cairo_xlib_surface_clear_shm (surface);
-
-done:
- dec_idle(surface->shm);
- return surface->shm;
-}
-
-cairo_int_status_t
-_cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface)
-{
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- if (!surface->fallback) {
- if (surface->shm)
- inc_idle (surface->shm);
- return CAIRO_INT_STATUS_SUCCESS;
- }
-
- if (surface->shm->damage->dirty) {
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) surface->shm;
- cairo_xlib_display_t *display;
- cairo_damage_t *damage;
- GC gc;
-
- status = _cairo_xlib_display_acquire (surface->base.device, &display);
- if (unlikely (status))
- return status;
-
- damage = _cairo_damage_reduce (shm->image.base.damage);
- shm->image.base.damage = _cairo_damage_create ();
-
- TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__,
- damage->region ? cairo_region_num_rectangles (damage->region) : 0));
- if (damage->status == CAIRO_STATUS_SUCCESS && damage->region) {
- XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (sizeof (XRectangle))];
- XRectangle *rects = stack_rects;
- cairo_rectangle_int_t r;
- int n_rects, i;
-
- n_rects = cairo_region_num_rectangles (damage->region);
- if (n_rects == 0)
- goto out;
-
- status = _cairo_xlib_surface_get_gc (display, surface, &gc);
- if (unlikely (status))
- goto out;
-
- if (n_rects == 1) {
- cairo_region_get_rectangle (damage->region, 0, &r);
- _cairo_xlib_shm_surface_mark_active (surface->shm);
- XCopyArea (display->display,
- shm->pixmap, surface->drawable, gc,
- r.x, r.y,
- r.width, r.height,
- r.x, r.y);
- } else {
- if (n_rects > ARRAY_LENGTH (stack_rects)) {
- rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
- if (unlikely (rects == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- _cairo_xlib_surface_put_gc (display, surface, gc);
- goto out;
- }
- }
- for (i = 0; i < n_rects; i++) {
- cairo_region_get_rectangle (damage->region, i, &r);
-
- rects[i].x = r.x;
- rects[i].y = r.y;
- rects[i].width = r.width;
- rects[i].height = r.height;
- }
- XSetClipRectangles (display->display, gc, 0, 0, rects, i, YXBanded);
-
- _cairo_xlib_shm_surface_mark_active (surface->shm);
- XCopyArea (display->display,
- shm->pixmap, surface->drawable, gc,
- 0, 0,
- shm->image.width, shm->image.height,
- 0, 0);
-
- if (damage->status == CAIRO_STATUS_SUCCESS && damage->region)
- XSetClipMask (display->display, gc, None);
- }
-
- _cairo_xlib_surface_put_gc (display, surface, gc);
- }
-
-out:
- _cairo_damage_destroy (damage);
- cairo_device_release (&display->base);
- }
-
- return status;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_shm (cairo_xlib_surface_t *other,
- pixman_format_code_t format,
- int width, int height)
-{
- cairo_surface_t *surface;
-
- surface = NULL;
- if (has_shm (other))
- surface = &_cairo_xlib_shm_surface_create (other, format, width, height,
- FALSE, has_shm_pixmaps (other))->image.base;
-
- return surface;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_shm__image (cairo_xlib_surface_t *surface,
- pixman_format_code_t format,
- int width, int height)
-{
- if (! has_shm(surface))
- return NULL;
-
- return &_cairo_xlib_shm_surface_create (surface, format, width, height,
- FALSE, 0)->image.base;
-}
-
-cairo_surface_t *
-_cairo_xlib_surface_create_similar_shm (void *other,
- cairo_format_t format,
- int width, int height)
-{
- cairo_surface_t *surface;
-
- surface = _cairo_xlib_surface_create_shm (other,
- _cairo_format_to_pixman_format_code (format),
- width, height);
- if (surface) {
- if (! surface->is_clear) {
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) surface;
- assert (shm->active == 0);
- memset (shm->image.data, 0, shm->image.stride * shm->image.height);
- shm->image.base.is_clear = TRUE;
- }
- } else
- surface = cairo_image_surface_create (format, width, height);
-
- return surface;
-}
-
-void
-_cairo_xlib_shm_surface_mark_active (cairo_surface_t *_shm)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) _shm;
- cairo_xlib_display_t *display = (cairo_xlib_display_t *) _shm->device;
-
- shm->active = NextRequest (display->display);
-}
-
-void
-_cairo_xlib_shm_surface_get_ximage (cairo_surface_t *surface,
- XImage *ximage)
-{
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) surface;
- int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
- cairo_format_masks_t image_masks;
- int ret;
-
- ret = _pixman_format_to_masks (shm->image.pixman_format, &image_masks);
- assert (ret);
-
- ximage->width = shm->image.width;
- ximage->height = shm->image.height;
- ximage->format = ZPixmap;
- ximage->data = (char *) shm->image.data;
- ximage->obdata = (char *)&shm->info->pool->shm;
- ximage->byte_order = native_byte_order;
- ximage->bitmap_unit = 32; /* always for libpixman */
- ximage->bitmap_bit_order = native_byte_order;
- ximage->bitmap_pad = 32; /* always for libpixman */
- ximage->depth = shm->image.depth;
- ximage->bytes_per_line = shm->image.stride;
- ximage->bits_per_pixel = image_masks.bpp;
- ximage->red_mask = image_masks.red_mask;
- ximage->green_mask = image_masks.green_mask;
- ximage->blue_mask = image_masks.blue_mask;
- ximage->xoffset = 0;
-
- ret = XInitImage (ximage);
- assert (ret != 0);
-}
-
-void *
-_cairo_xlib_shm_surface_get_obdata (cairo_surface_t *surface)
-{
- cairo_xlib_display_t *display = (cairo_xlib_display_t *) surface->device;
- cairo_xlib_shm_surface_t *shm = (cairo_xlib_shm_surface_t *) surface;
-
- display->shm->last_event = shm->active = NextRequest (display->display);
- return &shm->info->pool->shm;
-}
-
-Pixmap
-_cairo_xlib_shm_surface_get_pixmap (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm;
-
- shm = (cairo_xlib_shm_surface_t *) surface;
- return shm->pixmap;
-}
-
-XRenderPictFormat *
-_cairo_xlib_shm_surface_get_xrender_format (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm;
-
- shm = (cairo_xlib_shm_surface_t *) surface;
- if (shm->image.format != CAIRO_FORMAT_INVALID)
- return _cairo_xlib_display_get_xrender_format ((cairo_xlib_display_t *)surface->device,
- shm->image.format);
-
- return _cairo_xlib_display_get_xrender_format_for_pixman((cairo_xlib_display_t *)surface->device,
- shm->image.pixman_format);
-}
-
-cairo_bool_t
-_cairo_xlib_shm_surface_is_active (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm;
-
- shm = (cairo_xlib_shm_surface_t *) surface;
- if (shm->active == 0)
- return FALSE;
-
- if (seqno_passed (shm->active, peek_processed (shm->image.base.device))) {
- shm->active = 0;
- return FALSE;
- }
-
- return TRUE;
-}
-
-cairo_bool_t
-_cairo_xlib_shm_surface_is_idle (cairo_surface_t *surface)
-{
- cairo_xlib_shm_surface_t *shm;
-
- shm = (cairo_xlib_shm_surface_t *) surface;
- return shm->idle > 0;
-}
-
-#define XORG_VERSION_ENCODE(major,minor,patch,snap) \
- (((major) * 10000000) + ((minor) * 100000) + ((patch) * 1000) + snap)
-
-static cairo_bool_t
-has_broken_send_shm_event (cairo_xlib_display_t *display,
- cairo_xlib_shm_display_t *shm)
-{
- Display *dpy = display->display;
- int (*old_handler) (Display *display, XErrorEvent *event);
- XShmCompletionEvent ev;
- XShmSegmentInfo info;
-
- info.shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
- if (info.shmid == -1)
- return TRUE;
-
- info.readOnly = FALSE;
- info.shmaddr = shmat (info.shmid, NULL, 0);
- if (info.shmaddr == (char *) -1) {
- shmctl (info.shmid, IPC_RMID, NULL);
- return TRUE;
- }
-
- ev.type = shm->event;
- ev.send_event = 1;
- ev.serial = 1;
- ev.drawable = shm->window;
- ev.major_code = shm->opcode;
- ev.minor_code = X_ShmPutImage;
-
- ev.shmseg = info.shmid;
- ev.offset = 0;
-
- assert (CAIRO_MUTEX_IS_LOCKED (_cairo_xlib_display_mutex));
- _x_error_occurred = FALSE;
-
- XLockDisplay (dpy);
- XSync (dpy, False);
- old_handler = XSetErrorHandler (_check_error_handler);
-
- XShmAttach (dpy, &info);
- XSendEvent (dpy, ev.drawable, False, 0, (XEvent *)&ev);
- XShmDetach (dpy, &info);
-
- XSync (dpy, False);
- XSetErrorHandler (old_handler);
- XUnlockDisplay (dpy);
-
- shmctl (info.shmid, IPC_RMID, NULL);
- shmdt (info.shmaddr);
-
- return _x_error_occurred;
-}
-
-static cairo_bool_t
-xorg_has_buggy_send_shm_completion_event(cairo_xlib_display_t *display,
- cairo_xlib_shm_display_t *shm)
-{
- Display *dpy = display->display;
-
- /* As libXext sets the SEND_EVENT bit in the ShmCompletionEvent,
- * the Xserver may crash if it does not take care when processing
- * the event type. For instance versions of Xorg prior to 1.11.1
- * exhibited this bug, and was fixed by:
- *
- * commit 2d2dce558d24eeea0eb011ec9ebaa6c5c2273c39
- * Author: Sam Spilsbury <sam.spilsbury@canonical.com>
- * Date: Wed Sep 14 09:58:34 2011 +0800
- *
- * Remove the SendEvent bit (0x80) before doing range checks on event type.
- */
- if (_cairo_xlib_vendor_is_xorg (dpy) &&
- VendorRelease (dpy) < XORG_VERSION_ENCODE(1,11,0,1))
- return TRUE;
-
- /* For everyone else check that no error is generated */
- return has_broken_send_shm_event (display, shm);
-}
-
-void
-_cairo_xlib_display_init_shm (cairo_xlib_display_t *display)
-{
- cairo_xlib_shm_display_t *shm;
- XSetWindowAttributes attr;
- XExtCodes *codes;
- int has_pixmap, scr;
-
- display->shm = NULL;
-
- if (!can_use_shm (display->display, &has_pixmap))
- return;
-
- shm = malloc (sizeof (*shm));
- if (unlikely (shm == NULL))
- return;
-
- codes = XInitExtension (display->display, SHMNAME);
- if (codes == NULL) {
- free (shm);
- return;
- }
-
- shm->opcode = codes ->major_opcode;
- shm->event = codes->first_event;
-
- if (unlikely (_pqueue_init (&shm->info))) {
- free (shm);
- return;
- }
-
- scr = DefaultScreen (display->display);
- attr.override_redirect = 1;
- shm->window = XCreateWindow (display->display,
- DefaultRootWindow (display->display), -1, -1,
- 1, 1, 0,
- DefaultDepth (display->display, scr),
- InputOutput,
- DefaultVisual (display->display, scr),
- CWOverrideRedirect, &attr);
- shm->last_event = 0;
- shm->last_request = 0;
-
- if (xorg_has_buggy_send_shm_completion_event(display, shm))
- has_pixmap = 0;
-
- shm->has_pixmaps = has_pixmap ? MIN_PIXMAP_SIZE : 0;
- cairo_list_init (&shm->pool);
-
- cairo_list_init (&shm->surfaces);
-
- display->shm = shm;
-}
-
-void
-_cairo_xlib_display_fini_shm (cairo_xlib_display_t *display)
-{
- cairo_xlib_shm_display_t *shm = display->shm;
-
- if (shm == NULL)
- return;
-
- while (!cairo_list_is_empty (&shm->surfaces))
- cairo_surface_finish (&cairo_list_first_entry (&shm->surfaces,
- cairo_xlib_shm_surface_t,
- link)->image.base);
-
- _pqueue_fini (&shm->info);
-
- while (!cairo_list_is_empty (&shm->pool)) {
- cairo_xlib_shm_t *pool;
-
- pool = cairo_list_first_entry (&shm->pool, cairo_xlib_shm_t, link);
- _cairo_xlib_display_shm_pool_destroy (display, pool);
- }
-
- if (display->display)
- XDestroyWindow (display->display, shm->window);
-
- free (shm);
- display->shm = NULL;
-}
-#endif
-#endif