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