Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-xlib-display.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2007 Chris Wilson
4  *
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.
12  *
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
18  *
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/
23  *
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.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Chris Wilson.
31  *
32  * Contributor(s):
33  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
34  */
35
36 #include "cairoint.h"
37
38 #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
39
40 #include "cairo-xlib-private.h"
41 #include "cairo-xlib-xrender-private.h"
42 #include "cairo-freelist-private.h"
43 #include "cairo-error-private.h"
44 #include "cairo-list-inline.h"
45
46 #include <X11/Xlibint.h>        /* For XESetCloseDisplay */
47
48 typedef int (*cairo_xlib_error_func_t) (Display     *display,
49                                         XErrorEvent *event);
50
51 static cairo_xlib_display_t *_cairo_xlib_display_list;
52
53 static int
54 _noop_error_handler (Display     *display,
55                      XErrorEvent *event)
56 {
57     return False;               /* return value is ignored */
58 }
59
60 static void
61 _cairo_xlib_display_finish (void *abstract_display)
62 {
63     cairo_xlib_display_t *display = abstract_display;
64     Display *dpy = display->display;
65
66     _cairo_xlib_display_fini_shm (display);
67
68     if (! cairo_device_acquire (&display->base)) {
69         cairo_xlib_error_func_t old_handler;
70
71         /* protect the notifies from triggering XErrors */
72         XSync (dpy, False);
73         old_handler = XSetErrorHandler (_noop_error_handler);
74
75         while (! cairo_list_is_empty (&display->fonts)) {
76             _cairo_xlib_font_close (cairo_list_first_entry (&display->fonts,
77                                                             cairo_xlib_font_t,
78                                                             link));
79         }
80
81         while (! cairo_list_is_empty (&display->screens)) {
82             _cairo_xlib_screen_destroy (display,
83                                         cairo_list_first_entry (&display->screens,
84                                                                 cairo_xlib_screen_t,
85                                                                 link));
86         }
87
88         XSync (dpy, False);
89         XSetErrorHandler (old_handler);
90
91         cairo_device_release (&display->base);
92     }
93 }
94
95 static void
96 _cairo_xlib_display_destroy (void *abstract_display)
97 {
98     cairo_xlib_display_t *display = abstract_display;
99
100     free (display);
101 }
102
103 static int
104 _cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
105 {
106     cairo_xlib_display_t *display, **prev, *next;
107
108     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
109     for (display = _cairo_xlib_display_list; display; display = display->next)
110         if (display->display == dpy)
111             break;
112     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
113     if (display == NULL)
114         return 0;
115
116     cairo_device_finish (&display->base);
117
118     /*
119      * Unhook from the global list
120      */
121     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
122     prev = &_cairo_xlib_display_list;
123     for (display = _cairo_xlib_display_list; display; display = next) {
124         next = display->next;
125         if (display->display == dpy) {
126             *prev = next;
127             break;
128         } else
129             prev = &display->next;
130     }
131     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
132
133     display->display = NULL; /* catch any later invalid access */
134     cairo_device_destroy (&display->base);
135
136     /* Return value in accordance with requirements of
137      * XESetCloseDisplay */
138     return 0;
139 }
140
141 static const cairo_device_backend_t _cairo_xlib_device_backend = {
142     CAIRO_DEVICE_TYPE_XLIB,
143
144     NULL,
145     NULL,
146
147     NULL, /* flush */
148     _cairo_xlib_display_finish,
149     _cairo_xlib_display_destroy,
150 };
151
152 static void _cairo_xlib_display_select_compositor (cairo_xlib_display_t *display)
153 {
154 #if 1
155     if (display->render_major > 0 || display->render_minor >= 4)
156         display->compositor = _cairo_xlib_traps_compositor_get ();
157     else if (display->render_major > 0 || display->render_minor >= 0)
158         display->compositor = _cairo_xlib_mask_compositor_get ();
159     else
160         display->compositor = _cairo_xlib_core_compositor_get ();
161 #else
162     display->compositor = _cairo_xlib_fallback_compositor_get ();
163 #endif
164 }
165
166 /**
167  * _cairo_xlib_device_create:
168  * @dpy: the display to create the device for
169  *
170  * Gets the device belonging to @dpy, or creates it if it doesn't exist yet.
171  *
172  * Returns: the device belonging to @dpy
173  **/
174 cairo_device_t *
175 _cairo_xlib_device_create (Display *dpy)
176 {
177     cairo_xlib_display_t *display;
178     cairo_xlib_display_t **prev;
179     cairo_device_t *device;
180     XExtCodes *codes;
181     const char *env;
182
183     CAIRO_MUTEX_INITIALIZE ();
184
185     /* There is an apparent deadlock between this mutex and the
186      * mutex for the display, but it's actually safe. For the
187      * app to call XCloseDisplay() while any other thread is
188      * inside this function would be an error in the logic
189      * app, and the CloseDisplay hook is the only other place we
190      * acquire this mutex.
191      */
192     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
193
194     for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
195     {
196         if (display->display == dpy) {
197             /*
198              * MRU the list
199              */
200             if (prev != &_cairo_xlib_display_list) {
201                 *prev = display->next;
202                 display->next = _cairo_xlib_display_list;
203                 _cairo_xlib_display_list = display;
204             }
205             device = cairo_device_reference (&display->base);
206             goto UNLOCK;
207         }
208     }
209
210     display = malloc (sizeof (cairo_xlib_display_t));
211     if (unlikely (display == NULL)) {
212         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
213         goto UNLOCK;
214     }
215
216     _cairo_device_init (&display->base, &_cairo_xlib_device_backend);
217
218     display->display = dpy;
219     cairo_list_init (&display->screens);
220     cairo_list_init (&display->fonts);
221     display->closed = FALSE;
222
223     /* Xlib calls out to the extension close_display hooks in LIFO
224      * order. So we have to ensure that all extensions that we depend
225      * on in our close_display hook are properly initialized before we
226      * add our hook. For now, that means Render, so we call into its
227      * QueryVersion function to ensure it gets initialized.
228      */
229     display->render_major = display->render_minor = -1;
230     XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
231     env = getenv ("CAIRO_DEBUG");
232     if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
233         int max_render_major, max_render_minor;
234
235         env += sizeof ("xrender-version=") - 1;
236         if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
237             max_render_major = max_render_minor = -1;
238
239         if (max_render_major < display->render_major ||
240             (max_render_major == display->render_major &&
241              max_render_minor < display->render_minor))
242         {
243             display->render_major = max_render_major;
244             display->render_minor = max_render_minor;
245         }
246     }
247
248     _cairo_xlib_display_select_compositor (display);
249
250     display->white = NULL;
251     memset (display->alpha, 0, sizeof (display->alpha));
252     memset (display->solid, 0, sizeof (display->solid));
253     memset (display->solid_cache, 0, sizeof (display->solid_cache));
254     memset (display->last_solid_cache, 0, sizeof (display->last_solid_cache));
255
256     memset (display->cached_xrender_formats, 0,
257             sizeof (display->cached_xrender_formats));
258
259     display->force_precision = -1;
260
261     _cairo_xlib_display_init_shm (display);
262
263     /* Prior to Render 0.10, there is no protocol support for gradients and
264      * we call function stubs instead, which would silently consume the drawing.
265      */
266 #if RENDER_MAJOR == 0 && RENDER_MINOR < 10
267     display->buggy_gradients = TRUE;
268 #else
269     display->buggy_gradients = FALSE;
270 #endif
271     display->buggy_pad_reflect = FALSE;
272     display->buggy_repeat = FALSE;
273
274     /* This buggy_repeat condition is very complicated because there
275      * are multiple X server code bases (with multiple versioning
276      * schemes within a code base), and multiple bugs.
277      *
278      * The X servers:
279      *
280      *    1. The Vendor=="XFree86" code base with release numbers such
281      *    as 4.7.0 (VendorRelease==40700000).
282      *
283      *    2. The Vendor=="X.Org" code base (a descendant of the
284      *    XFree86 code base). It originally had things like
285      *    VendorRelease==60700000 for release 6.7.0 but then changed
286      *    its versioning scheme so that, for example,
287      *    VendorRelease==10400000 for the 1.4.0 X server within the
288      *    X.Org 7.3 release.
289      *
290      * The bugs:
291      *
292      *    1. The original bug that led to the buggy_repeat
293      *    workaround. This was a bug that Owen Taylor investigated,
294      *    understood well, and characterized against carious X
295      *    servers. Confirmed X servers with this bug include:
296      *
297      *          "XFree86" <= 40500000
298      *          "X.Org" <= 60802000 (only with old numbering >= 60700000)
299      *
300      *    2. A separate bug resulting in a crash of the X server when
301      *    using cairo's extend-reflect test case, (which, surprisingly
302      *    enough was not passing RepeatReflect to the X server, but
303      *    instead using RepeatNormal in a workaround). Nobody to date
304      *    has understood the bug well, but it appears to be gone as of
305      *    the X.Org 1.4.0 server. This bug is coincidentally avoided
306      *    by using the same buggy_repeat workaround. Confirmed X
307      *    servers with this bug include:
308      *
309      *          "X.org" == 60900000 (old versioning scheme)
310      *          "X.org"  < 10400000 (new numbering scheme)
311      *
312      *    For the old-versioning-scheme X servers we don't know
313      *    exactly when second the bug started, but since bug 1 is
314      *    present through 6.8.2 and bug 2 is present in 6.9.0 it seems
315      *    safest to just blacklist all old-versioning-scheme X servers,
316      *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
317      */
318     if (_cairo_xlib_vendor_is_xorg (dpy)) {
319         if (VendorRelease (dpy) >= 60700000) {
320             if (VendorRelease (dpy) < 70000000)
321                 display->buggy_repeat = TRUE;
322
323             /* We know that gradients simply do not work in early Xorg servers */
324             if (VendorRelease (dpy) < 70200000)
325                 display->buggy_gradients = TRUE;
326
327             /* And the extended repeat modes were not fixed until much later */
328             display->buggy_pad_reflect = TRUE;
329         } else {
330             if (VendorRelease (dpy) < 10400000)
331                 display->buggy_repeat = TRUE;
332
333             /* Too many bugs in the early drivers */
334             if (VendorRelease (dpy) < 10699000)
335                 display->buggy_pad_reflect = TRUE;
336         }
337     } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
338         if (VendorRelease (dpy) <= 40500000)
339             display->buggy_repeat = TRUE;
340
341         display->buggy_gradients = TRUE;
342         display->buggy_pad_reflect = TRUE;
343     }
344
345     codes = XAddExtension (dpy);
346     if (unlikely (codes == NULL)) {
347         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
348         free (display);
349         goto UNLOCK;
350     }
351
352     XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
353     cairo_device_reference (&display->base); /* add one for the CloseDisplay */
354
355     display->next = _cairo_xlib_display_list;
356     _cairo_xlib_display_list = display;
357
358     device = &display->base;
359
360 UNLOCK:
361     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
362     return device;
363 }
364
365 cairo_status_t
366 _cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display)
367 {
368     cairo_status_t status;
369
370     status = cairo_device_acquire (device);
371     if (status)
372         return status;
373
374     *display = (cairo_xlib_display_t *) device;
375     return CAIRO_STATUS_SUCCESS;
376 }
377
378 XRenderPictFormat *
379 _cairo_xlib_display_get_xrender_format_for_pixman(cairo_xlib_display_t *display,
380                                                   pixman_format_code_t format)
381 {
382     Display *dpy = display->display;
383     XRenderPictFormat tmpl;
384     int mask;
385
386 #define MASK(x) ((1<<(x))-1)
387
388     tmpl.depth = PIXMAN_FORMAT_DEPTH(format);
389     mask = PictFormatType | PictFormatDepth;
390
391     switch (PIXMAN_FORMAT_TYPE(format)) {
392     case PIXMAN_TYPE_ARGB:
393         tmpl.type = PictTypeDirect;
394
395         tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
396         if (PIXMAN_FORMAT_A(format))
397             tmpl.direct.alpha = (PIXMAN_FORMAT_R(format) +
398                                  PIXMAN_FORMAT_G(format) +
399                                  PIXMAN_FORMAT_B(format));
400
401         tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
402         tmpl.direct.red = (PIXMAN_FORMAT_G(format) +
403                            PIXMAN_FORMAT_B(format));
404
405         tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
406         tmpl.direct.green = PIXMAN_FORMAT_B(format);
407
408         tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
409         tmpl.direct.blue = 0;
410
411         mask |= PictFormatRed | PictFormatRedMask;
412         mask |= PictFormatGreen | PictFormatGreenMask;
413         mask |= PictFormatBlue | PictFormatBlueMask;
414         mask |= PictFormatAlpha | PictFormatAlphaMask;
415         break;
416
417     case PIXMAN_TYPE_ABGR:
418         tmpl.type = PictTypeDirect;
419
420         tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
421         if (tmpl.direct.alphaMask)
422             tmpl.direct.alpha = (PIXMAN_FORMAT_B(format) +
423                                  PIXMAN_FORMAT_G(format) +
424                                  PIXMAN_FORMAT_R(format));
425
426         tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
427         tmpl.direct.blue = (PIXMAN_FORMAT_G(format) +
428                             PIXMAN_FORMAT_R(format));
429
430         tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
431         tmpl.direct.green = PIXMAN_FORMAT_R(format);
432
433         tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
434         tmpl.direct.red = 0;
435
436         mask |= PictFormatRed | PictFormatRedMask;
437         mask |= PictFormatGreen | PictFormatGreenMask;
438         mask |= PictFormatBlue | PictFormatBlueMask;
439         mask |= PictFormatAlpha | PictFormatAlphaMask;
440         break;
441
442     case PIXMAN_TYPE_BGRA:
443         tmpl.type = PictTypeDirect;
444
445         tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
446         tmpl.direct.blue = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format));
447
448         tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
449         tmpl.direct.green = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
450                              PIXMAN_FORMAT_G(format));
451
452         tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
453         tmpl.direct.red = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
454                            PIXMAN_FORMAT_G(format) - PIXMAN_FORMAT_R(format));
455
456         tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
457         tmpl.direct.alpha = 0;
458
459         mask |= PictFormatRed | PictFormatRedMask;
460         mask |= PictFormatGreen | PictFormatGreenMask;
461         mask |= PictFormatBlue | PictFormatBlueMask;
462         mask |= PictFormatAlpha | PictFormatAlphaMask;
463         break;
464
465     case PIXMAN_TYPE_A:
466         tmpl.type = PictTypeDirect;
467
468         tmpl.direct.alpha = 0;
469         tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
470
471         mask |= PictFormatAlpha | PictFormatAlphaMask;
472         break;
473
474     case PIXMAN_TYPE_COLOR:
475     case PIXMAN_TYPE_GRAY:
476         /* XXX Find matching visual/colormap */
477         tmpl.type = PictTypeIndexed;
478         //tmpl.colormap = screen->visuals[PIXMAN_FORMAT_VIS(format)].vid;
479         //mask |= PictFormatColormap;
480         return NULL;
481     }
482 #undef MASK
483
484     /* XXX caching? */
485     return XRenderFindFormat(dpy, mask, &tmpl, 1);
486 }
487
488 XRenderPictFormat *
489 _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t    *display,
490                                         cairo_format_t           format)
491 {
492     XRenderPictFormat *xrender_format;
493
494 #if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
495     xrender_format = display->cached_xrender_formats[format];
496     if (likely (xrender_format != NULL))
497         return xrender_format;
498 #endif
499
500     xrender_format = display->cached_xrender_formats[format];
501     if (xrender_format == NULL) {
502         int pict_format = PictStandardNUM;
503
504         switch (format) {
505         case CAIRO_FORMAT_A1:
506             pict_format = PictStandardA1; break;
507         case CAIRO_FORMAT_A8:
508             pict_format = PictStandardA8; break;
509         case CAIRO_FORMAT_RGB24:
510             pict_format = PictStandardRGB24; break;
511         case CAIRO_FORMAT_RGB16_565:
512             xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
513                                                                                PIXMAN_r5g6b5);
514             break;
515         case CAIRO_FORMAT_RGB30:
516             xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
517                                                                                PIXMAN_x2r10g10b10);
518             break;
519         case CAIRO_FORMAT_INVALID:
520         default:
521             ASSERT_NOT_REACHED;
522         case CAIRO_FORMAT_ARGB32:
523             pict_format = PictStandardARGB32; break;
524         }
525         if (pict_format != PictStandardNUM)
526             xrender_format =
527                 XRenderFindStandardFormat (display->display, pict_format);
528         display->cached_xrender_formats[format] = xrender_format;
529     }
530
531     return xrender_format;
532 }
533
534 cairo_xlib_screen_t *
535 _cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
536                                 Screen *screen)
537 {
538     cairo_xlib_screen_t *info;
539
540     cairo_list_foreach_entry (info, cairo_xlib_screen_t, &display->screens, link) {
541         if (info->screen == screen) {
542             if (display->screens.next != &info->link)
543                 cairo_list_move (&info->link, &display->screens);
544             return info;
545         }
546     }
547
548     return NULL;
549 }
550
551 cairo_bool_t
552 _cairo_xlib_display_has_repeat (cairo_device_t *device)
553 {
554     return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
555 }
556
557 cairo_bool_t
558 _cairo_xlib_display_has_reflect (cairo_device_t *device)
559 {
560     return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect;
561 }
562
563 cairo_bool_t
564 _cairo_xlib_display_has_gradients (cairo_device_t *device)
565 {
566     return ! ((cairo_xlib_display_t *) device)->buggy_gradients;
567 }
568
569 /**
570  * cairo_xlib_device_debug_cap_xrender_version:
571  * @device: a #cairo_device_t for the Xlib backend
572  * @major_version: major version to restrict to
573  * @minor_version: minor version to restrict to
574  *
575  * Restricts all future Xlib surfaces for this devices to the specified version
576  * of the RENDER extension. This function exists solely for debugging purpose.
577  * It let's you find out how cairo would behave with an older version of
578  * the RENDER extension.
579  *
580  * Use the special values -1 and -1 for disabling the RENDER extension.
581  *
582  * Since: 1.12
583  **/
584 void
585 cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
586                                              int major_version,
587                                              int minor_version)
588 {
589     cairo_xlib_display_t *display = (cairo_xlib_display_t *) device;
590
591     if (device == NULL || device->status)
592         return;
593
594     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
595         return;
596
597     if (major_version < display->render_major ||
598         (major_version == display->render_major &&
599          minor_version < display->render_minor))
600     {
601         display->render_major = major_version;
602         display->render_minor = minor_version;
603     }
604
605     _cairo_xlib_display_select_compositor (display);
606 }
607
608 /**
609  * cairo_xlib_device_debug_set_precision:
610  * @device: a #cairo_device_t for the Xlib backend
611  * @precision: the precision to use
612  *
613  * Render supports two modes of precision when rendering trapezoids. Set
614  * the precision to the desired mode.
615  *
616  * Since: 1.12
617  **/
618 void
619 cairo_xlib_device_debug_set_precision (cairo_device_t *device,
620                                        int precision)
621 {
622     if (device == NULL || device->status)
623         return;
624     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
625         cairo_status_t status;
626
627         status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
628         (void) status;
629         return;
630     }
631
632     ((cairo_xlib_display_t *) device)->force_precision = precision;
633 }
634
635 /**
636  * cairo_xlib_device_debug_get_precision:
637  * @device: a #cairo_device_t for the Xlib backend
638  *
639  * Get the Xrender precision mode.
640  *
641  * Returns: the render precision mode
642  *
643  * Since: 1.12
644  **/
645 int
646 cairo_xlib_device_debug_get_precision (cairo_device_t *device)
647 {
648     if (device == NULL || device->status)
649         return -1;
650     if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
651         cairo_status_t status;
652
653         status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
654         (void) status;
655         return -1;
656     }
657
658     return ((cairo_xlib_display_t *) device)->force_precision;
659 }
660
661 #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */