1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2002 University of Southern California
4 * Copyright © 2009 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is University of Southern
35 * Carl D. Worth <cworth@cworth.org>
36 * Chris Wilson <chris@chris-wilson.co.uk>
41 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
43 #include "cairo-xlib.h"
44 #include "cairo-xcb.h"
46 #include "cairo-xcb-private.h"
47 #include "cairo-xlib-xrender-private.h"
49 #include "cairo-default-context-private.h"
50 #include "cairo-list-inline.h"
51 #include "cairo-image-surface-private.h"
52 #include "cairo-surface-backend-private.h"
54 #include <X11/Xlib-xcb.h>
55 #include <X11/Xlibint.h> /* For XESetCloseDisplay */
57 struct cairo_xlib_xcb_display_t {
61 cairo_device_t *xcb_device;
66 typedef struct cairo_xlib_xcb_display_t cairo_xlib_xcb_display_t;
68 /* List of all #cairo_xlib_xcb_display_t alive,
69 * protected by _cairo_xlib_display_mutex */
70 static cairo_list_t displays;
72 static cairo_surface_t *
73 _cairo_xlib_xcb_surface_create (void *dpy,
77 cairo_surface_t *xcb);
79 static cairo_surface_t *
80 _cairo_xlib_xcb_surface_create_similar (void *abstract_other,
81 cairo_content_t content,
85 cairo_xlib_xcb_surface_t *other = abstract_other;
88 xcb = other->xcb->base.backend->create_similar (other->xcb, content, width, height);
89 if (unlikely (xcb == NULL || xcb->status))
92 return _cairo_xlib_xcb_surface_create (other->display, other->screen, NULL, NULL, xcb);
96 _cairo_xlib_xcb_surface_finish (void *abstract_surface)
98 cairo_xlib_xcb_surface_t *surface = abstract_surface;
99 cairo_status_t status;
101 cairo_surface_finish (&surface->xcb->base);
102 status = surface->xcb->base.status;
103 cairo_surface_destroy (&surface->xcb->base);
109 static cairo_surface_t *
110 _cairo_xlib_xcb_surface_create_similar_image (void *abstract_other,
111 cairo_format_t format,
115 cairo_xlib_xcb_surface_t *surface = abstract_other;
116 return cairo_surface_create_similar_image (&surface->xcb->base, format, width, height);
119 static cairo_surface_t *
120 _cairo_xlib_xcb_surface_map_to_image (void *abstract_surface,
121 const cairo_rectangle_int_t *extents)
123 cairo_xlib_xcb_surface_t *surface = abstract_surface;
124 return cairo_surface_map_to_image (&surface->xcb->base, extents);
127 static cairo_int_status_t
128 _cairo_xlib_xcb_surface_unmap (void *abstract_surface,
129 cairo_image_surface_t *image)
131 cairo_xlib_xcb_surface_t *surface = abstract_surface;
133 /* cairo_surface_unmap_image destroys the surface, so get a new reference
136 cairo_surface_reference (&image->base);
137 cairo_surface_unmap_image (&surface->xcb->base, &image->base);
138 return cairo_surface_status (&surface->xcb->base);
141 static cairo_surface_t *
142 _cairo_xlib_xcb_surface_source (void *abstract_surface,
143 cairo_rectangle_int_t *extents)
145 cairo_xlib_xcb_surface_t *surface = abstract_surface;
146 return _cairo_surface_get_source (&surface->xcb->base, extents);
149 static cairo_status_t
150 _cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
151 cairo_image_surface_t **image_out,
154 cairo_xlib_xcb_surface_t *surface = abstract_surface;
155 return _cairo_surface_acquire_source_image (&surface->xcb->base,
156 image_out, image_extra);
160 _cairo_xlib_xcb_surface_release_source_image (void *abstract_surface,
161 cairo_image_surface_t *image_out,
164 cairo_xlib_xcb_surface_t *surface = abstract_surface;
165 _cairo_surface_release_source_image (&surface->xcb->base, image_out, image_extra);
169 _cairo_xlib_xcb_surface_get_extents (void *abstract_surface,
170 cairo_rectangle_int_t *extents)
172 cairo_xlib_xcb_surface_t *surface = abstract_surface;
173 return _cairo_surface_get_extents (&surface->xcb->base, extents);
177 _cairo_xlib_xcb_surface_get_font_options (void *abstract_surface,
178 cairo_font_options_t *options)
180 cairo_xlib_xcb_surface_t *surface = abstract_surface;
181 cairo_surface_get_font_options (&surface->xcb->base, options);
184 static cairo_int_status_t
185 _cairo_xlib_xcb_surface_paint (void *abstract_surface,
187 const cairo_pattern_t *source,
188 const cairo_clip_t *clip)
190 cairo_xlib_xcb_surface_t *surface = abstract_surface;
191 return _cairo_surface_paint (&surface->xcb->base, op, source, clip);
194 static cairo_int_status_t
195 _cairo_xlib_xcb_surface_mask (void *abstract_surface,
197 const cairo_pattern_t *source,
198 const cairo_pattern_t *mask,
199 const cairo_clip_t *clip)
201 cairo_xlib_xcb_surface_t *surface = abstract_surface;
202 return _cairo_surface_mask (&surface->xcb->base, op, source, mask, clip);
205 static cairo_int_status_t
206 _cairo_xlib_xcb_surface_stroke (void *abstract_surface,
208 const cairo_pattern_t *source,
209 const cairo_path_fixed_t *path,
210 const cairo_stroke_style_t *style,
211 const cairo_matrix_t *ctm,
212 const cairo_matrix_t *ctm_inverse,
214 cairo_antialias_t antialias,
215 const cairo_clip_t *clip)
217 cairo_xlib_xcb_surface_t *surface = abstract_surface;
218 return _cairo_surface_stroke (&surface->xcb->base,
219 op, source, path, style, ctm, ctm_inverse,
220 tolerance, antialias, clip);
223 static cairo_int_status_t
224 _cairo_xlib_xcb_surface_fill (void *abstract_surface,
226 const cairo_pattern_t *source,
227 const cairo_path_fixed_t *path,
228 cairo_fill_rule_t fill_rule,
230 cairo_antialias_t antialias,
231 const cairo_clip_t *clip)
233 cairo_xlib_xcb_surface_t *surface = abstract_surface;
234 return _cairo_surface_fill (&surface->xcb->base,
236 fill_rule, tolerance,
240 static cairo_int_status_t
241 _cairo_xlib_xcb_surface_glyphs (void *abstract_surface,
243 const cairo_pattern_t *source,
244 cairo_glyph_t *glyphs,
246 cairo_scaled_font_t *scaled_font,
247 const cairo_clip_t *clip)
249 cairo_xlib_xcb_surface_t *surface = abstract_surface;
250 return _cairo_surface_show_text_glyphs (&surface->xcb->base, op, source,
257 static cairo_status_t
258 _cairo_xlib_xcb_surface_flush (void *abstract_surface)
260 cairo_xlib_xcb_surface_t *surface = abstract_surface;
261 /* We have to call cairo_surface_flush() to make sure snapshots are detached */
262 cairo_surface_flush (&surface->xcb->base);
263 return CAIRO_STATUS_SUCCESS;
266 static cairo_status_t
267 _cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
269 int width, int height)
271 cairo_xlib_xcb_surface_t *surface = abstract_surface;
272 cairo_surface_mark_dirty_rectangle (&surface->xcb->base, x, y, width, height);
273 return cairo_surface_status (&surface->xcb->base);
276 static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
277 CAIRO_SURFACE_TYPE_XLIB,
278 _cairo_xlib_xcb_surface_finish,
280 _cairo_default_context_create, /* XXX */
282 _cairo_xlib_xcb_surface_create_similar,
283 _cairo_xlib_xcb_surface_create_similar_image,
284 _cairo_xlib_xcb_surface_map_to_image,
285 _cairo_xlib_xcb_surface_unmap,
287 _cairo_xlib_xcb_surface_source,
288 _cairo_xlib_xcb_surface_acquire_source_image,
289 _cairo_xlib_xcb_surface_release_source_image,
292 NULL, /* copy_page */
293 NULL, /* show_page */
295 _cairo_xlib_xcb_surface_get_extents,
296 _cairo_xlib_xcb_surface_get_font_options,
298 _cairo_xlib_xcb_surface_flush,
299 _cairo_xlib_xcb_surface_mark_dirty,
301 _cairo_xlib_xcb_surface_paint,
302 _cairo_xlib_xcb_surface_mask,
303 _cairo_xlib_xcb_surface_stroke,
304 _cairo_xlib_xcb_surface_fill,
305 NULL, /* fill_stroke */
306 _cairo_xlib_xcb_surface_glyphs,
310 _cairo_xlib_xcb_display_finish (void *abstract_display)
312 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) abstract_display;
314 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
315 cairo_list_del (&display->link);
316 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
318 cairo_device_destroy (display->xcb_device);
319 display->xcb_device = NULL;
321 XESetCloseDisplay (display->dpy, display->codes->extension, NULL);
322 /* Drop the reference from _cairo_xlib_xcb_device_create */
323 cairo_device_destroy (&display->base);
327 _cairo_xlib_xcb_close_display(Display *dpy, XExtCodes *codes)
329 cairo_xlib_xcb_display_t *display;
331 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
332 cairo_list_foreach_entry (display,
333 cairo_xlib_xcb_display_t,
337 if (display->dpy == dpy)
339 /* _cairo_xlib_xcb_display_finish will lock the mutex again
340 * -> deadlock (This mutex isn't recursive) */
341 cairo_device_reference (&display->base);
342 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
344 /* Make sure the xcb and xlib-xcb devices are finished */
345 cairo_device_finish (display->xcb_device);
346 cairo_device_finish (&display->base);
348 cairo_device_destroy (&display->base);
352 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
357 static const cairo_device_backend_t _cairo_xlib_xcb_device_backend = {
358 CAIRO_DEVICE_TYPE_XLIB,
364 _cairo_xlib_xcb_display_finish,
368 static cairo_device_t *
369 _cairo_xlib_xcb_device_create (Display *dpy, cairo_device_t *xcb_device)
371 cairo_xlib_xcb_display_t *display = NULL;
372 cairo_device_t *device;
374 if (xcb_device == NULL)
377 CAIRO_MUTEX_INITIALIZE ();
379 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
380 if (displays.next == NULL) {
381 cairo_list_init (&displays);
384 cairo_list_foreach_entry (display,
385 cairo_xlib_xcb_display_t,
389 if (display->dpy == dpy) {
390 /* Maintain MRU order. */
391 if (displays.next != &display->link)
392 cairo_list_move (&display->link, &displays);
394 /* Grab a reference for our caller */
395 device = cairo_device_reference (&display->base);
396 assert (display->xcb_device == xcb_device);
401 display = malloc (sizeof (cairo_xlib_xcb_display_t));
402 if (unlikely (display == NULL)) {
403 device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
407 display->codes = XAddExtension (dpy);
408 if (unlikely (display->codes == NULL)) {
409 device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
414 _cairo_device_init (&display->base, &_cairo_xlib_xcb_device_backend);
416 XESetCloseDisplay (dpy, display->codes->extension, _cairo_xlib_xcb_close_display);
417 /* Add a reference for _cairo_xlib_xcb_display_finish. This basically means
418 * that the device's reference count never drops to zero
419 * as long as our Display* is alive. We need this because there is no
420 * "XDelExtension" to undo XAddExtension and having lots of registered
421 * extensions slows down libX11. */
422 cairo_device_reference (&display->base);
425 display->xcb_device = cairo_device_reference(xcb_device);
427 cairo_list_add (&display->link, &displays);
428 device = &display->base;
431 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
436 static cairo_surface_t *
437 _cairo_xlib_xcb_surface_create (void *dpy,
441 cairo_surface_t *xcb)
443 cairo_xlib_xcb_surface_t *surface;
445 if (unlikely (xcb->status))
448 surface = malloc (sizeof (*surface));
449 if (unlikely (surface == NULL)) {
450 cairo_surface_destroy (xcb);
451 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
454 _cairo_surface_init (&surface->base,
455 &_cairo_xlib_xcb_surface_backend,
456 _cairo_xlib_xcb_device_create (dpy, xcb->device),
459 /* _cairo_surface_init() got another reference to the device, drop ours */
460 cairo_device_destroy (surface->base.device);
462 surface->display = dpy;
463 surface->screen = scr;
464 surface->visual = visual;
465 surface->format = format;
466 surface->xcb = (cairo_xcb_surface_t *) xcb;
468 return &surface->base;
472 _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
476 for (s = 0; s < ScreenCount (dpy); s++) {
479 screen = ScreenOfDisplay (dpy, s);
480 if (visual == DefaultVisualOfScreen (screen))
483 for (d = 0; d < screen->ndepths; d++) {
486 depth = &screen->depths[d];
487 for (v = 0; v < depth->nvisuals; v++)
488 if (visual == &depth->visuals[v])
497 cairo_xlib_surface_create (Display *dpy,
504 xcb_visualtype_t xcb_visual;
506 scr = _cairo_xlib_screen_from_visual (dpy, visual);
508 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
510 xcb_visual.visual_id = visual->visualid;
511 #if defined(__cplusplus) || defined(c_plusplus)
512 xcb_visual._class = visual->c_class;
514 xcb_visual._class = visual->class;
516 xcb_visual.bits_per_rgb_value = visual->bits_per_rgb;
517 xcb_visual.colormap_entries = visual->map_entries;
518 xcb_visual.red_mask = visual->red_mask;
519 xcb_visual.green_mask = visual->green_mask;
520 xcb_visual.blue_mask = visual->blue_mask;
522 return _cairo_xlib_xcb_surface_create (dpy, scr, visual, NULL,
523 cairo_xcb_surface_create (XGetXCBConnection (dpy),
530 cairo_xlib_surface_create_for_bitmap (Display *dpy,
536 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
537 cairo_xcb_surface_create_for_bitmap (XGetXCBConnection (dpy),
538 (xcb_screen_t *) scr,
543 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
544 static xcb_screen_t *
545 _cairo_xcb_screen_from_root (xcb_connection_t *connection,
548 xcb_screen_iterator_t s;
550 s = xcb_setup_roots_iterator (xcb_get_setup (connection));
551 for (; s.rem; xcb_screen_next (&s)) {
552 if (s.data->root == id)
559 cairo_xlib_surface_create_with_xrender_format (Display *dpy,
562 XRenderPictFormat *format,
566 xcb_render_pictforminfo_t xcb_format;
567 xcb_connection_t *connection;
568 xcb_screen_t *screen;
570 xcb_format.id = format->id;
571 xcb_format.type = format->type;
572 xcb_format.depth = format->depth;
573 xcb_format.direct.red_shift = format->direct.red;
574 xcb_format.direct.red_mask = format->direct.redMask;
575 xcb_format.direct.green_shift = format->direct.green;
576 xcb_format.direct.green_mask = format->direct.greenMask;
577 xcb_format.direct.blue_shift = format->direct.blue;
578 xcb_format.direct.blue_mask = format->direct.blueMask;
579 xcb_format.direct.alpha_shift = format->direct.alpha;
580 xcb_format.direct.alpha_mask = format->direct.alphaMask;
581 xcb_format.colormap = format->colormap;
583 connection = XGetXCBConnection (dpy);
584 screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
586 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
587 cairo_xcb_surface_create_with_xrender_format (connection, screen,
594 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
596 cairo_xlib_xcb_surface_t *xlib_surface = (cairo_xlib_xcb_surface_t *) surface;
598 /* Throw an error for a non-xlib surface */
599 if (surface->type != CAIRO_SURFACE_TYPE_XLIB) {
600 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
604 return xlib_surface->format;
609 cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
613 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
614 cairo_status_t status;
616 if (unlikely (abstract_surface->status))
618 if (unlikely (abstract_surface->finished)) {
619 status = _cairo_surface_set_error (abstract_surface,
620 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
624 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
625 status = _cairo_surface_set_error (abstract_surface,
626 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
630 cairo_xcb_surface_set_size (&surface->xcb->base, width, height);
631 if (unlikely (surface->xcb->base.status)) {
632 status = _cairo_surface_set_error (abstract_surface,
633 _cairo_error (surface->xcb->base.status));
638 cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
643 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *)abstract_surface;
644 cairo_status_t status;
646 if (unlikely (abstract_surface->status))
648 if (unlikely (abstract_surface->finished)) {
649 status = _cairo_surface_set_error (abstract_surface,
650 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
654 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
655 status = _cairo_surface_set_error (abstract_surface,
656 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
660 cairo_xcb_surface_set_drawable (&surface->xcb->base, drawable, width, height);
661 if (unlikely (surface->xcb->base.status)) {
662 status = _cairo_surface_set_error (abstract_surface,
663 _cairo_error (surface->xcb->base.status));
668 cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
670 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
672 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
673 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
677 return surface->display;
681 cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
683 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
685 if (unlikely (abstract_surface->finished)) {
686 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
689 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
690 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
693 /* This can happen when e.g. create_similar falls back to an image surface
694 * because we don't have the RENDER extension. */
695 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
696 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
700 return surface->xcb->drawable;
704 cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
706 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
708 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
709 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
713 return surface->screen;
717 cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
719 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
721 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
722 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
726 return surface->visual;
730 cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
732 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
734 if (unlikely (abstract_surface->finished)) {
735 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
738 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
739 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
742 /* This can happen when e.g. create_similar falls back to an image surface
743 * because we don't have the RENDER extension. */
744 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
745 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
749 return surface->xcb->depth;
753 cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
755 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
757 if (unlikely (abstract_surface->finished)) {
758 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
761 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
762 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
765 /* This can happen when e.g. create_similar falls back to an image surface
766 * because we don't have the RENDER extension. */
767 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
768 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
772 return surface->xcb->width;
776 cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
778 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
780 if (unlikely (abstract_surface->finished)) {
781 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
784 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
785 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
788 /* This can happen when e.g. create_similar falls back to an image surface
789 * because we don't have the RENDER extension. */
790 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
791 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
795 return surface->xcb->height;
799 cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
800 int major, int minor)
802 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
804 if (device == NULL || device->status)
807 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
810 cairo_xcb_device_debug_cap_xrender_version (display->xcb_device,
815 cairo_xlib_device_debug_set_precision (cairo_device_t *device,
818 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
820 if (device == NULL || device->status)
822 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
823 cairo_status_t status;
825 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
830 cairo_xcb_device_debug_set_precision (display->xcb_device, precision);
834 cairo_xlib_device_debug_get_precision (cairo_device_t *device)
836 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
838 if (device == NULL || device->status)
840 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
841 cairo_status_t status;
843 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
848 return cairo_xcb_device_debug_get_precision (display->xcb_device);
851 #endif /* CAIRO_HAS_XLIB_XCB_FUNCTIONS */