beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-xlib-xcb-surface.c
blobaf3e15578992900f445a1590bb6ae19e6d5a0e98
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
32 * California.
34 * Contributor(s):
35 * Carl D. Worth <cworth@cworth.org>
36 * Chris Wilson <chris@chris-wilson.co.uk>
39 #include "cairoint.h"
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 {
58 cairo_device_t base;
60 Display *dpy;
61 cairo_device_t *xcb_device;
62 XExtCodes *codes;
64 cairo_list_t link;
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,
74 void *scr,
75 void *visual,
76 void *format,
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,
82 int width,
83 int height)
85 cairo_xlib_xcb_surface_t *other = abstract_other;
86 cairo_surface_t *xcb;
88 xcb = other->xcb->base.backend->create_similar (other->xcb, content, width, height);
89 if (unlikely (xcb == NULL || xcb->status))
90 return xcb;
92 return _cairo_xlib_xcb_surface_create (other->display, other->screen, NULL, NULL, xcb);
95 static cairo_status_t
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);
104 surface->xcb = NULL;
106 return status;
109 static cairo_surface_t *
110 _cairo_xlib_xcb_surface_create_similar_image (void *abstract_other,
111 cairo_format_t format,
112 int width,
113 int height)
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_image_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;
132 return _cairo_surface_unmap_image (&surface->xcb->base, image);
135 static cairo_surface_t *
136 _cairo_xlib_xcb_surface_source (void *abstract_surface,
137 cairo_rectangle_int_t *extents)
139 cairo_xlib_xcb_surface_t *surface = abstract_surface;
140 return _cairo_surface_get_source (&surface->xcb->base, extents);
143 static cairo_status_t
144 _cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
145 cairo_image_surface_t **image_out,
146 void **image_extra)
148 cairo_xlib_xcb_surface_t *surface = abstract_surface;
149 return _cairo_surface_acquire_source_image (&surface->xcb->base,
150 image_out, image_extra);
153 static void
154 _cairo_xlib_xcb_surface_release_source_image (void *abstract_surface,
155 cairo_image_surface_t *image_out,
156 void *image_extra)
158 cairo_xlib_xcb_surface_t *surface = abstract_surface;
159 _cairo_surface_release_source_image (&surface->xcb->base, image_out, image_extra);
162 static cairo_bool_t
163 _cairo_xlib_xcb_surface_get_extents (void *abstract_surface,
164 cairo_rectangle_int_t *extents)
166 cairo_xlib_xcb_surface_t *surface = abstract_surface;
167 return _cairo_surface_get_extents (&surface->xcb->base, extents);
170 static void
171 _cairo_xlib_xcb_surface_get_font_options (void *abstract_surface,
172 cairo_font_options_t *options)
174 cairo_xlib_xcb_surface_t *surface = abstract_surface;
175 cairo_surface_get_font_options (&surface->xcb->base, options);
178 static cairo_int_status_t
179 _cairo_xlib_xcb_surface_paint (void *abstract_surface,
180 cairo_operator_t op,
181 const cairo_pattern_t *source,
182 const cairo_clip_t *clip)
184 cairo_xlib_xcb_surface_t *surface = abstract_surface;
185 return _cairo_surface_paint (&surface->xcb->base, op, source, clip);
188 static cairo_int_status_t
189 _cairo_xlib_xcb_surface_mask (void *abstract_surface,
190 cairo_operator_t op,
191 const cairo_pattern_t *source,
192 const cairo_pattern_t *mask,
193 const cairo_clip_t *clip)
195 cairo_xlib_xcb_surface_t *surface = abstract_surface;
196 return _cairo_surface_mask (&surface->xcb->base, op, source, mask, clip);
199 static cairo_int_status_t
200 _cairo_xlib_xcb_surface_stroke (void *abstract_surface,
201 cairo_operator_t op,
202 const cairo_pattern_t *source,
203 const cairo_path_fixed_t *path,
204 const cairo_stroke_style_t *style,
205 const cairo_matrix_t *ctm,
206 const cairo_matrix_t *ctm_inverse,
207 double tolerance,
208 cairo_antialias_t antialias,
209 const cairo_clip_t *clip)
211 cairo_xlib_xcb_surface_t *surface = abstract_surface;
212 return _cairo_surface_stroke (&surface->xcb->base,
213 op, source, path, style, ctm, ctm_inverse,
214 tolerance, antialias, clip);
217 static cairo_int_status_t
218 _cairo_xlib_xcb_surface_fill (void *abstract_surface,
219 cairo_operator_t op,
220 const cairo_pattern_t *source,
221 const cairo_path_fixed_t *path,
222 cairo_fill_rule_t fill_rule,
223 double tolerance,
224 cairo_antialias_t antialias,
225 const cairo_clip_t *clip)
227 cairo_xlib_xcb_surface_t *surface = abstract_surface;
228 return _cairo_surface_fill (&surface->xcb->base,
229 op, source, path,
230 fill_rule, tolerance,
231 antialias, clip);
234 static cairo_int_status_t
235 _cairo_xlib_xcb_surface_glyphs (void *abstract_surface,
236 cairo_operator_t op,
237 const cairo_pattern_t *source,
238 cairo_glyph_t *glyphs,
239 int num_glyphs,
240 cairo_scaled_font_t *scaled_font,
241 const cairo_clip_t *clip)
243 cairo_xlib_xcb_surface_t *surface = abstract_surface;
244 return _cairo_surface_show_text_glyphs (&surface->xcb->base, op, source,
245 NULL, 0,
246 glyphs, num_glyphs,
247 NULL, 0, 0,
248 scaled_font, clip);
251 static cairo_status_t
252 _cairo_xlib_xcb_surface_flush (void *abstract_surface, unsigned flags)
254 cairo_xlib_xcb_surface_t *surface = abstract_surface;
255 /* We have to call cairo_surface_flush() to make sure snapshots are detached */
256 return _cairo_surface_flush (&surface->xcb->base, flags);
259 static cairo_status_t
260 _cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
261 int x, int y,
262 int width, int height)
264 cairo_xlib_xcb_surface_t *surface = abstract_surface;
265 cairo_surface_mark_dirty_rectangle (&surface->xcb->base, x, y, width, height);
266 return cairo_surface_status (&surface->xcb->base);
269 static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
270 CAIRO_SURFACE_TYPE_XLIB,
271 _cairo_xlib_xcb_surface_finish,
273 _cairo_default_context_create, /* XXX */
275 _cairo_xlib_xcb_surface_create_similar,
276 _cairo_xlib_xcb_surface_create_similar_image,
277 _cairo_xlib_xcb_surface_map_to_image,
278 _cairo_xlib_xcb_surface_unmap,
280 _cairo_xlib_xcb_surface_source,
281 _cairo_xlib_xcb_surface_acquire_source_image,
282 _cairo_xlib_xcb_surface_release_source_image,
283 NULL, /* snapshot */
285 NULL, /* copy_page */
286 NULL, /* show_page */
288 _cairo_xlib_xcb_surface_get_extents,
289 _cairo_xlib_xcb_surface_get_font_options,
291 _cairo_xlib_xcb_surface_flush,
292 _cairo_xlib_xcb_surface_mark_dirty,
294 _cairo_xlib_xcb_surface_paint,
295 _cairo_xlib_xcb_surface_mask,
296 _cairo_xlib_xcb_surface_stroke,
297 _cairo_xlib_xcb_surface_fill,
298 NULL, /* fill_stroke */
299 _cairo_xlib_xcb_surface_glyphs,
302 static void
303 _cairo_xlib_xcb_display_finish (void *abstract_display)
305 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) abstract_display;
307 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
308 cairo_list_del (&display->link);
309 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
311 cairo_device_destroy (display->xcb_device);
312 display->xcb_device = NULL;
314 XESetCloseDisplay (display->dpy, display->codes->extension, NULL);
315 /* Drop the reference from _cairo_xlib_xcb_device_create */
316 cairo_device_destroy (&display->base);
319 static int
320 _cairo_xlib_xcb_close_display(Display *dpy, XExtCodes *codes)
322 cairo_xlib_xcb_display_t *display;
324 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
325 cairo_list_foreach_entry (display,
326 cairo_xlib_xcb_display_t,
327 &displays,
328 link)
330 if (display->dpy == dpy)
332 /* _cairo_xlib_xcb_display_finish will lock the mutex again
333 * -> deadlock (This mutex isn't recursive) */
334 cairo_device_reference (&display->base);
335 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
337 /* Make sure the xcb and xlib-xcb devices are finished */
338 cairo_device_finish (display->xcb_device);
339 cairo_device_finish (&display->base);
341 cairo_device_destroy (&display->base);
342 return 0;
345 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
347 return 0;
350 static const cairo_device_backend_t _cairo_xlib_xcb_device_backend = {
351 CAIRO_DEVICE_TYPE_XLIB,
353 NULL,
354 NULL,
356 NULL, /* flush */
357 _cairo_xlib_xcb_display_finish,
358 free, /* destroy */
361 static cairo_device_t *
362 _cairo_xlib_xcb_device_create (Display *dpy, cairo_device_t *xcb_device)
364 cairo_xlib_xcb_display_t *display = NULL;
365 cairo_device_t *device;
367 if (xcb_device == NULL)
368 return NULL;
370 CAIRO_MUTEX_INITIALIZE ();
372 CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
373 if (displays.next == NULL) {
374 cairo_list_init (&displays);
377 cairo_list_foreach_entry (display,
378 cairo_xlib_xcb_display_t,
379 &displays,
380 link)
382 if (display->dpy == dpy) {
383 /* Maintain MRU order. */
384 if (displays.next != &display->link)
385 cairo_list_move (&display->link, &displays);
387 /* Grab a reference for our caller */
388 device = cairo_device_reference (&display->base);
389 assert (display->xcb_device == xcb_device);
390 goto unlock;
394 display = malloc (sizeof (cairo_xlib_xcb_display_t));
395 if (unlikely (display == NULL)) {
396 device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
397 goto unlock;
400 display->codes = XAddExtension (dpy);
401 if (unlikely (display->codes == NULL)) {
402 device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
403 free (display);
404 goto unlock;
407 _cairo_device_init (&display->base, &_cairo_xlib_xcb_device_backend);
409 XESetCloseDisplay (dpy, display->codes->extension, _cairo_xlib_xcb_close_display);
410 /* Add a reference for _cairo_xlib_xcb_display_finish. This basically means
411 * that the device's reference count never drops to zero
412 * as long as our Display* is alive. We need this because there is no
413 * "XDelExtension" to undo XAddExtension and having lots of registered
414 * extensions slows down libX11. */
415 cairo_device_reference (&display->base);
417 display->dpy = dpy;
418 display->xcb_device = cairo_device_reference(xcb_device);
420 cairo_list_add (&display->link, &displays);
421 device = &display->base;
423 unlock:
424 CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
426 return device;
429 static cairo_surface_t *
430 _cairo_xlib_xcb_surface_create (void *dpy,
431 void *scr,
432 void *visual,
433 void *format,
434 cairo_surface_t *xcb)
436 cairo_xlib_xcb_surface_t *surface;
438 if (unlikely (xcb->status))
439 return xcb;
441 surface = malloc (sizeof (*surface));
442 if (unlikely (surface == NULL)) {
443 cairo_surface_destroy (xcb);
444 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
447 _cairo_surface_init (&surface->base,
448 &_cairo_xlib_xcb_surface_backend,
449 _cairo_xlib_xcb_device_create (dpy, xcb->device),
450 xcb->content);
452 /* _cairo_surface_init() got another reference to the device, drop ours */
453 cairo_device_destroy (surface->base.device);
455 surface->display = dpy;
456 surface->screen = scr;
457 surface->visual = visual;
458 surface->format = format;
459 surface->xcb = (cairo_xcb_surface_t *) xcb;
461 return &surface->base;
464 static Screen *
465 _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
467 int s, d, v;
469 for (s = 0; s < ScreenCount (dpy); s++) {
470 Screen *screen;
472 screen = ScreenOfDisplay (dpy, s);
473 if (visual == DefaultVisualOfScreen (screen))
474 return screen;
476 for (d = 0; d < screen->ndepths; d++) {
477 Depth *depth;
479 depth = &screen->depths[d];
480 for (v = 0; v < depth->nvisuals; v++)
481 if (visual == &depth->visuals[v])
482 return screen;
486 return NULL;
489 cairo_surface_t *
490 cairo_xlib_surface_create (Display *dpy,
491 Drawable drawable,
492 Visual *visual,
493 int width,
494 int height)
496 Screen *scr;
497 xcb_visualtype_t xcb_visual;
499 scr = _cairo_xlib_screen_from_visual (dpy, visual);
500 if (scr == NULL)
501 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
503 xcb_visual.visual_id = visual->visualid;
504 #if defined(__cplusplus) || defined(c_plusplus)
505 xcb_visual._class = visual->c_class;
506 #else
507 xcb_visual._class = visual->class;
508 #endif
509 xcb_visual.bits_per_rgb_value = visual->bits_per_rgb;
510 xcb_visual.colormap_entries = visual->map_entries;
511 xcb_visual.red_mask = visual->red_mask;
512 xcb_visual.green_mask = visual->green_mask;
513 xcb_visual.blue_mask = visual->blue_mask;
515 return _cairo_xlib_xcb_surface_create (dpy, scr, visual, NULL,
516 cairo_xcb_surface_create (XGetXCBConnection (dpy),
517 drawable,
518 &xcb_visual,
519 width, height));
522 static xcb_screen_t *
523 _cairo_xcb_screen_from_root (xcb_connection_t *connection,
524 xcb_window_t id)
526 xcb_screen_iterator_t s;
528 s = xcb_setup_roots_iterator (xcb_get_setup (connection));
529 for (; s.rem; xcb_screen_next (&s)) {
530 if (s.data->root == id)
531 return s.data;
534 return NULL;
537 cairo_surface_t *
538 cairo_xlib_surface_create_for_bitmap (Display *dpy,
539 Pixmap bitmap,
540 Screen *scr,
541 int width,
542 int height)
544 xcb_connection_t *connection = XGetXCBConnection (dpy);
545 xcb_screen_t *screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
546 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
547 cairo_xcb_surface_create_for_bitmap (connection,
548 screen,
549 bitmap,
550 width, height));
553 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
554 cairo_surface_t *
555 cairo_xlib_surface_create_with_xrender_format (Display *dpy,
556 Drawable drawable,
557 Screen *scr,
558 XRenderPictFormat *format,
559 int width,
560 int height)
562 xcb_render_pictforminfo_t xcb_format;
563 xcb_connection_t *connection;
564 xcb_screen_t *screen;
566 xcb_format.id = format->id;
567 xcb_format.type = format->type;
568 xcb_format.depth = format->depth;
569 xcb_format.direct.red_shift = format->direct.red;
570 xcb_format.direct.red_mask = format->direct.redMask;
571 xcb_format.direct.green_shift = format->direct.green;
572 xcb_format.direct.green_mask = format->direct.greenMask;
573 xcb_format.direct.blue_shift = format->direct.blue;
574 xcb_format.direct.blue_mask = format->direct.blueMask;
575 xcb_format.direct.alpha_shift = format->direct.alpha;
576 xcb_format.direct.alpha_mask = format->direct.alphaMask;
577 xcb_format.colormap = format->colormap;
579 connection = XGetXCBConnection (dpy);
580 screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
582 return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
583 cairo_xcb_surface_create_with_xrender_format (connection, screen,
584 drawable,
585 &xcb_format,
586 width, height));
589 XRenderPictFormat *
590 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
592 cairo_xlib_xcb_surface_t *xlib_surface = (cairo_xlib_xcb_surface_t *) surface;
594 /* Throw an error for a non-xlib surface */
595 if (surface->type != CAIRO_SURFACE_TYPE_XLIB) {
596 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
597 return NULL;
600 return xlib_surface->format;
602 #endif
604 void
605 cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
606 int width,
607 int height)
609 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
610 cairo_status_t status;
612 if (unlikely (abstract_surface->status))
613 return;
614 if (unlikely (abstract_surface->finished)) {
615 status = _cairo_surface_set_error (abstract_surface,
616 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
617 return;
620 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
621 status = _cairo_surface_set_error (abstract_surface,
622 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
623 return;
626 cairo_xcb_surface_set_size (&surface->xcb->base, width, height);
627 if (unlikely (surface->xcb->base.status)) {
628 status = _cairo_surface_set_error (abstract_surface,
629 _cairo_error (surface->xcb->base.status));
633 void
634 cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
635 Drawable drawable,
636 int width,
637 int height)
639 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *)abstract_surface;
640 cairo_status_t status;
642 if (unlikely (abstract_surface->status))
643 return;
644 if (unlikely (abstract_surface->finished)) {
645 status = _cairo_surface_set_error (abstract_surface,
646 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
647 return;
650 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
651 status = _cairo_surface_set_error (abstract_surface,
652 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
653 return;
656 cairo_xcb_surface_set_drawable (&surface->xcb->base, drawable, width, height);
657 if (unlikely (surface->xcb->base.status)) {
658 status = _cairo_surface_set_error (abstract_surface,
659 _cairo_error (surface->xcb->base.status));
663 Display *
664 cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
666 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
668 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
669 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
670 return NULL;
673 return surface->display;
676 Drawable
677 cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
679 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
681 if (unlikely (abstract_surface->finished)) {
682 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
683 return 0;
685 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
686 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
687 return 0;
689 /* This can happen when e.g. create_similar falls back to an image surface
690 * because we don't have the RENDER extension. */
691 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
692 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
693 return 0;
696 return surface->xcb->drawable;
699 Screen *
700 cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
702 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
704 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
705 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
706 return NULL;
709 return surface->screen;
712 Visual *
713 cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
715 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
717 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
718 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
719 return NULL;
722 return surface->visual;
726 cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
728 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
730 if (unlikely (abstract_surface->finished)) {
731 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
732 return 0;
734 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
735 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
736 return 0;
738 /* This can happen when e.g. create_similar falls back to an image surface
739 * because we don't have the RENDER extension. */
740 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
741 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
742 return 0;
745 return surface->xcb->depth;
749 cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
751 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
753 if (unlikely (abstract_surface->finished)) {
754 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
755 return 0;
757 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
758 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
759 return 0;
761 /* This can happen when e.g. create_similar falls back to an image surface
762 * because we don't have the RENDER extension. */
763 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
764 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
765 return 0;
768 return surface->xcb->width;
772 cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
774 cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
776 if (unlikely (abstract_surface->finished)) {
777 _cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
778 return 0;
780 if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
781 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
782 return 0;
784 /* This can happen when e.g. create_similar falls back to an image surface
785 * because we don't have the RENDER extension. */
786 if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
787 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
788 return 0;
791 return surface->xcb->height;
794 void
795 cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
796 int major, int minor)
798 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
800 if (device == NULL || device->status)
801 return;
803 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
804 return;
806 cairo_xcb_device_debug_cap_xrender_version (display->xcb_device,
807 major, minor);
810 void
811 cairo_xlib_device_debug_set_precision (cairo_device_t *device,
812 int precision)
814 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
816 if (device == NULL || device->status)
817 return;
818 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
819 cairo_status_t status;
821 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
822 (void) status;
823 return;
826 cairo_xcb_device_debug_set_precision (display->xcb_device, precision);
830 cairo_xlib_device_debug_get_precision (cairo_device_t *device)
832 cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
834 if (device == NULL || device->status)
835 return -1;
836 if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
837 cairo_status_t status;
839 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
840 (void) status;
841 return -1;
844 return cairo_xcb_device_debug_get_precision (display->xcb_device);
847 #endif /* CAIRO_HAS_XLIB_XCB_FUNCTIONS */