Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3959 | Serge | 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 |
||
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 |
||
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, 0); |
||
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 */>>(x))-1) |