beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-xlib-surface.c
blob029a542b946026266dd83a7014fce3df78609c83
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is University of Southern
33 * California.
35 * Contributor(s):
36 * Carl D. Worth <cworth@cworth.org>
37 * Behdad Esfahbod <behdad@behdad.org>
38 * Chris Wilson <chris@chris-wilson.co.uk>
39 * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
42 /* Heed well the words of Owen Taylor:
43 * "Any patch that works around a render bug, or claims to, without a
44 * specific reference to the bug filed in bugzilla.freedesktop.org will
45 * never pass approval."
48 #include "cairoint.h"
50 #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
52 #include "cairo-xlib-private.h"
53 #include "cairo-xlib-surface-private.h"
55 #include "cairo-compositor-private.h"
56 #include "cairo-clip-private.h"
57 #include "cairo-damage-private.h"
58 #include "cairo-default-context-private.h"
59 #include "cairo-error-private.h"
60 #include "cairo-image-surface-private.h"
61 #include "cairo-list-inline.h"
62 #include "cairo-pattern-private.h"
63 #include "cairo-pixman-private.h"
64 #include "cairo-region-private.h"
65 #include "cairo-scaled-font-private.h"
66 #include "cairo-surface-snapshot-private.h"
67 #include "cairo-surface-subsurface-private.h"
69 #include <X11/Xutil.h> /* for XDestroyImage */
71 #include <X11/extensions/XShm.h>
72 #include <sys/ipc.h>
73 #include <sys/shm.h>
75 #define XLIB_COORD_MAX 32767
77 #define DEBUG 0
79 #if DEBUG
80 #define UNSUPPORTED(reason) \
81 fprintf (stderr, \
82 "cairo-xlib: hit unsupported operation %s(), line %d: %s\n", \
83 __FUNCTION__, __LINE__, reason), \
84 CAIRO_INT_STATUS_UNSUPPORTED
85 #else
86 #define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
87 #endif
89 #if DEBUG
90 #include <X11/Xlibint.h>
91 static void CAIRO_PRINTF_FORMAT (2, 3)
92 _x_bread_crumb (Display *dpy,
93 const char *fmt,
94 ...)
96 xReq *req;
97 char buf[2048];
98 unsigned int len, len_dwords;
99 va_list ap;
101 va_start (ap, fmt);
102 len = vsnprintf (buf, sizeof (buf), fmt, ap);
103 va_end (ap);
105 buf[len++] = '\0';
106 while (len & 3)
107 buf[len++] = '\0';
109 LockDisplay (dpy);
110 GetEmptyReq (NoOperation, req);
112 len_dwords = len >> 2;
113 SetReqLen (req, len_dwords, len_dwords);
114 Data (dpy, buf, len);
116 UnlockDisplay (dpy);
117 SyncHandle ();
119 #define X_DEBUG(x) _x_bread_crumb x
120 #else
121 #define X_DEBUG(x)
122 #endif
125 * SECTION:cairo-xlib
126 * @Title: XLib Surfaces
127 * @Short_Description: X Window System rendering using XLib
128 * @See_Also: #cairo_surface_t
130 * The XLib surface is used to render cairo graphics to X Window System
131 * windows and pixmaps using the XLib library.
133 * Note that the XLib surface automatically takes advantage of X render extension
134 * if it is available.
138 * CAIRO_HAS_XLIB_SURFACE:
140 * Defined if the Xlib surface backend is available.
141 * This macro can be used to conditionally compile backend-specific code.
143 * Since: 1.0
147 * SECTION:cairo-xlib-xrender
148 * @Title: XLib-XRender Backend
149 * @Short_Description: X Window System rendering using XLib and the X Render extension
150 * @See_Also: #cairo_surface_t
152 * The XLib surface is used to render cairo graphics to X Window System
153 * windows and pixmaps using the XLib and Xrender libraries.
155 * Note that the XLib surface automatically takes advantage of X Render extension
156 * if it is available.
160 * CAIRO_HAS_XLIB_XRENDER_SURFACE:
162 * Defined if the XLib/XRender surface functions are available.
163 * This macro can be used to conditionally compile backend-specific code.
165 * Since: 1.6
168 /* Xlib doesn't define a typedef, so define one ourselves */
169 typedef int (*cairo_xlib_error_func_t) (Display *display,
170 XErrorEvent *event);
172 static cairo_surface_t *
173 _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
174 Drawable drawable,
175 Visual *visual,
176 XRenderPictFormat *xrender_format,
177 int width,
178 int height,
179 int depth);
181 static cairo_bool_t
182 _cairo_surface_is_xlib (cairo_surface_t *surface);
185 * Instead of taking two round trips for each blending request,
186 * assume that if a particular drawable fails GetImage that it will
187 * fail for a "while"; use temporary pixmaps to avoid the errors
190 #define CAIRO_ASSUME_PIXMAP 20
192 static const XTransform identity = { {
193 { 1 << 16, 0x00000, 0x00000 },
194 { 0x00000, 1 << 16, 0x00000 },
195 { 0x00000, 0x00000, 1 << 16 },
196 } };
198 static Visual *
199 _visual_for_xrender_format(Screen *screen,
200 XRenderPictFormat *xrender_format)
202 int d, v;
204 /* XXX Consider searching through the list of known cairo_visual_t for
205 * the reverse mapping.
208 for (d = 0; d < screen->ndepths; d++) {
209 Depth *d_info = &screen->depths[d];
211 if (d_info->depth != xrender_format->depth)
212 continue;
214 for (v = 0; v < d_info->nvisuals; v++) {
215 Visual *visual = &d_info->visuals[v];
217 switch (visual->class) {
218 case TrueColor:
219 if (xrender_format->type != PictTypeDirect)
220 continue;
221 break;
223 case DirectColor:
224 /* Prefer TrueColor to DirectColor.
225 * (XRenderFindVisualFormat considers both TrueColor and DirectColor
226 * Visuals to match the same PictFormat.)
228 continue;
230 case StaticGray:
231 case GrayScale:
232 case StaticColor:
233 case PseudoColor:
234 if (xrender_format->type != PictTypeIndexed)
235 continue;
236 break;
239 if (xrender_format ==
240 XRenderFindVisualFormat (DisplayOfScreen(screen), visual))
241 return visual;
245 return NULL;
248 static cairo_content_t
249 _xrender_format_to_content (XRenderPictFormat *xrender_format)
251 cairo_content_t content;
253 /* This only happens when using a non-Render server. Let's punt
254 * and say there's no alpha here. */
255 if (xrender_format == NULL)
256 return CAIRO_CONTENT_COLOR;
258 content = 0;
259 if (xrender_format->direct.alphaMask)
260 content |= CAIRO_CONTENT_ALPHA;
261 if (xrender_format->direct.redMask |
262 xrender_format->direct.greenMask |
263 xrender_format->direct.blueMask)
264 content |= CAIRO_CONTENT_COLOR;
266 return content;
269 static cairo_surface_t *
270 _cairo_xlib_surface_create_similar (void *abstract_src,
271 cairo_content_t content,
272 int width,
273 int height)
275 cairo_xlib_surface_t *src = abstract_src;
276 XRenderPictFormat *xrender_format;
277 cairo_xlib_surface_t *surface;
278 cairo_xlib_display_t *display;
279 Pixmap pix;
281 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
282 return NULL;
284 if (width == 0 || height == 0)
285 return NULL;
287 if (_cairo_xlib_display_acquire (src->base.device, &display))
288 return NULL;
290 /* If we never found an XRenderFormat or if it isn't compatible
291 * with the content being requested, then we fallback to just
292 * constructing a cairo_format_t instead, (which will fairly
293 * arbitrarily pick a visual/depth for the similar surface.
295 xrender_format = NULL;
296 if (src->xrender_format &&
297 _xrender_format_to_content (src->xrender_format) == content)
299 xrender_format = src->xrender_format;
301 if (xrender_format == NULL) {
302 xrender_format =
303 _cairo_xlib_display_get_xrender_format (display,
304 _cairo_format_from_content (content));
306 if (xrender_format) {
307 Visual *visual;
309 /* We've got a compatible XRenderFormat now, which means the
310 * similar surface will match the existing surface as closely in
311 * visual/depth etc. as possible. */
312 pix = XCreatePixmap (display->display, src->drawable,
313 width, height, xrender_format->depth);
315 if (xrender_format == src->xrender_format)
316 visual = src->visual;
317 else
318 visual = _visual_for_xrender_format(src->screen->screen,
319 xrender_format);
321 surface = (cairo_xlib_surface_t *)
322 _cairo_xlib_surface_create_internal (src->screen, pix, visual,
323 xrender_format,
324 width, height,
325 xrender_format->depth);
327 else
329 Screen *screen = src->screen->screen;
330 int depth;
332 /* No compatible XRenderFormat, see if we can make an ordinary pixmap,
333 * so that we can still accelerate blits with XCopyArea(). */
334 if (content != CAIRO_CONTENT_COLOR) {
335 cairo_device_release (&display->base);
336 return NULL;
339 depth = DefaultDepthOfScreen (screen);
341 pix = XCreatePixmap (display->display, RootWindowOfScreen (screen),
342 width <= 0 ? 1 : width, height <= 0 ? 1 : height,
343 depth);
345 surface = (cairo_xlib_surface_t *)
346 _cairo_xlib_surface_create_internal (src->screen, pix,
347 DefaultVisualOfScreen (screen),
348 NULL,
349 width, height, depth);
352 if (likely (surface->base.status == CAIRO_STATUS_SUCCESS))
353 surface->owns_pixmap = TRUE;
354 else
355 XFreePixmap (display->display, pix);
357 cairo_device_release (&display->base);
359 return &surface->base;
362 static void
363 _cairo_xlib_surface_discard_shm (cairo_xlib_surface_t *surface)
365 if (surface->shm == NULL)
366 return;
368 /* Force the flush for an external surface */
369 if (!surface->owns_pixmap)
370 cairo_surface_flush (surface->shm);
372 cairo_surface_finish (surface->shm);
373 cairo_surface_destroy (surface->shm);
374 surface->shm = NULL;
376 _cairo_damage_destroy (surface->base.damage);
377 surface->base.damage = NULL;
379 surface->fallback = 0;
382 static cairo_status_t
383 _cairo_xlib_surface_finish (void *abstract_surface)
385 cairo_xlib_surface_t *surface = abstract_surface;
386 cairo_status_t status;
387 cairo_xlib_display_t *display;
389 cairo_list_del (&surface->link);
391 status = _cairo_xlib_display_acquire (surface->base.device, &display);
392 if (unlikely (status))
393 return status;
395 X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
397 if (surface->embedded_source.picture)
398 XRenderFreePicture (display->display, surface->embedded_source.picture);
399 if (surface->picture)
400 XRenderFreePicture (display->display, surface->picture);
402 _cairo_xlib_surface_discard_shm (surface);
404 if (surface->owns_pixmap)
405 XFreePixmap (display->display, surface->drawable);
407 cairo_device_release (&display->base);
409 return status;
412 cairo_status_t
413 _cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
414 cairo_xlib_surface_t *surface,
415 GC *gc)
417 *gc = _cairo_xlib_screen_get_gc (display,
418 surface->screen,
419 surface->depth,
420 surface->drawable);
421 if (unlikely (*gc == NULL))
422 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
424 return CAIRO_STATUS_SUCCESS;
427 static int
428 _noop_error_handler (Display *display,
429 XErrorEvent *event)
431 return False; /* return value is ignored */
434 static void
435 _swap_ximage_2bytes (XImage *ximage)
437 int i, j;
438 char *line = ximage->data;
440 for (j = ximage->height; j; j--) {
441 uint16_t *p = (uint16_t *) line;
442 for (i = ximage->width; i; i--) {
443 *p = bswap_16 (*p);
444 p++;
447 line += ximage->bytes_per_line;
451 static void
452 _swap_ximage_3bytes (XImage *ximage)
454 int i, j;
455 char *line = ximage->data;
457 for (j = ximage->height; j; j--) {
458 uint8_t *p = (uint8_t *) line;
459 for (i = ximage->width; i; i--) {
460 uint8_t tmp;
461 tmp = p[2];
462 p[2] = p[0];
463 p[0] = tmp;
464 p += 3;
467 line += ximage->bytes_per_line;
471 static void
472 _swap_ximage_4bytes (XImage *ximage)
474 int i, j;
475 char *line = ximage->data;
477 for (j = ximage->height; j; j--) {
478 uint32_t *p = (uint32_t *) line;
479 for (i = ximage->width; i; i--) {
480 *p = bswap_32 (*p);
481 p++;
484 line += ximage->bytes_per_line;
488 static void
489 _swap_ximage_nibbles (XImage *ximage)
491 int i, j;
492 char *line = ximage->data;
494 for (j = ximage->height; j; j--) {
495 uint8_t *p = (uint8_t *) line;
496 for (i = (ximage->width + 1) / 2; i; i--) {
497 *p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
498 p++;
501 line += ximage->bytes_per_line;
505 static void
506 _swap_ximage_bits (XImage *ximage)
508 int i, j;
509 char *line = ximage->data;
510 int unit = ximage->bitmap_unit;
511 int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8;
513 for (j = ximage->height; j; j--) {
514 char *p = line;
516 for (i = line_bytes; i; i--) {
517 char b = *p;
518 b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
519 b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
520 b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
521 *p = b;
523 p++;
526 line += ximage->bytes_per_line;
530 static void
531 _swap_ximage_to_native (XImage *ximage)
533 int unit_bytes = 0;
534 int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
536 if (ximage->bits_per_pixel == 1 &&
537 ximage->bitmap_bit_order != native_byte_order)
539 _swap_ximage_bits (ximage);
540 if (ximage->bitmap_bit_order == ximage->byte_order)
541 return;
544 if (ximage->byte_order == native_byte_order)
545 return;
547 switch (ximage->bits_per_pixel) {
548 case 1:
549 unit_bytes = ximage->bitmap_unit / 8;
550 break;
551 case 4:
552 _swap_ximage_nibbles (ximage);
553 /* fall-through */
554 case 8:
555 case 16:
556 case 20:
557 case 24:
558 case 28:
559 case 30:
560 case 32:
561 unit_bytes = (ximage->bits_per_pixel + 7) / 8;
562 break;
563 default:
564 /* This could be hit on some rare but possible cases. */
565 ASSERT_NOT_REACHED;
568 switch (unit_bytes) {
569 case 1:
570 break;
571 case 2:
572 _swap_ximage_2bytes (ximage);
573 break;
574 case 3:
575 _swap_ximage_3bytes (ximage);
576 break;
577 case 4:
578 _swap_ximage_4bytes (ximage);
579 break;
580 default:
581 ASSERT_NOT_REACHED;
586 /* Given a mask, (with a single sequence of contiguous 1 bits), return
587 * the number of 1 bits in 'width' and the number of 0 bits to its
588 * right in 'shift'. */
589 static void
590 _characterize_field (uint32_t mask, int *width, int *shift)
592 *width = _cairo_popcount (mask);
593 /* The final '& 31' is to force a 0 mask to result in 0 shift. */
594 *shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
597 /* Convert a field of 'width' bits to 'new_width' bits with correct
598 * rounding. */
599 static inline uint32_t
600 _resize_field (uint32_t field, int width, int new_width)
602 if (width == 0)
603 return 0;
605 if (width >= new_width) {
606 return field >> (width - new_width);
607 } else {
608 uint32_t result = field << (new_width - width);
610 while (width < new_width) {
611 result |= result >> width;
612 width <<= 1;
614 return result;
618 static inline uint32_t
619 _adjust_field (uint32_t field, int adjustment)
621 return MIN (255, MAX(0, (int)field + adjustment));
624 /* Given a shifted field value, (described by 'width' and 'shift),
625 * resize it 8-bits and return that value.
627 * Note that the original field value must not have any non-field bits
628 * set.
630 static inline uint32_t
631 _field_to_8 (uint32_t field, int width, int shift)
633 return _resize_field (field >> shift, width, 8);
636 static inline uint32_t
637 _field_to_8_undither (uint32_t field, int width, int shift,
638 int dither_adjustment)
640 return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width);
643 /* Given an 8-bit value, convert it to a field of 'width', shift it up
644 * to 'shift, and return it. */
645 static inline uint32_t
646 _field_from_8 (uint32_t field, int width, int shift)
648 return _resize_field (field, 8, width) << shift;
651 static inline uint32_t
652 _field_from_8_dither (uint32_t field, int width, int shift,
653 int8_t dither_adjustment)
655 return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift);
658 static inline uint32_t
659 _pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t *visual_info,
660 uint32_t r, uint32_t g, uint32_t b,
661 int8_t dither_adjustment)
663 if (r == g && g == b) {
664 dither_adjustment /= RAMP_SIZE;
665 return visual_info->gray8_to_pseudocolor[_adjust_field (r, dither_adjustment)];
666 } else {
667 dither_adjustment = visual_info->dither8_to_cube[dither_adjustment+128];
668 return visual_info->cube_to_pseudocolor[visual_info->field8_to_cube[_adjust_field (r, dither_adjustment)]]
669 [visual_info->field8_to_cube[_adjust_field (g, dither_adjustment)]]
670 [visual_info->field8_to_cube[_adjust_field (b, dither_adjustment)]];
674 static inline uint32_t
675 _pseudocolor_to_rgb888 (cairo_xlib_visual_info_t *visual_info,
676 uint32_t pixel)
678 uint32_t r, g, b;
679 pixel &= 0xff;
680 r = visual_info->colors[pixel].r;
681 g = visual_info->colors[pixel].g;
682 b = visual_info->colors[pixel].b;
683 return (r << 16) |
684 (g << 8) |
685 (b );
688 /* should range from -128 to 127 */
689 #define X 16
690 static const int8_t dither_pattern[4][4] = {
691 {-8*X, +0*X, -6*X, +2*X},
692 {+4*X, -4*X, +6*X, -2*X},
693 {-5*X, +4*X, -7*X, +1*X},
694 {+7*X, -1*X, +5*X, -3*X}
696 #undef X
698 static int bits_per_pixel(cairo_xlib_surface_t *surface)
700 if (surface->depth > 16)
701 return 32;
702 else if (surface->depth > 8)
703 return 16;
704 else if (surface->depth > 1)
705 return 8;
706 else
707 return 1;
710 pixman_format_code_t
711 _pixman_format_for_xlib_surface (cairo_xlib_surface_t *surface)
713 cairo_format_masks_t masks;
714 pixman_format_code_t format;
716 masks.bpp = bits_per_pixel (surface);
717 masks.alpha_mask = surface->a_mask;
718 masks.red_mask = surface->r_mask;
719 masks.green_mask = surface->g_mask;
720 masks.blue_mask = surface->b_mask;
721 if (! _pixman_format_from_masks (&masks, &format))
722 return 0;
724 return format;
727 static cairo_surface_t *
728 _get_image_surface (cairo_xlib_surface_t *surface,
729 const cairo_rectangle_int_t *extents,
730 int try_shm)
732 cairo_int_status_t status;
733 cairo_image_surface_t *image = NULL;
734 XImage *ximage;
735 pixman_format_code_t pixman_format;
736 cairo_xlib_display_t *display;
738 assert (extents->x >= 0);
739 assert (extents->y >= 0);
740 assert (extents->x + extents->width <= surface->width);
741 assert (extents->y + extents->height <= surface->height);
743 if (surface->base.is_clear ||
744 (surface->base.serial == 0 && surface->owns_pixmap))
746 pixman_format = _pixman_format_for_xlib_surface (surface);
747 if (pixman_format)
749 return _cairo_image_surface_create_with_pixman_format (NULL,
750 pixman_format,
751 extents->width,
752 extents->height,
757 if (surface->shm) {
758 cairo_image_surface_t *src = (cairo_image_surface_t *) surface->shm;
759 cairo_surface_t *dst;
760 cairo_surface_pattern_t pattern;
762 dst = cairo_image_surface_create (src->format,
763 extents->width, extents->height);
764 if (unlikely (dst->status))
765 return dst;
767 _cairo_pattern_init_for_surface (&pattern, &src->base);
768 cairo_matrix_init_translate (&pattern.base.matrix,
769 extents->x, extents->y);
770 status = _cairo_surface_paint (dst, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL);
771 _cairo_pattern_fini (&pattern.base);
772 if (unlikely (status)) {
773 cairo_surface_destroy (dst);
774 dst = _cairo_surface_create_in_error (status);
777 return dst;
780 status = _cairo_xlib_display_acquire (surface->base.device, &display);
781 if (status)
782 return _cairo_surface_create_in_error (status);
784 pixman_format = _pixman_format_for_xlib_surface (surface);
785 if (try_shm && pixman_format) {
786 image = (cairo_image_surface_t *)
787 _cairo_xlib_surface_create_shm__image (surface, pixman_format,
788 extents->width, extents->height);
789 if (image && image->base.status == CAIRO_STATUS_SUCCESS) {
790 cairo_xlib_error_func_t old_handler;
791 XImage shm_image;
792 Bool success;
794 _cairo_xlib_shm_surface_get_ximage (&image->base, &shm_image);
796 old_handler = XSetErrorHandler (_noop_error_handler);
797 success = XShmGetImage (display->display,
798 surface->drawable,
799 &shm_image,
800 extents->x, extents->y,
801 AllPlanes);
802 XSetErrorHandler (old_handler);
804 if (success) {
805 cairo_device_release (&display->base);
806 return &image->base;
809 cairo_surface_destroy (&image->base);
813 if (surface->use_pixmap == 0) {
814 cairo_xlib_error_func_t old_handler;
816 old_handler = XSetErrorHandler (_noop_error_handler);
818 ximage = XGetImage (display->display,
819 surface->drawable,
820 extents->x, extents->y,
821 extents->width, extents->height,
822 AllPlanes, ZPixmap);
824 XSetErrorHandler (old_handler);
826 /* If we get an error, the surface must have been a window,
827 * so retry with the safe code path.
829 if (!ximage)
830 surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
831 } else {
832 surface->use_pixmap--;
833 ximage = NULL;
836 if (ximage == NULL) {
837 /* XGetImage from a window is dangerous because it can
838 * produce errors if the window is unmapped or partially
839 * outside the screen. We could check for errors and
840 * retry, but to keep things simple, we just create a
841 * temporary pixmap
843 Pixmap pixmap;
844 GC gc;
846 status = _cairo_xlib_surface_get_gc (display, surface, &gc);
847 if (unlikely (status))
848 goto BAIL;
850 pixmap = XCreatePixmap (display->display,
851 surface->drawable,
852 extents->width, extents->height,
853 surface->depth);
854 if (pixmap) {
855 XGCValues gcv;
857 gcv.subwindow_mode = IncludeInferiors;
858 XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
860 XCopyArea (display->display, surface->drawable, pixmap, gc,
861 extents->x, extents->y,
862 extents->width, extents->height,
863 0, 0);
865 gcv.subwindow_mode = ClipByChildren;
866 XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
868 ximage = XGetImage (display->display,
869 pixmap,
870 0, 0,
871 extents->width, extents->height,
872 AllPlanes, ZPixmap);
874 XFreePixmap (display->display, pixmap);
877 _cairo_xlib_surface_put_gc (display, surface, gc);
879 if (ximage == NULL) {
880 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
881 goto BAIL;
885 _swap_ximage_to_native (ximage);
887 /* We can't use pixman to simply write to image if:
888 * (a) the pixels are not appropriately aligned,
889 * (b) pixman does not the pixel format, or
890 * (c) if the image is palettized and we need to convert.
892 if (pixman_format &&
893 ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
894 (surface->visual == NULL || surface->visual->class == TrueColor))
896 image = (cairo_image_surface_t*)
897 _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
898 pixman_format,
899 ximage->width,
900 ximage->height,
901 ximage->bytes_per_line);
902 status = image->base.status;
903 if (unlikely (status))
904 goto BAIL;
906 /* Let the surface take ownership of the data */
907 _cairo_image_surface_assume_ownership_of_data (image);
908 ximage->data = NULL;
909 } else {
910 /* The visual we are dealing with is not supported by the
911 * standard pixman formats. So we must first convert the data
912 * to a supported format. */
914 cairo_format_t format;
915 unsigned char *data;
916 uint32_t *row;
917 uint32_t in_pixel, out_pixel;
918 unsigned int rowstride;
919 uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0;
920 int a_width=0, r_width=0, g_width=0, b_width=0;
921 int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
922 int x, y, x0, y0, x_off, y_off;
923 cairo_xlib_visual_info_t *visual_info = NULL;
925 if (surface->visual == NULL || surface->visual->class == TrueColor) {
926 cairo_bool_t has_alpha;
927 cairo_bool_t has_color;
929 has_alpha = surface->a_mask;
930 has_color = (surface->r_mask ||
931 surface->g_mask ||
932 surface->b_mask);
934 if (has_color) {
935 if (has_alpha) {
936 format = CAIRO_FORMAT_ARGB32;
937 } else {
938 format = CAIRO_FORMAT_RGB24;
940 } else {
941 /* XXX: Using CAIRO_FORMAT_A8 here would be more
942 * efficient, but would require slightly different code in
943 * the image conversion to put the alpha channel values
944 * into the right place. */
945 format = CAIRO_FORMAT_ARGB32;
948 a_mask = surface->a_mask;
949 r_mask = surface->r_mask;
950 g_mask = surface->g_mask;
951 b_mask = surface->b_mask;
953 _characterize_field (a_mask, &a_width, &a_shift);
954 _characterize_field (r_mask, &r_width, &r_shift);
955 _characterize_field (g_mask, &g_width, &g_shift);
956 _characterize_field (b_mask, &b_width, &b_shift);
958 } else {
959 format = CAIRO_FORMAT_RGB24;
961 status = _cairo_xlib_screen_get_visual_info (display,
962 surface->screen,
963 surface->visual,
964 &visual_info);
965 if (unlikely (status))
966 goto BAIL;
969 image = (cairo_image_surface_t *) cairo_image_surface_create
970 (format, ximage->width, ximage->height);
971 status = image->base.status;
972 if (unlikely (status))
973 goto BAIL;
975 data = cairo_image_surface_get_data (&image->base);
976 rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
977 row = (uint32_t *) data;
978 x0 = extents->x + surface->base.device_transform.x0;
979 y0 = extents->y + surface->base.device_transform.y0;
980 for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
981 y < ximage->height;
982 y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
983 const int8_t *dither_row = dither_pattern[y_off];
984 for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
985 x < ximage->width;
986 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
987 int dither_adjustment = dither_row[x_off];
989 in_pixel = XGetPixel (ximage, x, y);
990 if (visual_info == NULL) {
991 out_pixel = (
992 _field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 |
993 _field_to_8_undither (in_pixel & r_mask, r_width, r_shift, dither_adjustment) << 16 |
994 _field_to_8_undither (in_pixel & g_mask, g_width, g_shift, dither_adjustment) << 8 |
995 _field_to_8_undither (in_pixel & b_mask, b_width, b_shift, dither_adjustment));
996 } else {
997 /* Undithering pseudocolor does not look better */
998 out_pixel = _pseudocolor_to_rgb888 (visual_info, in_pixel);
1000 row[x] = out_pixel;
1002 row += rowstride;
1004 cairo_surface_mark_dirty (&image->base);
1007 BAIL:
1008 if (ximage)
1009 XDestroyImage (ximage);
1011 cairo_device_release (&display->base);
1013 if (unlikely (status)) {
1014 cairo_surface_destroy (&image->base);
1015 return _cairo_surface_create_in_error (status);
1018 return &image->base;
1021 void
1022 _cairo_xlib_surface_set_precision (cairo_xlib_surface_t *surface,
1023 cairo_antialias_t antialias)
1025 cairo_xlib_display_t *display = surface->display;
1026 int precision;
1028 if (display->force_precision != -1)
1029 precision = display->force_precision;
1030 else switch (antialias) {
1031 default:
1032 case CAIRO_ANTIALIAS_DEFAULT:
1033 case CAIRO_ANTIALIAS_GRAY:
1034 case CAIRO_ANTIALIAS_NONE:
1035 case CAIRO_ANTIALIAS_FAST:
1036 case CAIRO_ANTIALIAS_GOOD:
1037 precision = PolyModeImprecise;
1038 break;
1039 case CAIRO_ANTIALIAS_BEST:
1040 case CAIRO_ANTIALIAS_SUBPIXEL:
1041 precision = PolyModePrecise;
1042 break;
1045 if (surface->precision != precision) {
1046 XRenderPictureAttributes pa;
1048 pa.poly_mode = precision;
1049 XRenderChangePicture (display->display, surface->picture,
1050 CPPolyMode, &pa);
1052 surface->precision = precision;
1056 void
1057 _cairo_xlib_surface_ensure_picture (cairo_xlib_surface_t *surface)
1059 cairo_xlib_display_t *display = surface->display;
1060 XRenderPictureAttributes pa;
1061 int mask = 0;
1063 if (surface->picture)
1064 return;
1066 if (display->force_precision != -1)
1067 pa.poly_mode = display->force_precision;
1068 else
1069 pa.poly_mode = PolyModeImprecise;
1070 if (pa.poly_mode)
1071 mask |= CPPolyMode;
1073 surface->precision = pa.poly_mode;
1074 surface->picture = XRenderCreatePicture (display->display,
1075 surface->drawable,
1076 surface->xrender_format,
1077 mask, &pa);
1080 cairo_status_t
1081 _cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
1082 cairo_image_surface_t *image,
1083 int src_x,
1084 int src_y,
1085 int width,
1086 int height,
1087 int dst_x,
1088 int dst_y)
1090 cairo_xlib_display_t *display;
1091 XImage ximage;
1092 cairo_format_masks_t image_masks;
1093 int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
1094 cairo_surface_t *shm_image = NULL;
1095 pixman_image_t *pixman_image = NULL;
1096 cairo_status_t status;
1097 cairo_bool_t own_data = FALSE;
1098 cairo_bool_t is_rgb_image;
1099 GC gc;
1101 ximage.width = image->width;
1102 ximage.height = image->height;
1103 ximage.format = ZPixmap;
1104 ximage.byte_order = native_byte_order;
1105 ximage.bitmap_unit = 32; /* always for libpixman */
1106 ximage.bitmap_bit_order = native_byte_order;
1107 ximage.bitmap_pad = 32; /* always for libpixman */
1108 ximage.depth = surface->depth;
1109 ximage.red_mask = surface->r_mask;
1110 ximage.green_mask = surface->g_mask;
1111 ximage.blue_mask = surface->b_mask;
1112 ximage.xoffset = 0;
1113 ximage.obdata = NULL;
1115 status = _cairo_xlib_display_acquire (surface->base.device, &display);
1116 if (unlikely (status))
1117 return status;
1119 is_rgb_image = _pixman_format_to_masks (image->pixman_format, &image_masks);
1121 if (is_rgb_image &&
1122 (image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
1123 (image_masks.red_mask == surface->r_mask || surface->r_mask == 0) &&
1124 (image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
1125 (image_masks.blue_mask == surface->b_mask || surface->b_mask == 0))
1127 int ret;
1129 ximage.bits_per_pixel = image_masks.bpp;
1130 ximage.bytes_per_line = image->stride;
1131 ximage.data = (char *)image->data;
1132 if (image->base.device != surface->base.device) {
1133 /* If PutImage will break the image up into chunks, prefer to
1134 * send it all in one pass with ShmPutImage. For larger images,
1135 * it is further advantageous to reduce the number of copies,
1136 * albeit at the expense of more SHM bookkeeping.
1138 int max_request_size = XExtendedMaxRequestSize (display->display);
1139 if (max_request_size == 0)
1140 max_request_size = XMaxRequestSize (display->display);
1141 if (max_request_size > 8192)
1142 max_request_size = 8192;
1143 if (width * height * 4 > max_request_size) {
1144 shm_image = _cairo_xlib_surface_create_shm__image (surface,
1145 image->pixman_format,
1146 width, height);
1147 if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
1148 cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
1149 pixman_image_composite32 (PIXMAN_OP_SRC,
1150 image->pixman_image, NULL, clone->pixman_image,
1151 src_x, src_y,
1152 0, 0,
1153 0, 0,
1154 width, height);
1155 ximage.obdata = _cairo_xlib_shm_surface_get_obdata (shm_image);
1156 ximage.data = (char *)clone->data;
1157 ximage.bytes_per_line = clone->stride;
1158 ximage.width = width;
1159 ximage.height = height;
1160 src_x = src_y = 0;
1163 } else
1164 ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&image->base);
1166 ret = XInitImage (&ximage);
1167 assert (ret != 0);
1169 else if (surface->visual == NULL || surface->visual->class == TrueColor)
1171 pixman_format_code_t intermediate_format;
1172 int ret;
1174 image_masks.alpha_mask = surface->a_mask;
1175 image_masks.red_mask = surface->r_mask;
1176 image_masks.green_mask = surface->g_mask;
1177 image_masks.blue_mask = surface->b_mask;
1178 image_masks.bpp = bits_per_pixel (surface);
1179 ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
1180 assert (ret);
1182 shm_image = _cairo_xlib_surface_create_shm__image (surface,
1183 intermediate_format,
1184 width, height);
1185 if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
1186 cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
1188 pixman_image_composite32 (PIXMAN_OP_SRC,
1189 image->pixman_image,
1190 NULL,
1191 clone->pixman_image,
1192 src_x, src_y,
1193 0, 0,
1194 0, 0,
1195 width, height);
1197 ximage.data = (char *) clone->data;
1198 ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&clone->base);
1199 ximage.bytes_per_line = clone->stride;
1200 } else {
1201 pixman_image = pixman_image_create_bits (intermediate_format,
1202 width, height, NULL, 0);
1203 if (pixman_image == NULL) {
1204 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1205 goto BAIL;
1208 pixman_image_composite32 (PIXMAN_OP_SRC,
1209 image->pixman_image,
1210 NULL,
1211 pixman_image,
1212 src_x, src_y,
1213 0, 0,
1214 0, 0,
1215 width, height);
1217 ximage.data = (char *) pixman_image_get_data (pixman_image);
1218 ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
1221 ximage.width = width;
1222 ximage.height = height;
1223 ximage.bits_per_pixel = image_masks.bpp;
1225 ret = XInitImage (&ximage);
1226 assert (ret != 0);
1228 src_x = src_y = 0;
1230 else
1232 unsigned int stride, rowstride;
1233 int x, y, x0, y0, x_off, y_off;
1234 uint32_t in_pixel, out_pixel, *row;
1235 int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0;
1236 int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0;
1237 int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
1238 int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
1239 cairo_xlib_visual_info_t *visual_info = NULL;
1240 cairo_bool_t true_color;
1241 int ret;
1243 ximage.bits_per_pixel = bits_per_pixel(surface);
1244 stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
1245 ximage.bits_per_pixel);
1246 ximage.bytes_per_line = stride;
1247 ximage.data = _cairo_malloc_ab (stride, ximage.height);
1248 if (unlikely (ximage.data == NULL)) {
1249 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1250 goto BAIL;
1253 own_data = TRUE;
1255 ret = XInitImage (&ximage);
1256 assert (ret != 0);
1258 _characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
1259 _characterize_field (image_masks.red_mask , &i_r_width, &i_r_shift);
1260 _characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
1261 _characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
1263 true_color = surface->visual == NULL ||
1264 surface->visual->class == TrueColor;
1265 if (true_color) {
1266 _characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
1267 _characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
1268 _characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
1269 _characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
1270 } else {
1271 status = _cairo_xlib_screen_get_visual_info (display,
1272 surface->screen,
1273 surface->visual,
1274 &visual_info);
1275 if (unlikely (status))
1276 goto BAIL;
1279 rowstride = image->stride >> 2;
1280 row = (uint32_t *) image->data;
1281 x0 = dst_x + surface->base.device_transform.x0;
1282 y0 = dst_y + surface->base.device_transform.y0;
1283 for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
1284 y < ximage.height;
1285 y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
1287 const int8_t *dither_row = dither_pattern[y_off];
1289 for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
1290 x < ximage.width;
1291 x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
1293 int dither_adjustment = dither_row[x_off];
1294 int a, r, g, b;
1296 if (image_masks.bpp == 1)
1297 in_pixel = !! (((uint8_t*)row)[x/8] & (1 << (x & 7)));
1298 else if (image_masks.bpp <= 8)
1299 in_pixel = ((uint8_t*)row)[x];
1300 else if (image_masks.bpp <= 16)
1301 in_pixel = ((uint16_t*)row)[x];
1302 else if (image_masks.bpp <= 24)
1303 #ifdef WORDS_BIGENDIAN
1304 in_pixel = ((uint8_t*)row)[3 * x] << 16 |
1305 ((uint8_t*)row)[3 * x + 1] << 8 |
1306 ((uint8_t*)row)[3 * x + 2];
1307 #else
1308 in_pixel = ((uint8_t*)row)[3 * x] |
1309 ((uint8_t*)row)[3 * x + 1] << 8 |
1310 ((uint8_t*)row)[3 * x + 2] << 16;
1311 #endif
1312 else
1313 in_pixel = row[x];
1315 /* If the incoming image has no alpha channel, then the input
1316 * is opaque and the output should have the maximum alpha value.
1317 * For all other channels, their absence implies 0.
1319 if (image_masks.alpha_mask == 0x0)
1320 a = 0xff;
1321 else
1322 a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
1323 r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
1324 g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
1325 b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
1327 if (true_color) {
1328 out_pixel = _field_from_8 (a, o_a_width, o_a_shift) |
1329 _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
1330 _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
1331 _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
1332 } else {
1333 out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
1336 XPutPixel (&ximage, x, y, out_pixel);
1339 row += rowstride;
1343 status = _cairo_xlib_surface_get_gc (display, surface, &gc);
1344 if (unlikely (status))
1345 goto BAIL;
1347 if (ximage.obdata)
1348 XShmPutImage (display->display, surface->drawable, gc, &ximage,
1349 src_x, src_y, dst_x, dst_y, width, height, True);
1350 else
1351 XPutImage (display->display, surface->drawable, gc, &ximage,
1352 src_x, src_y, dst_x, dst_y, width, height);
1354 _cairo_xlib_surface_put_gc (display, surface, gc);
1356 BAIL:
1357 cairo_device_release (&display->base);
1359 if (own_data)
1360 free (ximage.data);
1361 if (shm_image)
1362 cairo_surface_destroy (shm_image);
1363 if (pixman_image)
1364 pixman_image_unref (pixman_image);
1366 return CAIRO_STATUS_SUCCESS;
1369 static cairo_surface_t *
1370 _cairo_xlib_surface_source(void *abstract_surface,
1371 cairo_rectangle_int_t *extents)
1373 cairo_xlib_surface_t *surface = abstract_surface;
1375 if (extents) {
1376 extents->x = extents->y = 0;
1377 extents->width = surface->width;
1378 extents->height = surface->height;
1381 return &surface->base;
1384 static cairo_status_t
1385 _cairo_xlib_surface_acquire_source_image (void *abstract_surface,
1386 cairo_image_surface_t **image_out,
1387 void **image_extra)
1389 cairo_xlib_surface_t *surface = abstract_surface;
1390 cairo_rectangle_int_t extents;
1392 *image_extra = NULL;
1393 *image_out = (cairo_image_surface_t *)
1394 _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
1395 if (*image_out)
1396 return (*image_out)->base.status;
1398 extents.x = extents.y = 0;
1399 extents.width = surface->width;
1400 extents.height = surface->height;
1402 *image_out = (cairo_image_surface_t*)
1403 _get_image_surface (surface, &extents, TRUE);
1404 return (*image_out)->base.status;
1407 static cairo_surface_t *
1408 _cairo_xlib_surface_snapshot (void *abstract_surface)
1410 cairo_xlib_surface_t *surface = abstract_surface;
1411 cairo_rectangle_int_t extents;
1413 extents.x = extents.y = 0;
1414 extents.width = surface->width;
1415 extents.height = surface->height;
1417 return _get_image_surface (surface, &extents, FALSE);
1420 static void
1421 _cairo_xlib_surface_release_source_image (void *abstract_surface,
1422 cairo_image_surface_t *image,
1423 void *image_extra)
1425 cairo_xlib_surface_t *surface = abstract_surface;
1427 if (&image->base == surface->shm)
1428 return;
1430 cairo_surface_destroy (&image->base);
1433 static cairo_image_surface_t *
1434 _cairo_xlib_surface_map_to_image (void *abstract_surface,
1435 const cairo_rectangle_int_t *extents)
1437 cairo_xlib_surface_t *surface = abstract_surface;
1438 cairo_surface_t *image;
1440 image = _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
1441 if (image) {
1442 assert (surface->base.damage);
1443 surface->fallback++;
1444 return _cairo_image_surface_map_to_image (image, extents);
1447 image = _get_image_surface (abstract_surface, extents, TRUE);
1448 cairo_surface_set_device_offset (image, -extents->x, -extents->y);
1450 return (cairo_image_surface_t *) image;
1453 static cairo_int_status_t
1454 _cairo_xlib_surface_unmap_image (void *abstract_surface,
1455 cairo_image_surface_t *image)
1457 cairo_xlib_surface_t *surface = abstract_surface;
1458 cairo_int_status_t status;
1460 if (surface->shm) {
1461 cairo_rectangle_int_t r;
1463 assert (surface->fallback);
1464 assert (surface->base.damage);
1466 r.x = image->base.device_transform_inverse.x0;
1467 r.y = image->base.device_transform_inverse.y0;
1468 r.width = image->width;
1469 r.height = image->height;
1471 TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n",
1472 __FUNCTION__, r.x, r.y, r.width, r.height));
1473 surface->shm->damage =
1474 _cairo_damage_add_rectangle (surface->shm->damage, &r);
1476 return _cairo_image_surface_unmap_image (surface->shm, image);
1479 status = _cairo_xlib_surface_draw_image (abstract_surface, image,
1480 0, 0,
1481 image->width, image->height,
1482 image->base.device_transform_inverse.x0,
1483 image->base.device_transform_inverse.y0);
1485 cairo_surface_finish (&image->base);
1486 cairo_surface_destroy (&image->base);
1488 return status;
1491 static cairo_status_t
1492 _cairo_xlib_surface_flush (void *abstract_surface,
1493 unsigned flags)
1495 cairo_xlib_surface_t *surface = abstract_surface;
1496 cairo_int_status_t status;
1498 if (flags)
1499 return CAIRO_STATUS_SUCCESS;
1501 status = _cairo_xlib_surface_put_shm (surface);
1502 if (unlikely (status))
1503 return status;
1505 surface->fallback >>= 1;
1506 if (surface->shm && _cairo_xlib_shm_surface_is_idle (surface->shm))
1507 _cairo_xlib_surface_discard_shm (surface);
1509 return CAIRO_STATUS_SUCCESS;
1512 static cairo_bool_t
1513 _cairo_xlib_surface_get_extents (void *abstract_surface,
1514 cairo_rectangle_int_t *rectangle)
1516 cairo_xlib_surface_t *surface = abstract_surface;
1518 rectangle->x = 0;
1519 rectangle->y = 0;
1521 rectangle->width = surface->width;
1522 rectangle->height = surface->height;
1524 return TRUE;
1527 static void
1528 _cairo_xlib_surface_get_font_options (void *abstract_surface,
1529 cairo_font_options_t *options)
1531 cairo_xlib_surface_t *surface = abstract_surface;
1533 *options = *_cairo_xlib_screen_get_font_options (surface->screen);
1536 static inline cairo_int_status_t
1537 get_compositor (cairo_xlib_surface_t **surface,
1538 const cairo_compositor_t **compositor)
1540 cairo_xlib_surface_t *s = *surface;
1541 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;;
1543 if (s->fallback) {
1544 assert (s->base.damage != NULL);
1545 assert (s->shm != NULL);
1546 assert (s->shm->damage != NULL);
1547 if (! _cairo_xlib_shm_surface_is_active (s->shm)) {
1548 *surface = (cairo_xlib_surface_t *) s->shm;
1549 *compositor = ((cairo_image_surface_t *) s->shm)->compositor;
1550 s->fallback++;
1551 } else {
1552 status = _cairo_xlib_surface_put_shm (s);
1553 s->fallback = 0;
1554 *compositor = s->compositor;
1556 } else
1557 *compositor = s->compositor;
1559 return status;
1562 static cairo_int_status_t
1563 _cairo_xlib_surface_paint (void *_surface,
1564 cairo_operator_t op,
1565 const cairo_pattern_t *source,
1566 const cairo_clip_t *clip)
1568 cairo_xlib_surface_t *surface = _surface;
1569 const cairo_compositor_t *compositor;
1570 cairo_int_status_t status;
1572 status = get_compositor (&surface, &compositor);
1573 if (unlikely (status))
1574 return status;
1576 return _cairo_compositor_paint (compositor, &surface->base,
1577 op, source,
1578 clip);
1581 static cairo_int_status_t
1582 _cairo_xlib_surface_mask (void *_surface,
1583 cairo_operator_t op,
1584 const cairo_pattern_t *source,
1585 const cairo_pattern_t *mask,
1586 const cairo_clip_t *clip)
1588 cairo_xlib_surface_t *surface = _surface;
1589 const cairo_compositor_t *compositor;
1590 cairo_int_status_t status;
1592 status = get_compositor (&surface, &compositor);
1593 if (unlikely (status))
1594 return status;
1596 return _cairo_compositor_mask (compositor, &surface->base,
1597 op, source, mask,
1598 clip);
1601 static cairo_int_status_t
1602 _cairo_xlib_surface_stroke (void *_surface,
1603 cairo_operator_t op,
1604 const cairo_pattern_t *source,
1605 const cairo_path_fixed_t *path,
1606 const cairo_stroke_style_t *style,
1607 const cairo_matrix_t *ctm,
1608 const cairo_matrix_t *ctm_inverse,
1609 double tolerance,
1610 cairo_antialias_t antialias,
1611 const cairo_clip_t *clip)
1613 cairo_xlib_surface_t *surface = _surface;
1614 const cairo_compositor_t *compositor;
1615 cairo_int_status_t status;
1617 status = get_compositor (&surface, &compositor);
1618 if (unlikely (status))
1619 return status;
1621 return _cairo_compositor_stroke (compositor, &surface->base,
1622 op, source,
1623 path, style, ctm, ctm_inverse,
1624 tolerance, antialias,
1625 clip);
1628 static cairo_int_status_t
1629 _cairo_xlib_surface_fill (void *_surface,
1630 cairo_operator_t op,
1631 const cairo_pattern_t *source,
1632 const cairo_path_fixed_t *path,
1633 cairo_fill_rule_t fill_rule,
1634 double tolerance,
1635 cairo_antialias_t antialias,
1636 const cairo_clip_t *clip)
1638 cairo_xlib_surface_t *surface = _surface;
1639 const cairo_compositor_t *compositor;
1640 cairo_int_status_t status;
1642 status = get_compositor (&surface, &compositor);
1643 if (unlikely (status))
1644 return status;
1646 return _cairo_compositor_fill (compositor, &surface->base,
1647 op, source,
1648 path, fill_rule, tolerance, antialias,
1649 clip);
1652 static cairo_int_status_t
1653 _cairo_xlib_surface_glyphs (void *_surface,
1654 cairo_operator_t op,
1655 const cairo_pattern_t *source,
1656 cairo_glyph_t *glyphs,
1657 int num_glyphs,
1658 cairo_scaled_font_t *scaled_font,
1659 const cairo_clip_t *clip)
1661 cairo_xlib_surface_t *surface = _surface;
1662 const cairo_compositor_t *compositor;
1663 cairo_int_status_t status;
1665 status = get_compositor (&surface, &compositor);
1666 if (unlikely (status))
1667 return status;
1669 return _cairo_compositor_glyphs (compositor, &surface->base,
1670 op, source,
1671 glyphs, num_glyphs, scaled_font,
1672 clip);
1675 static const cairo_surface_backend_t cairo_xlib_surface_backend = {
1676 CAIRO_SURFACE_TYPE_XLIB,
1677 _cairo_xlib_surface_finish,
1679 _cairo_default_context_create,
1681 _cairo_xlib_surface_create_similar,
1682 _cairo_xlib_surface_create_similar_shm,
1683 _cairo_xlib_surface_map_to_image,
1684 _cairo_xlib_surface_unmap_image,
1686 _cairo_xlib_surface_source,
1687 _cairo_xlib_surface_acquire_source_image,
1688 _cairo_xlib_surface_release_source_image,
1689 _cairo_xlib_surface_snapshot,
1691 NULL, /* copy_page */
1692 NULL, /* show_page */
1694 _cairo_xlib_surface_get_extents,
1695 _cairo_xlib_surface_get_font_options,
1697 _cairo_xlib_surface_flush,
1698 NULL, /* mark_dirty_rectangle */
1700 _cairo_xlib_surface_paint,
1701 _cairo_xlib_surface_mask,
1702 _cairo_xlib_surface_stroke,
1703 _cairo_xlib_surface_fill,
1704 NULL, /* fill-stroke */
1705 _cairo_xlib_surface_glyphs,
1709 * _cairo_surface_is_xlib:
1710 * @surface: a #cairo_surface_t
1712 * Checks if a surface is a #cairo_xlib_surface_t
1714 * Return value: True if the surface is an xlib surface
1716 static cairo_bool_t
1717 _cairo_surface_is_xlib (cairo_surface_t *surface)
1719 return surface->backend == &cairo_xlib_surface_backend;
1722 static cairo_surface_t *
1723 _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
1724 Drawable drawable,
1725 Visual *visual,
1726 XRenderPictFormat *xrender_format,
1727 int width,
1728 int height,
1729 int depth)
1731 cairo_xlib_surface_t *surface;
1732 cairo_xlib_display_t *display;
1733 cairo_status_t status;
1735 if (depth == 0) {
1736 if (xrender_format) {
1737 depth = xrender_format->depth;
1739 /* XXX find matching visual for core/dithering fallbacks? */
1740 } else if (visual) {
1741 Screen *scr = screen->screen;
1743 if (visual == DefaultVisualOfScreen (scr)) {
1744 depth = DefaultDepthOfScreen (scr);
1745 } else {
1746 int j, k;
1748 /* This is ugly, but we have to walk over all visuals
1749 * for the display to find the correct depth.
1751 depth = 0;
1752 for (j = 0; j < scr->ndepths; j++) {
1753 Depth *d = &scr->depths[j];
1754 for (k = 0; k < d->nvisuals; k++) {
1755 if (&d->visuals[k] == visual) {
1756 depth = d->depth;
1757 goto found;
1764 if (depth == 0)
1765 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1767 found:
1771 surface = malloc (sizeof (cairo_xlib_surface_t));
1772 if (unlikely (surface == NULL))
1773 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1775 status = _cairo_xlib_display_acquire (screen->device, &display);
1776 if (unlikely (status)) {
1777 free (surface);
1778 return _cairo_surface_create_in_error (_cairo_error (status));
1781 surface->display = display;
1782 if (CAIRO_RENDER_HAS_CREATE_PICTURE (display)) {
1783 if (!xrender_format) {
1784 if (visual) {
1785 xrender_format = XRenderFindVisualFormat (display->display, visual);
1786 } else if (depth == 1) {
1787 xrender_format =
1788 _cairo_xlib_display_get_xrender_format (display,
1789 CAIRO_FORMAT_A1);
1794 cairo_device_release (&display->base);
1796 _cairo_surface_init (&surface->base,
1797 &cairo_xlib_surface_backend,
1798 screen->device,
1799 _xrender_format_to_content (xrender_format));
1801 surface->screen = screen;
1802 surface->compositor = display->compositor;
1803 surface->shm = NULL;
1804 surface->fallback = 0;
1806 surface->drawable = drawable;
1807 surface->owns_pixmap = FALSE;
1808 surface->use_pixmap = 0;
1809 surface->width = width;
1810 surface->height = height;
1812 surface->picture = None;
1813 surface->precision = PolyModePrecise;
1815 surface->embedded_source.picture = None;
1817 surface->visual = visual;
1818 surface->xrender_format = xrender_format;
1819 surface->depth = depth;
1822 * Compute the pixel format masks from either a XrenderFormat or
1823 * else from a visual; failing that we assume the drawable is an
1824 * alpha-only pixmap as it could only have been created that way
1825 * through the cairo_xlib_surface_create_for_bitmap function.
1827 if (xrender_format) {
1828 surface->a_mask = (unsigned long)
1829 surface->xrender_format->direct.alphaMask
1830 << surface->xrender_format->direct.alpha;
1831 surface->r_mask = (unsigned long)
1832 surface->xrender_format->direct.redMask
1833 << surface->xrender_format->direct.red;
1834 surface->g_mask = (unsigned long)
1835 surface->xrender_format->direct.greenMask
1836 << surface->xrender_format->direct.green;
1837 surface->b_mask = (unsigned long)
1838 surface->xrender_format->direct.blueMask
1839 << surface->xrender_format->direct.blue;
1840 } else if (visual) {
1841 surface->a_mask = 0;
1842 surface->r_mask = visual->red_mask;
1843 surface->g_mask = visual->green_mask;
1844 surface->b_mask = visual->blue_mask;
1845 } else {
1846 if (depth < 32)
1847 surface->a_mask = (1 << depth) - 1;
1848 else
1849 surface->a_mask = 0xffffffff;
1850 surface->r_mask = 0;
1851 surface->g_mask = 0;
1852 surface->b_mask = 0;
1855 cairo_list_add (&surface->link, &screen->surfaces);
1857 return &surface->base;
1860 static Screen *
1861 _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
1863 int s, d, v;
1865 for (s = 0; s < ScreenCount (dpy); s++) {
1866 Screen *screen;
1868 screen = ScreenOfDisplay (dpy, s);
1869 if (visual == DefaultVisualOfScreen (screen))
1870 return screen;
1872 for (d = 0; d < screen->ndepths; d++) {
1873 Depth *depth;
1875 depth = &screen->depths[d];
1876 for (v = 0; v < depth->nvisuals; v++)
1877 if (visual == &depth->visuals[v])
1878 return screen;
1882 return NULL;
1885 static cairo_bool_t valid_size (int width, int height)
1887 /* Note: the minimum surface size allowed in the X protocol is 1x1.
1888 * However, as we historically did not check the minimum size we
1889 * allowed applications to lie and set the correct size later (one hopes).
1890 * To preserve compatability we must allow applications to use
1891 * 0x0 surfaces.
1893 return (width >= 0 && width <= XLIB_COORD_MAX &&
1894 height >= 0 && height <= XLIB_COORD_MAX);
1898 * cairo_xlib_surface_create:
1899 * @dpy: an X Display
1900 * @drawable: an X Drawable, (a Pixmap or a Window)
1901 * @visual: the visual to use for drawing to @drawable. The depth
1902 * of the visual must match the depth of the drawable.
1903 * Currently, only TrueColor visuals are fully supported.
1904 * @width: the current width of @drawable.
1905 * @height: the current height of @drawable.
1907 * Creates an Xlib surface that draws to the given drawable.
1908 * The way that colors are represented in the drawable is specified
1909 * by the provided visual.
1911 * Note: If @drawable is a Window, then the function
1912 * cairo_xlib_surface_set_size() must be called whenever the size of the
1913 * window changes.
1915 * When @drawable is a Window containing child windows then drawing to
1916 * the created surface will be clipped by those child windows. When
1917 * the created surface is used as a source, the contents of the
1918 * children will be included.
1920 * Return value: the newly created surface
1922 * Since: 1.0
1924 cairo_surface_t *
1925 cairo_xlib_surface_create (Display *dpy,
1926 Drawable drawable,
1927 Visual *visual,
1928 int width,
1929 int height)
1931 Screen *scr;
1932 cairo_xlib_screen_t *screen;
1933 cairo_status_t status;
1935 if (! valid_size (width, height)) {
1936 /* you're lying, and you know it! */
1937 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1940 scr = _cairo_xlib_screen_from_visual (dpy, visual);
1941 if (scr == NULL)
1942 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1944 status = _cairo_xlib_screen_get (dpy, scr, &screen);
1945 if (unlikely (status))
1946 return _cairo_surface_create_in_error (status);
1948 X_DEBUG ((dpy, "create (drawable=%x)", (unsigned int) drawable));
1950 return _cairo_xlib_surface_create_internal (screen, drawable,
1951 visual, NULL,
1952 width, height, 0);
1956 * cairo_xlib_surface_create_for_bitmap:
1957 * @dpy: an X Display
1958 * @bitmap: an X Drawable, (a depth-1 Pixmap)
1959 * @screen: the X Screen associated with @bitmap
1960 * @width: the current width of @bitmap.
1961 * @height: the current height of @bitmap.
1963 * Creates an Xlib surface that draws to the given bitmap.
1964 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1966 * Return value: the newly created surface
1968 * Since: 1.0
1970 cairo_surface_t *
1971 cairo_xlib_surface_create_for_bitmap (Display *dpy,
1972 Pixmap bitmap,
1973 Screen *scr,
1974 int width,
1975 int height)
1977 cairo_xlib_screen_t *screen;
1978 cairo_status_t status;
1980 if (! valid_size (width, height))
1981 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1983 status = _cairo_xlib_screen_get (dpy, scr, &screen);
1984 if (unlikely (status))
1985 return _cairo_surface_create_in_error (status);
1987 X_DEBUG ((dpy, "create_for_bitmap (drawable=%x)", (unsigned int) bitmap));
1989 return _cairo_xlib_surface_create_internal (screen, bitmap,
1990 NULL, NULL,
1991 width, height, 1);
1994 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
1996 * cairo_xlib_surface_create_with_xrender_format:
1997 * @dpy: an X Display
1998 * @drawable: an X Drawable, (a Pixmap or a Window)
1999 * @screen: the X Screen associated with @drawable
2000 * @format: the picture format to use for drawing to @drawable. The depth
2001 * of @format must match the depth of the drawable.
2002 * @width: the current width of @drawable.
2003 * @height: the current height of @drawable.
2005 * Creates an Xlib surface that draws to the given drawable.
2006 * The way that colors are represented in the drawable is specified
2007 * by the provided picture format.
2009 * Note: If @drawable is a Window, then the function
2010 * cairo_xlib_surface_set_size() must be called whenever the size of the
2011 * window changes.
2013 * Return value: the newly created surface
2015 * Since: 1.0
2017 cairo_surface_t *
2018 cairo_xlib_surface_create_with_xrender_format (Display *dpy,
2019 Drawable drawable,
2020 Screen *scr,
2021 XRenderPictFormat *format,
2022 int width,
2023 int height)
2025 cairo_xlib_screen_t *screen;
2026 cairo_status_t status;
2028 if (! valid_size (width, height))
2029 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
2031 status = _cairo_xlib_screen_get (dpy, scr, &screen);
2032 if (unlikely (status))
2033 return _cairo_surface_create_in_error (status);
2035 X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
2037 return _cairo_xlib_surface_create_internal (screen, drawable,
2038 _visual_for_xrender_format (scr, format),
2039 format, width, height, 0);
2043 * cairo_xlib_surface_get_xrender_format:
2044 * @surface: an xlib surface
2046 * Gets the X Render picture format that @surface uses for rendering with the
2047 * X Render extension. If the surface was created by
2048 * cairo_xlib_surface_create_with_xrender_format() originally, the return
2049 * value is the format passed to that constructor.
2051 * Return value: the XRenderPictFormat* associated with @surface,
2052 * or %NULL if the surface is not an xlib surface
2053 * or if the X Render extension is not available.
2055 * Since: 1.6
2057 XRenderPictFormat *
2058 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
2060 cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
2062 /* Throw an error for a non-xlib surface */
2063 if (! _cairo_surface_is_xlib (surface)) {
2064 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2065 return NULL;
2068 return xlib_surface->xrender_format;
2070 #endif
2073 * cairo_xlib_surface_set_size:
2074 * @surface: a #cairo_surface_t for the XLib backend
2075 * @width: the new width of the surface
2076 * @height: the new height of the surface
2078 * Informs cairo of the new size of the X Drawable underlying the
2079 * surface. For a surface created for a Window (rather than a Pixmap),
2080 * this function must be called each time the size of the window
2081 * changes. (For a subwindow, you are normally resizing the window
2082 * yourself, but for a toplevel window, it is necessary to listen for
2083 * ConfigureNotify events.)
2085 * A Pixmap can never change size, so it is never necessary to call
2086 * this function on a surface created for a Pixmap.
2088 * Since: 1.0
2090 void
2091 cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
2092 int width,
2093 int height)
2095 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2096 cairo_status_t status;
2098 if (unlikely (abstract_surface->status))
2099 return;
2100 if (unlikely (abstract_surface->finished)) {
2101 _cairo_surface_set_error (abstract_surface,
2102 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
2103 return;
2106 if (! _cairo_surface_is_xlib (abstract_surface)) {
2107 _cairo_surface_set_error (abstract_surface,
2108 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
2109 return;
2112 if (surface->width == width && surface->height == height)
2113 return;
2115 if (! valid_size (width, height)) {
2116 _cairo_surface_set_error (abstract_surface,
2117 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
2118 return;
2121 status = _cairo_surface_flush (abstract_surface, 0);
2122 if (unlikely (status)) {
2123 _cairo_surface_set_error (abstract_surface, status);
2124 return;
2127 _cairo_xlib_surface_discard_shm (surface);
2129 surface->width = width;
2130 surface->height = height;
2134 * cairo_xlib_surface_set_drawable:
2135 * @surface: a #cairo_surface_t for the XLib backend
2136 * @drawable: the new drawable for the surface
2137 * @width: the width of the new drawable
2138 * @height: the height of the new drawable
2140 * Informs cairo of a new X Drawable underlying the
2141 * surface. The drawable must match the display, screen
2142 * and format of the existing drawable or the application
2143 * will get X protocol errors and will probably terminate.
2144 * No checks are done by this function to ensure this
2145 * compatibility.
2147 * Since: 1.0
2149 void
2150 cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
2151 Drawable drawable,
2152 int width,
2153 int height)
2155 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
2156 cairo_status_t status;
2158 if (unlikely (abstract_surface->status))
2159 return;
2160 if (unlikely (abstract_surface->finished)) {
2161 status = _cairo_surface_set_error (abstract_surface,
2162 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
2163 return;
2166 if (! _cairo_surface_is_xlib (abstract_surface)) {
2167 status = _cairo_surface_set_error (abstract_surface,
2168 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
2169 return;
2172 if (! valid_size (width, height)) {
2173 status = _cairo_surface_set_error (abstract_surface,
2174 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
2175 return;
2178 /* XXX: and what about this case? */
2179 if (surface->owns_pixmap)
2180 return;
2182 status = _cairo_surface_flush (abstract_surface, 0);
2183 if (unlikely (status)) {
2184 _cairo_surface_set_error (abstract_surface, status);
2185 return;
2188 if (surface->drawable != drawable) {
2189 cairo_xlib_display_t *display;
2191 status = _cairo_xlib_display_acquire (surface->base.device, &display);
2192 if (unlikely (status))
2193 return;
2195 X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable));
2197 if (surface->picture != None) {
2198 XRenderFreePicture (display->display, surface->picture);
2199 if (unlikely (status)) {
2200 status = _cairo_surface_set_error (&surface->base, status);
2201 return;
2204 surface->picture = None;
2207 cairo_device_release (&display->base);
2209 surface->drawable = drawable;
2212 if (surface->width != width || surface->height != height) {
2213 _cairo_xlib_surface_discard_shm (surface);
2215 surface->width = width;
2216 surface->height = height;
2221 * cairo_xlib_surface_get_display:
2222 * @surface: a #cairo_xlib_surface_t
2224 * Get the X Display for the underlying X Drawable.
2226 * Return value: the display.
2228 * Since: 1.2
2230 Display *
2231 cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
2233 if (! _cairo_surface_is_xlib (abstract_surface)) {
2234 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2235 return NULL;
2238 return ((cairo_xlib_display_t *) abstract_surface->device)->display;
2242 * cairo_xlib_surface_get_drawable:
2243 * @surface: a #cairo_xlib_surface_t
2245 * Get the underlying X Drawable used for the surface.
2247 * Return value: the drawable.
2249 * Since: 1.2
2251 Drawable
2252 cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
2254 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2256 if (! _cairo_surface_is_xlib (abstract_surface)) {
2257 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2258 return 0;
2261 return surface->drawable;
2265 * cairo_xlib_surface_get_screen:
2266 * @surface: a #cairo_xlib_surface_t
2268 * Get the X Screen for the underlying X Drawable.
2270 * Return value: the screen.
2272 * Since: 1.2
2274 Screen *
2275 cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
2277 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2279 if (! _cairo_surface_is_xlib (abstract_surface)) {
2280 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2281 return NULL;
2284 return surface->screen->screen;
2288 * cairo_xlib_surface_get_visual:
2289 * @surface: a #cairo_xlib_surface_t
2291 * Gets the X Visual associated with @surface, suitable for use with the
2292 * underlying X Drawable. If @surface was created by
2293 * cairo_xlib_surface_create(), the return value is the Visual passed to that
2294 * constructor.
2296 * Return value: the Visual or %NULL if there is no appropriate Visual for
2297 * @surface.
2299 * Since: 1.2
2301 Visual *
2302 cairo_xlib_surface_get_visual (cairo_surface_t *surface)
2304 cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
2306 if (! _cairo_surface_is_xlib (surface)) {
2307 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2308 return NULL;
2311 return xlib_surface->visual;
2315 * cairo_xlib_surface_get_depth:
2316 * @surface: a #cairo_xlib_surface_t
2318 * Get the number of bits used to represent each pixel value.
2320 * Return value: the depth of the surface in bits.
2322 * Since: 1.2
2325 cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
2327 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2329 if (! _cairo_surface_is_xlib (abstract_surface)) {
2330 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2331 return 0;
2334 return surface->depth;
2338 * cairo_xlib_surface_get_width:
2339 * @surface: a #cairo_xlib_surface_t
2341 * Get the width of the X Drawable underlying the surface in pixels.
2343 * Return value: the width of the surface in pixels.
2345 * Since: 1.2
2348 cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
2350 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2352 if (! _cairo_surface_is_xlib (abstract_surface)) {
2353 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2354 return 0;
2357 return surface->width;
2361 * cairo_xlib_surface_get_height:
2362 * @surface: a #cairo_xlib_surface_t
2364 * Get the height of the X Drawable underlying the surface in pixels.
2366 * Return value: the height of the surface in pixels.
2368 * Since: 1.2
2371 cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
2373 cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2375 if (! _cairo_surface_is_xlib (abstract_surface)) {
2376 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2377 return 0;
2380 return surface->height;
2383 #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */