1 /* Cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Intel Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
29 * Chris Wilson <chris@chris-wilson.co.uk>
35 #include "cairo-xcb-private.h"
36 #include "cairo-hash-private.h"
37 #include "cairo-freelist-private.h"
38 #include "cairo-list-inline.h"
40 #include <xcb/xcbext.h>
41 #include <xcb/bigreq.h>
44 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
50 typedef struct _cairo_xcb_xrender_format {
51 cairo_hash_entry_t key;
52 xcb_render_pictformat_t xrender_format;
53 } cairo_xcb_xrender_format_t;
55 typedef struct _cairo_xcb_xid {
60 #define XCB_RENDER_AT_LEAST(V, major, minor) \
61 (((V)->major_version > major) || \
62 (((V)->major_version == major) && ((V)->minor_version >= minor)))
64 #define XCB_RENDER_HAS_CREATE_PICTURE(surface) XCB_RENDER_AT_LEAST((surface), 0, 0)
65 #define XCB_RENDER_HAS_COMPOSITE(surface) XCB_RENDER_AT_LEAST((surface), 0, 0)
66 #define XCB_RENDER_HAS_COMPOSITE_TEXT(surface) XCB_RENDER_AT_LEAST((surface), 0, 0)
68 #define XCB_RENDER_HAS_FILL_RECTANGLES(surface) XCB_RENDER_AT_LEAST((surface), 0, 1)
70 #define XCB_RENDER_HAS_DISJOINT(surface) XCB_RENDER_AT_LEAST((surface), 0, 2)
71 #define XCB_RENDER_HAS_CONJOINT(surface) XCB_RENDER_AT_LEAST((surface), 0, 2)
73 #define XCB_RENDER_HAS_TRAPEZOIDS(surface) XCB_RENDER_AT_LEAST((surface), 0, 4)
74 #define XCB_RENDER_HAS_TRIANGLES(surface) XCB_RENDER_AT_LEAST((surface), 0, 4)
75 #define XCB_RENDER_HAS_TRISTRIP(surface) XCB_RENDER_AT_LEAST((surface), 0, 4)
76 #define XCB_RENDER_HAS_TRIFAN(surface) XCB_RENDER_AT_LEAST((surface), 0, 4)
78 #define XCB_RENDER_HAS_PICTURE_TRANSFORM(surface) XCB_RENDER_AT_LEAST((surface), 0, 6)
79 #define XCB_RENDER_HAS_FILTERS(surface) XCB_RENDER_AT_LEAST((surface), 0, 6)
81 #define XCB_RENDER_HAS_EXTENDED_REPEAT(surface) XCB_RENDER_AT_LEAST((surface), 0, 10)
82 #define XCB_RENDER_HAS_GRADIENTS(surface) XCB_RENDER_AT_LEAST((surface), 0, 10)
84 #define XCB_RENDER_HAS_PDF_OPERATORS(surface) XCB_RENDER_AT_LEAST((surface), 0, 11)
86 static cairo_list_t connections;
89 _cairo_xcb_connection_find_visual_formats (cairo_xcb_connection_t *connection,
90 const xcb_render_query_pict_formats_reply_t *formats)
92 xcb_render_pictscreen_iterator_t screens;
93 xcb_render_pictdepth_iterator_t depths;
94 xcb_render_pictvisual_iterator_t visuals;
96 for (screens = xcb_render_query_pict_formats_screens_iterator (formats);
98 xcb_render_pictscreen_next (&screens))
100 for (depths = xcb_render_pictscreen_depths_iterator (screens.data);
102 xcb_render_pictdepth_next (&depths))
104 for (visuals = xcb_render_pictdepth_visuals_iterator (depths.data);
106 xcb_render_pictvisual_next (&visuals))
108 cairo_xcb_xrender_format_t *f;
109 cairo_status_t status;
111 f = malloc (sizeof (cairo_xcb_xrender_format_t));
112 if (unlikely (f == NULL))
113 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
115 f->key.hash = visuals.data->visual;
116 f->xrender_format = visuals.data->format;
117 status = _cairo_hash_table_insert (connection->visual_to_xrender_format,
119 if (unlikely (status))
125 return CAIRO_STATUS_SUCCESS;
129 static xcb_format_t *
130 find_format_for_depth (const xcb_setup_t *setup, uint8_t depth)
132 xcb_format_t *fmt = xcb_setup_pixmap_formats (setup);
133 xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length (setup);
135 for (; fmt != fmtend; ++fmt)
136 if (fmt->depth == depth)
143 static cairo_status_t
144 _cairo_xcb_connection_parse_xrender_formats (cairo_xcb_connection_t *connection,
145 const xcb_render_query_pict_formats_reply_t *formats)
147 xcb_render_pictforminfo_iterator_t i;
148 cairo_status_t status;
150 for (i = xcb_render_query_pict_formats_formats_iterator (formats);
152 xcb_render_pictforminfo_next (&i))
154 cairo_format_masks_t masks;
155 pixman_format_code_t pixman_format;
157 if (i.data->type != XCB_RENDER_PICT_TYPE_DIRECT)
161 (unsigned long) i.data->direct.alpha_mask << i.data->direct.alpha_shift;
163 (unsigned long) i.data->direct.red_mask << i.data->direct.red_shift;
165 (unsigned long) i.data->direct.green_mask << i.data->direct.green_shift;
167 (unsigned long) i.data->direct.blue_mask << i.data->direct.blue_shift;
168 masks.bpp = i.data->depth;
170 if (_pixman_format_from_masks (&masks, &pixman_format)) {
171 cairo_hash_entry_t key;
173 key.hash = pixman_format;
174 if (! _cairo_hash_table_lookup (connection->xrender_formats, &key)) {
175 cairo_xcb_xrender_format_t *f;
177 f = malloc (sizeof (cairo_xcb_xrender_format_t));
178 if (unlikely (f == NULL))
179 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
181 f->key.hash = pixman_format;
182 f->xrender_format = i.data->id;
183 status = _cairo_hash_table_insert (connection->xrender_formats,
185 if (unlikely (status))
189 printf ("xrender %x -> (%lx, %lx, %lx, %lx, %d) %x [%d, %d]\n",
197 PIXMAN_FORMAT_DEPTH(pixman_format),
198 PIXMAN_FORMAT_BPP(pixman_format));
204 status = _cairo_xcb_connection_find_visual_formats (connection, formats);
205 if (unlikely (status))
208 connection->standard_formats[CAIRO_FORMAT_A1] =
209 _cairo_xcb_connection_get_xrender_format (connection, PIXMAN_a1);
211 connection->standard_formats[CAIRO_FORMAT_A8] =
212 _cairo_xcb_connection_get_xrender_format (connection, PIXMAN_a8);
214 connection->standard_formats[CAIRO_FORMAT_RGB24] =
215 _cairo_xcb_connection_get_xrender_format (connection,
219 if (connection->standard_formats[CAIRO_FORMAT_RGB24] == XCB_NONE) {
220 connection->standard_formats[CAIRO_FORMAT_RGB24] =
221 _cairo_xcb_connection_get_xrender_format (connection,
222 PIXMAN_FORMAT (24, PIXMAN_TYPE_ABGR,
226 connection->standard_formats[CAIRO_FORMAT_ARGB32] =
227 _cairo_xcb_connection_get_xrender_format (connection, PIXMAN_a8r8g8b8);
228 if (connection->standard_formats[CAIRO_FORMAT_ARGB32] == XCB_NONE) {
229 connection->standard_formats[CAIRO_FORMAT_ARGB32] =
230 _cairo_xcb_connection_get_xrender_format (connection, PIXMAN_a8b8g8r8);
233 return CAIRO_STATUS_SUCCESS;
237 * We require support for depth 1, 8, 24 and 32 pixmaps
239 #define DEPTH_MASK(d) (1 << ((d) - 1))
240 #define REQUIRED_DEPTHS (DEPTH_MASK(1) | \
245 pixmap_depths_usable (cairo_xcb_connection_t *connection,
249 xcb_connection_t *c = connection->xcb_connection;
250 xcb_void_cookie_t create_cookie[32];
252 cairo_bool_t success = TRUE;
255 pixmap = _cairo_xcb_connection_get_xid (connection);
257 for (depth = 1, i = 0; depth <= 32; depth++) {
258 if (missing & DEPTH_MASK(depth)) {
259 create_cookie[i] = xcb_create_pixmap_checked (c, depth, pixmap, root, 1, 1);
260 xcb_free_pixmap (c, pixmap);
261 if (!create_cookie[i].sequence) {
269 for (j = 0; j < i; j++) {
270 xcb_generic_error_t *create_error = xcb_request_check (c, create_cookie[j]);
271 success &= create_error == NULL;
275 _cairo_xcb_connection_put_xid (connection, pixmap);
281 has_required_depths (cairo_xcb_connection_t *connection)
283 xcb_screen_iterator_t screens;
285 for (screens = xcb_setup_roots_iterator (connection->root);
287 xcb_screen_next (&screens))
289 xcb_depth_iterator_t depths;
290 uint32_t missing = REQUIRED_DEPTHS;
292 for (depths = xcb_screen_allowed_depths_iterator (screens.data);
294 xcb_depth_next (&depths))
296 missing &= ~DEPTH_MASK (depths.data->depth);
302 * Ok, this is ugly. It should be sufficient at this
303 * point to just return false, but Xinerama is broken at
304 * this point and only advertises depths which have an
305 * associated visual. Of course, the other depths still
306 * work, but the only way to find out is to try them.
308 if (! pixmap_depths_usable (connection, missing, screens.data->root))
315 static xcb_render_query_version_reply_t *
316 _render_restrict_env(xcb_render_query_version_reply_t *version)
323 env = getenv ("CAIRO_DEBUG");
325 env = strstr (env, "xrender-version=");
327 int max_render_major, max_render_minor;
329 env += sizeof ("xrender-version=") - 1;
330 if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
331 max_render_major = max_render_minor = -1;
333 if (max_render_major < 0 || max_render_minor < 0) {
338 if (max_render_major < (int) version->major_version ||
339 (max_render_major == (int) version->major_version &&
340 max_render_minor < (int) version->minor_version))
342 version->major_version = max_render_major;
343 version->minor_version = max_render_minor;
350 static cairo_status_t
351 _cairo_xcb_connection_query_render (cairo_xcb_connection_t *connection)
353 xcb_connection_t *c = connection->xcb_connection;
354 xcb_render_query_version_cookie_t version_cookie;
355 xcb_render_query_pict_formats_cookie_t formats_cookie;
356 xcb_render_query_version_reply_t *version;
357 xcb_render_query_pict_formats_reply_t *formats;
358 cairo_status_t status;
359 cairo_bool_t present;
361 version_cookie = xcb_render_query_version (c, XCB_RENDER_MAJOR_VERSION, XCB_RENDER_MINOR_VERSION);
362 formats_cookie = xcb_render_query_pict_formats (c);
364 present = has_required_depths (connection);
365 version = xcb_render_query_version_reply (c, version_cookie, 0);
366 formats = xcb_render_query_pict_formats_reply (c, formats_cookie, 0);
368 version = _render_restrict_env (version);
370 if (! present || version == NULL || formats == NULL) {
373 return CAIRO_STATUS_SUCCESS;
376 /* always true if the extension is present (i.e. >= 0.0) */
377 connection->flags |= CAIRO_XCB_HAS_RENDER;
378 connection->flags |= CAIRO_XCB_RENDER_HAS_COMPOSITE;
379 connection->flags |= CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS;
381 if (XCB_RENDER_HAS_FILL_RECTANGLES (version))
382 connection->flags |= CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES;
384 if (XCB_RENDER_HAS_TRAPEZOIDS (version))
385 connection->flags |= CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS;
387 if (XCB_RENDER_HAS_PICTURE_TRANSFORM (version))
388 connection->flags |= CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM;
390 if (XCB_RENDER_HAS_FILTERS (version))
391 connection->flags |= CAIRO_XCB_RENDER_HAS_FILTERS;
393 if (XCB_RENDER_HAS_PDF_OPERATORS (version))
394 connection->flags |= CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
396 if (XCB_RENDER_HAS_EXTENDED_REPEAT (version))
397 connection->flags |= CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT;
399 if (XCB_RENDER_HAS_GRADIENTS (version))
400 connection->flags |= CAIRO_XCB_RENDER_HAS_GRADIENTS;
404 status = _cairo_xcb_connection_parse_xrender_formats (connection, formats);
412 _cairo_xcb_connection_query_cairo (cairo_xcb_connection_t *connection)
414 xcb_connection_t *c = connection->xcb_connection;
415 xcb_cairo_query_version_reply_t *version;
417 version = xcb_cairo_query_version_reply (c,
418 xcb_cairo_query_version (c, 0, 0),
425 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
427 can_use_shm (cairo_xcb_connection_t *connection)
429 cairo_bool_t success = TRUE;
430 xcb_connection_t *c = connection->xcb_connection;
431 xcb_void_cookie_t cookie[2];
432 xcb_generic_error_t *error;
437 shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
441 ptr = shmat (shmid, NULL, 0);
442 if (ptr == (char *) -1) {
443 shmctl (shmid, IPC_RMID, NULL);
447 shmseg = _cairo_xcb_connection_get_xid (connection);
448 cookie[0] = xcb_shm_attach_checked (c, shmseg, shmid, FALSE);
449 cookie[1] = xcb_shm_detach_checked (c, shmseg);
450 _cairo_xcb_connection_put_xid (connection, shmseg);
452 error = xcb_request_check (c, cookie[0]);
456 error = xcb_request_check (c, cookie[1]);
460 shmctl (shmid, IPC_RMID, NULL);
467 _cairo_xcb_connection_query_shm (cairo_xcb_connection_t *connection)
469 xcb_connection_t *c = connection->xcb_connection;
470 xcb_shm_query_version_reply_t *version;
472 version = xcb_shm_query_version_reply (c, xcb_shm_query_version (c), 0);
478 if (can_use_shm (connection))
479 connection->flags |= CAIRO_XCB_HAS_SHM;
483 static cairo_status_t
484 _device_flush (void *device)
486 cairo_xcb_connection_t *connection = device;
487 cairo_status_t status;
489 status = cairo_device_acquire (&connection->device);
490 if (unlikely (status))
493 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
494 _cairo_xcb_connection_shm_mem_pools_flush (connection);
497 xcb_flush (connection->xcb_connection);
499 cairo_device_release (&connection->device);
500 return CAIRO_STATUS_SUCCESS;
504 _pluck_xrender_format (void *entry,
507 _cairo_hash_table_remove (closure, entry);
512 _device_finish (void *device)
514 cairo_xcb_connection_t *connection = device;
515 cairo_bool_t was_cached = FALSE;
517 if (! cairo_list_is_empty (&connection->link)) {
518 CAIRO_MUTEX_LOCK (_cairo_xcb_connections_mutex);
519 cairo_list_del (&connection->link);
520 CAIRO_MUTEX_UNLOCK (_cairo_xcb_connections_mutex);
524 while (! cairo_list_is_empty (&connection->fonts)) {
525 cairo_xcb_font_t *font;
527 font = cairo_list_first_entry (&connection->fonts,
530 _cairo_xcb_font_close (font);
533 while (! cairo_list_is_empty (&connection->screens)) {
534 cairo_xcb_screen_t *screen;
536 screen = cairo_list_first_entry (&connection->screens,
539 _cairo_xcb_screen_finish (screen);
542 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
543 /* _cairo_xcb_screen_finish finishes surfaces. If any of those surfaces had
544 * a fallback image, we might have done a SHM PutImage. */
545 _cairo_xcb_connection_shm_mem_pools_flush (connection);
549 cairo_device_destroy (device);
553 _device_destroy (void *device)
555 cairo_xcb_connection_t *connection = device;
557 _cairo_hash_table_foreach (connection->xrender_formats,
558 _pluck_xrender_format, connection->xrender_formats);
559 _cairo_hash_table_destroy (connection->xrender_formats);
561 _cairo_hash_table_foreach (connection->visual_to_xrender_format,
562 _pluck_xrender_format,
563 connection->visual_to_xrender_format);
564 _cairo_hash_table_destroy (connection->visual_to_xrender_format);
566 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
567 _cairo_xcb_connection_shm_mem_pools_fini (connection);
569 _cairo_freepool_fini (&connection->shm_info_freelist);
571 _cairo_freepool_fini (&connection->xid_pool);
573 CAIRO_MUTEX_FINI (connection->shm_mutex);
574 CAIRO_MUTEX_FINI (connection->screens_mutex);
579 static const cairo_device_backend_t _cairo_xcb_device_backend = {
580 CAIRO_DEVICE_TYPE_XCB,
582 NULL, NULL, /* lock, unlock */
589 cairo_xcb_connection_t *
590 _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
592 cairo_xcb_connection_t *connection;
593 const xcb_query_extension_reply_t *ext;
594 cairo_status_t status;
596 CAIRO_MUTEX_INITIALIZE ();
598 CAIRO_MUTEX_LOCK (_cairo_xcb_connections_mutex);
599 if (connections.next == NULL) {
600 /* XXX _cairo_init () */
601 cairo_list_init (&connections);
604 cairo_list_foreach_entry (connection,
605 cairo_xcb_connection_t,
609 if (connection->xcb_connection == xcb_connection) {
610 /* Maintain MRU order. */
611 if (connections.next != &connection->link)
612 cairo_list_move (&connection->link, &connections);
618 connection = malloc (sizeof (cairo_xcb_connection_t));
619 if (unlikely (connection == NULL))
622 _cairo_device_init (&connection->device, &_cairo_xcb_device_backend);
624 connection->xcb_connection = xcb_connection;
626 cairo_list_init (&connection->fonts);
627 cairo_list_init (&connection->screens);
628 cairo_list_init (&connection->link);
629 connection->xrender_formats = _cairo_hash_table_create (NULL);
630 if (connection->xrender_formats == NULL) {
631 CAIRO_MUTEX_FINI (connection->device.mutex);
637 connection->visual_to_xrender_format = _cairo_hash_table_create (NULL);
638 if (connection->visual_to_xrender_format == NULL) {
639 _cairo_hash_table_destroy (connection->xrender_formats);
640 CAIRO_MUTEX_FINI (connection->device.mutex);
646 cairo_list_init (&connection->free_xids);
647 _cairo_freepool_init (&connection->xid_pool,
648 sizeof (cairo_xcb_xid_t));
650 cairo_list_init (&connection->shm_pools);
651 cairo_list_init (&connection->shm_pending);
652 _cairo_freepool_init (&connection->shm_info_freelist,
653 sizeof (cairo_xcb_shm_info_t));
655 connection->maximum_request_length =
656 xcb_get_maximum_request_length (xcb_connection);
658 CAIRO_MUTEX_INIT (connection->shm_mutex);
659 CAIRO_MUTEX_INIT (connection->screens_mutex);
661 CAIRO_MUTEX_LOCK (connection->device.mutex);
663 connection->flags = 0;
664 connection->force_precision = -1;
666 xcb_prefetch_extension_data (xcb_connection, &xcb_big_requests_id);
667 xcb_prefetch_extension_data (xcb_connection, &xcb_render_id);
668 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
669 xcb_prefetch_extension_data (xcb_connection, &xcb_shm_id);
672 xcb_prefetch_extension_data (xcb_connection, &xcb_cairo_id);
675 xcb_prefetch_maximum_request_length (xcb_connection);
677 connection->root = xcb_get_setup (xcb_connection);
678 connection->render = NULL;
679 ext = xcb_get_extension_data (xcb_connection, &xcb_render_id);
680 if (ext != NULL && ext->present) {
681 status = _cairo_xcb_connection_query_render (connection);
682 if (unlikely (status)) {
683 CAIRO_MUTEX_UNLOCK (connection->device.mutex);
684 _cairo_xcb_connection_destroy (connection);
689 connection->render = ext;
693 ext = xcb_get_extension_data (connection, &xcb_cairo_id);
694 if (ext != NULL && ext->present)
695 _cairo_xcb_connection_query_cairo (connection);
698 connection->shm = NULL;
699 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
700 ext = xcb_get_extension_data (xcb_connection, &xcb_shm_id);
701 if (ext != NULL && ext->present) {
702 _cairo_xcb_connection_query_shm (connection);
703 connection->shm = ext;
707 connection->original_flags = connection->flags;
709 CAIRO_MUTEX_UNLOCK (connection->device.mutex);
711 cairo_list_add (&connection->link, &connections);
713 CAIRO_MUTEX_UNLOCK (_cairo_xcb_connections_mutex);
718 xcb_render_pictformat_t
719 _cairo_xcb_connection_get_xrender_format (cairo_xcb_connection_t *connection,
720 pixman_format_code_t pixman_format)
722 cairo_hash_entry_t key;
723 cairo_xcb_xrender_format_t *format;
725 key.hash = pixman_format;
726 format = _cairo_hash_table_lookup (connection->xrender_formats, &key);
727 return format ? format->xrender_format : XCB_NONE;
730 xcb_render_pictformat_t
731 _cairo_xcb_connection_get_xrender_format_for_visual (cairo_xcb_connection_t *connection,
732 const xcb_visualid_t visual)
734 cairo_hash_entry_t key;
735 cairo_xcb_xrender_format_t *format;
738 format = _cairo_hash_table_lookup (connection->visual_to_xrender_format, &key);
739 return format ? format->xrender_format : XCB_NONE;
743 _cairo_xcb_connection_put_xid (cairo_xcb_connection_t *connection,
746 cairo_xcb_xid_t *cache;
748 assert (CAIRO_MUTEX_IS_LOCKED (connection->device.mutex));
749 cache = _cairo_freepool_alloc (&connection->xid_pool);
750 if (likely (cache != NULL)) {
752 cairo_list_add (&cache->link, &connection->free_xids);
757 _cairo_xcb_connection_get_xid (cairo_xcb_connection_t *connection)
761 assert (CAIRO_MUTEX_IS_LOCKED (connection->device.mutex));
762 if (! cairo_list_is_empty (&connection->free_xids)) {
763 cairo_xcb_xid_t *cache;
765 cache = cairo_list_first_entry (&connection->free_xids,
770 cairo_list_del (&cache->link);
771 _cairo_freepool_free (&connection->xid_pool, cache);
773 xid = xcb_generate_id (connection->xcb_connection);
780 * cairo_xcb_device_get_connection:
781 * @device: a #cairo_device_t for the XCB backend
783 * Get the connection for the XCB device.
785 * Returns: the #xcb_connection_t for the connection
790 cairo_xcb_device_get_connection (cairo_device_t *device)
792 if (device->backend->type != CAIRO_DEVICE_TYPE_XCB)
795 return ((cairo_xcb_connection_t *)device)->xcb_connection;
798 /* public (debug) interface */
801 * cairo_xcb_device_debug_cap_xshm_version:
802 * @device: a #cairo_device_t for the XCB backend
803 * @major_version: major version to restrict to
804 * @minor_version: minor version to restrict to
806 * Restricts all future XCB surfaces for this devices to the specified version
807 * of the SHM extension. This function exists solely for debugging purpose.
808 * It let's you find out how cairo would behave with an older version of
811 * Use the special values -1 and -1 for disabling the SHM extension.
816 cairo_xcb_device_debug_cap_xshm_version (cairo_device_t *device,
820 cairo_xcb_connection_t *connection = (cairo_xcb_connection_t *) device;
822 if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
823 cairo_status_t status;
825 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
830 /* First reset all the SHM flags to their original value. This works
831 * because we only ever clear bits after the connection was created.
833 connection->flags |= (connection->original_flags & CAIRO_XCB_SHM_MASK);
835 /* clear any flags that are inappropriate for the desired version */
836 if (major_version < 0 && minor_version < 0) {
837 connection->flags &= ~(CAIRO_XCB_HAS_SHM);
842 * cairo_xcb_device_debug_cap_xrender_version:
843 * @device: a #cairo_device_t for the XCB backend
844 * @major_version: major version to restrict to
845 * @minor_version: minor version to restrict to
847 * Restricts all future XCB surfaces for this devices to the specified version
848 * of the RENDER extension. This function exists solely for debugging purpose.
849 * It let's you find out how cairo would behave with an older version of
850 * the RENDER extension.
852 * Use the special values -1 and -1 for disabling the RENDER extension.
857 cairo_xcb_device_debug_cap_xrender_version (cairo_device_t *device,
861 cairo_xcb_connection_t *connection = (cairo_xcb_connection_t *) device;
863 if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
864 cairo_status_t status;
866 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
871 /* First reset all the RENDER flags to their original value. This works
872 * because we only ever clear bits after the connection was created.
874 connection->flags |= (connection->original_flags & CAIRO_XCB_RENDER_MASK);
876 /* clear any flags that are inappropriate for the desired version */
877 if (major_version < 0 && minor_version < 0) {
878 connection->flags &= ~(CAIRO_XCB_HAS_RENDER |
879 CAIRO_XCB_RENDER_HAS_COMPOSITE |
880 CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS |
881 CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES |
882 CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
883 CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM |
884 CAIRO_XCB_RENDER_HAS_FILTERS |
885 CAIRO_XCB_RENDER_HAS_PDF_OPERATORS |
886 CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT |
887 CAIRO_XCB_RENDER_HAS_GRADIENTS);
889 xcb_render_query_version_reply_t version;
891 version.major_version = major_version;
892 version.minor_version = minor_version;
894 if (! XCB_RENDER_HAS_FILL_RECTANGLES (&version))
895 connection->flags &= ~CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES;
897 if (! XCB_RENDER_HAS_TRAPEZOIDS (&version))
898 connection->flags &= ~CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS;
900 if (! XCB_RENDER_HAS_PICTURE_TRANSFORM (&version))
901 connection->flags &= ~CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM;
903 if (! XCB_RENDER_HAS_FILTERS (&version))
904 connection->flags &= ~CAIRO_XCB_RENDER_HAS_FILTERS;
906 if (! XCB_RENDER_HAS_PDF_OPERATORS (&version))
907 connection->flags &= ~CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
909 if (! XCB_RENDER_HAS_EXTENDED_REPEAT (&version))
910 connection->flags &= ~CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT;
912 if (! XCB_RENDER_HAS_GRADIENTS (&version))
913 connection->flags &= ~CAIRO_XCB_RENDER_HAS_GRADIENTS;
916 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
917 slim_hidden_def (cairo_xcb_device_debug_cap_xrender_version);
921 * cairo_xcb_device_debug_set_precision:
922 * @device: a #cairo_device_t for the XCB backend
923 * @precision: the precision to use
925 * Render supports two modes of precision when rendering trapezoids. Set
926 * the precision to the desired mode.
931 cairo_xcb_device_debug_set_precision (cairo_device_t *device,
934 if (device == NULL || device->status)
936 if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
937 cairo_status_t status;
939 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
944 ((cairo_xcb_connection_t *) device)->force_precision = precision;
946 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
947 slim_hidden_def (cairo_xcb_device_debug_set_precision);
951 * cairo_xcb_device_debug_get_precision:
952 * @device: a #cairo_device_t for the XCB backend
954 * Get the Xrender precision mode.
956 * Returns: the render precision mode
961 cairo_xcb_device_debug_get_precision (cairo_device_t *device)
963 if (device == NULL || device->status)
965 if (device->backend->type != CAIRO_DEVICE_TYPE_XCB) {
966 cairo_status_t status;
968 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
973 return ((cairo_xcb_connection_t *) device)->force_precision;
975 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
976 slim_hidden_def (cairo_xcb_device_debug_get_precision);