1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2002 University of Southern California
4 * Copyright © 2009 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is University of Southern
35 * Behdad Esfahbod <behdad@behdad.org>
36 * Carl D. Worth <cworth@cworth.org>
37 * Chris Wilson <chris@chris-wilson.co.uk>
38 * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
43 #include "cairo-xcb.h"
44 #include "cairo-xcb-private.h"
46 #include "cairo-composite-rectangles-private.h"
47 #include "cairo-default-context-private.h"
48 #include "cairo-image-surface-inline.h"
49 #include "cairo-list-inline.h"
50 #include "cairo-surface-backend-private.h"
51 #include "cairo-compositor-private.h"
53 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
54 slim_hidden_proto (cairo_xcb_surface_create);
55 slim_hidden_proto (cairo_xcb_surface_create_for_bitmap);
56 slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format);
61 * @Title: XCB Surfaces
62 * @Short_Description: X Window System rendering using the XCB library
63 * @See_Also: #cairo_surface_t
65 * The XCB surface is used to render cairo graphics to X Window System
66 * windows and pixmaps using the XCB library.
68 * Note that the XCB surface automatically takes advantage of the X render
69 * extension if it is available.
73 * CAIRO_HAS_XCB_SURFACE:
75 * Defined if the xcb surface backend is available.
76 * This macro can be used to conditionally compile backend-specific code.
82 _cairo_xcb_surface_create_similar (void *abstract_other,
83 cairo_content_t content,
87 cairo_xcb_surface_t *other = abstract_other;
88 cairo_xcb_surface_t *surface;
89 cairo_xcb_connection_t *connection;
91 cairo_status_t status;
93 if (unlikely(width > XLIB_COORD_MAX ||
94 height > XLIB_COORD_MAX ||
97 return cairo_image_surface_create (_cairo_format_from_content (content),
100 if ((other->connection->flags & CAIRO_XCB_HAS_RENDER) == 0)
101 return _cairo_xcb_surface_create_similar_image (other,
102 _cairo_format_from_content (content),
105 connection = other->connection;
106 status = _cairo_xcb_connection_acquire (connection);
107 if (unlikely (status))
108 return _cairo_surface_create_in_error (status);
110 if (content == other->base.content) {
111 pixmap = _cairo_xcb_connection_create_pixmap (connection,
116 surface = (cairo_xcb_surface_t *)
117 _cairo_xcb_surface_create_internal (other->screen,
119 other->pixman_format,
120 other->xrender_format,
123 cairo_format_t format;
124 pixman_format_code_t pixman_format;
126 /* XXX find a compatible xrender format */
128 case CAIRO_CONTENT_ALPHA:
129 pixman_format = PIXMAN_a8;
130 format = CAIRO_FORMAT_A8;
132 case CAIRO_CONTENT_COLOR:
133 pixman_format = PIXMAN_x8r8g8b8;
134 format = CAIRO_FORMAT_RGB24;
138 case CAIRO_CONTENT_COLOR_ALPHA:
139 pixman_format = PIXMAN_a8r8g8b8;
140 format = CAIRO_FORMAT_ARGB32;
144 pixmap = _cairo_xcb_connection_create_pixmap (connection,
145 PIXMAN_FORMAT_DEPTH (pixman_format),
149 surface = (cairo_xcb_surface_t *)
150 _cairo_xcb_surface_create_internal (other->screen,
153 connection->standard_formats[format],
157 if (unlikely (surface->base.status))
158 _cairo_xcb_connection_free_pixmap (connection, pixmap);
160 _cairo_xcb_connection_release (connection);
162 return &surface->base;
166 _cairo_xcb_surface_create_similar_image (void *abstract_other,
167 cairo_format_t format,
171 cairo_xcb_surface_t *other = abstract_other;
172 cairo_xcb_connection_t *connection = other->connection;
174 cairo_xcb_shm_info_t *shm_info;
175 cairo_image_surface_t *image;
176 cairo_status_t status;
177 pixman_format_code_t pixman_format;
179 if (unlikely(width > XLIB_COORD_MAX ||
180 height > XLIB_COORD_MAX ||
185 pixman_format = _cairo_format_to_pixman_format_code (format);
187 status = _cairo_xcb_shm_image_create (connection, pixman_format,
188 width, height, &image,
190 if (unlikely (status))
191 return _cairo_surface_create_in_error (status);
193 if (! image->base.is_clear) {
194 memset (image->data, 0, image->stride * image->height);
195 image->base.is_clear = TRUE;
201 static cairo_status_t
202 _cairo_xcb_surface_finish (void *abstract_surface)
204 cairo_xcb_surface_t *surface = abstract_surface;
205 cairo_status_t status;
207 if (surface->fallback != NULL) {
208 cairo_surface_finish (&surface->fallback->base);
209 cairo_surface_destroy (&surface->fallback->base);
211 _cairo_boxes_fini (&surface->fallback_damage);
213 cairo_list_del (&surface->link);
215 status = _cairo_xcb_connection_acquire (surface->connection);
216 if (status == CAIRO_STATUS_SUCCESS) {
217 if (surface->picture != XCB_NONE) {
218 _cairo_xcb_connection_render_free_picture (surface->connection,
222 if (surface->owns_pixmap)
223 _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
224 _cairo_xcb_connection_release (surface->connection);
227 _cairo_xcb_connection_destroy (surface->connection);
233 _destroy_image (pixman_image_t *image, void *data)
238 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
239 static cairo_surface_t *
240 _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection,
241 pixman_format_code_t pixman_format,
242 int width, int height,
243 cairo_bool_t might_reuse,
244 cairo_xcb_shm_info_t **shm_info_out)
246 cairo_surface_t *image;
247 cairo_xcb_shm_info_t *shm_info;
248 cairo_int_status_t status;
251 *shm_info_out = NULL;
253 stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
254 PIXMAN_FORMAT_BPP (pixman_format));
255 status = _cairo_xcb_connection_allocate_shm_info (connection,
259 if (unlikely (status)) {
260 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
263 return _cairo_surface_create_in_error (status);
266 image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
270 if (unlikely (image->status)) {
271 _cairo_xcb_shm_info_destroy (shm_info);
275 status = _cairo_user_data_array_set_data (&image->user_data,
276 (const cairo_user_data_key_t *) connection,
278 (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
279 if (unlikely (status)) {
280 cairo_surface_destroy (image);
281 _cairo_xcb_shm_info_destroy (shm_info);
282 return _cairo_surface_create_in_error (status);
285 *shm_info_out = shm_info;
290 static cairo_surface_t *
291 _get_shm_image (cairo_xcb_surface_t *surface,
293 int width, int height)
295 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
296 cairo_xcb_shm_info_t *shm_info;
297 cairo_surface_t *image;
298 cairo_status_t status;
300 if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
303 image = _cairo_xcb_surface_create_shm_image (surface->connection,
304 surface->pixman_format,
308 if (unlikely (image == NULL || image->status))
311 status = _cairo_xcb_connection_shm_get_image (surface->connection,
317 if (unlikely (status)) {
318 cairo_surface_destroy (image);
319 image = _cairo_surface_create_in_error (status);
329 static cairo_surface_t *
330 _get_image (cairo_xcb_surface_t *surface,
331 cairo_bool_t use_shm,
333 int width, int height)
335 cairo_surface_t *image;
336 cairo_xcb_connection_t *connection;
337 xcb_get_image_reply_t *reply;
338 cairo_int_status_t status;
340 assert (surface->fallback == NULL);
343 assert (x + width <= surface->width);
344 assert (y + height <= surface->height);
346 if (surface->deferred_clear) {
348 _cairo_image_surface_create_with_pixman_format (NULL,
349 surface->pixman_format,
352 if (surface->deferred_clear_color.alpha_short > 0x00ff) {
353 cairo_solid_pattern_t solid;
355 _cairo_pattern_init_solid (&solid, &surface->deferred_clear_color);
356 status = _cairo_surface_paint (image,
357 CAIRO_OPERATOR_SOURCE,
360 if (unlikely (status)) {
361 cairo_surface_destroy (image);
362 image = _cairo_surface_create_in_error (status);
368 connection = surface->connection;
370 status = _cairo_xcb_connection_acquire (connection);
371 if (unlikely (status))
372 return _cairo_surface_create_in_error (status);
375 image = _get_shm_image (surface, x, y, width, height);
377 if (image->status == CAIRO_STATUS_SUCCESS) {
378 _cairo_xcb_connection_release (connection);
381 cairo_surface_destroy (image);
385 status = _cairo_xcb_connection_get_image (connection,
390 if (unlikely (status))
393 if (reply == NULL && ! surface->owns_pixmap) {
394 /* xcb_get_image_t from a window is dangerous because it can
395 * produce errors if the window is unmapped or partially
396 * outside the screen. We could check for errors and
397 * retry, but to keep things simple, we just create a
400 * If we hit this fallback too often, we should remember so and
401 * skip the round-trip from the above GetImage request,
402 * similar to what cairo-xlib does.
407 gc = _cairo_xcb_screen_get_gc (surface->screen,
410 pixmap = _cairo_xcb_connection_create_pixmap (connection,
415 /* XXX IncludeInferiors? */
416 _cairo_xcb_connection_copy_area (connection,
423 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
425 status = _cairo_xcb_connection_get_image (connection,
430 _cairo_xcb_connection_free_pixmap (connection, pixmap);
432 if (unlikely (status))
436 if (unlikely (reply == NULL)) {
437 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
442 /* XXX format conversion */
443 assert (reply->depth == surface->depth);
445 image = _cairo_image_surface_create_with_pixman_format
446 (xcb_get_image_data (reply),
447 surface->pixman_format,
449 CAIRO_STRIDE_FOR_WIDTH_BPP (width,
450 PIXMAN_FORMAT_BPP (surface->pixman_format)));
451 status = image->status;
452 if (unlikely (status)) {
458 pixman_image_set_destroy_function (((cairo_image_surface_t *)image)->pixman_image, _destroy_image, reply);
460 _cairo_xcb_connection_release (connection);
465 _cairo_xcb_connection_release (connection);
466 return _cairo_surface_create_in_error (status);
469 static cairo_surface_t *
470 _cairo_xcb_surface_source (void *abstract_surface,
471 cairo_rectangle_int_t *extents)
473 cairo_xcb_surface_t *surface = abstract_surface;
476 extents->x = extents->y = 0;
477 extents->width = surface->width;
478 extents->height = surface->height;
481 return &surface->base;
484 static cairo_status_t
485 _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
486 cairo_image_surface_t **image_out,
489 cairo_xcb_surface_t *surface = abstract_surface;
490 cairo_surface_t *image;
492 if (surface->fallback != NULL) {
493 image = cairo_surface_reference (&surface->fallback->base);
497 image = _cairo_surface_has_snapshot (&surface->base,
498 &_cairo_image_surface_backend);
500 image = cairo_surface_reference (image);
504 image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
505 if (unlikely (image->status))
506 return image->status;
508 _cairo_surface_attach_snapshot (&surface->base, image, NULL);
511 *image_out = (cairo_image_surface_t *) image;
513 return CAIRO_STATUS_SUCCESS;
517 _cairo_xcb_surface_release_source_image (void *abstract_surface,
518 cairo_image_surface_t *image,
521 cairo_surface_destroy (&image->base);
525 _cairo_xcb_surface_get_extents (void *abstract_surface,
526 cairo_rectangle_int_t *extents)
528 cairo_xcb_surface_t *surface = abstract_surface;
530 extents->x = extents->y = 0;
531 extents->width = surface->width;
532 extents->height = surface->height;
537 _cairo_xcb_surface_get_font_options (void *abstract_surface,
538 cairo_font_options_t *options)
540 /* XXX copy from xlib */
541 _cairo_font_options_init_default (options);
542 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
545 static cairo_status_t
546 _put_shm_image (cairo_xcb_surface_t *surface,
548 cairo_image_surface_t *image)
550 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
551 cairo_xcb_shm_info_t *shm_info;
553 shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
554 (const cairo_user_data_key_t *) surface->connection);
555 if (shm_info == NULL)
556 return CAIRO_INT_STATUS_UNSUPPORTED;
558 _cairo_xcb_connection_shm_put_image (surface->connection,
561 surface->width, surface->height,
563 image->width, image->height,
564 image->base.device_transform_inverse.x0,
565 image->base.device_transform_inverse.y0,
570 return CAIRO_STATUS_SUCCESS;
572 return CAIRO_INT_STATUS_UNSUPPORTED;
576 static cairo_status_t
577 _put_image (cairo_xcb_surface_t *surface,
578 cairo_image_surface_t *image)
580 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
582 /* XXX track damaged region? */
584 status = _cairo_xcb_connection_acquire (surface->connection);
585 if (unlikely (status))
588 if (image->pixman_format == surface->pixman_format) {
591 assert (image->depth == surface->depth);
592 assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
594 gc = _cairo_xcb_screen_get_gc (surface->screen,
598 status = _put_shm_image (surface, gc, image);
599 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
600 _cairo_xcb_connection_put_image (surface->connection,
601 surface->drawable, gc,
602 image->width, image->height,
603 image->base.device_transform_inverse.x0,
604 image->base.device_transform_inverse.y0,
608 status = CAIRO_STATUS_SUCCESS;
611 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
616 _cairo_xcb_connection_release (surface->connection);
620 static cairo_int_status_t
621 _put_shm_image_boxes (cairo_xcb_surface_t *surface,
622 cairo_image_surface_t *image,
624 cairo_boxes_t *boxes)
626 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
627 cairo_xcb_shm_info_t *shm_info;
629 shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
630 (const cairo_user_data_key_t *) surface->connection);
631 if (shm_info != NULL) {
632 struct _cairo_boxes_chunk *chunk;
634 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
637 for (i = 0; i < chunk->count; i++) {
638 cairo_box_t *b = &chunk->base[i];
639 int x = _cairo_fixed_integer_part (b->p1.x);
640 int y = _cairo_fixed_integer_part (b->p1.y);
641 int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
642 int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
644 _cairo_xcb_connection_shm_put_image (surface->connection,
647 surface->width, surface->height,
658 return CAIRO_INT_STATUS_SUCCESS;
661 return CAIRO_INT_STATUS_UNSUPPORTED;
664 static cairo_status_t
665 _put_image_boxes (cairo_xcb_surface_t *surface,
666 cairo_image_surface_t *image,
667 cairo_boxes_t *boxes)
669 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
672 if (boxes->num_boxes == 0)
673 return CAIRO_STATUS_SUCCESS;
675 /* XXX track damaged region? */
677 status = _cairo_xcb_connection_acquire (surface->connection);
678 if (unlikely (status))
681 assert (image->pixman_format == surface->pixman_format);
682 assert (image->depth == surface->depth);
683 assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
685 gc = _cairo_xcb_screen_get_gc (surface->screen,
689 status = _put_shm_image_boxes (surface, image, gc, boxes);
690 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
691 struct _cairo_boxes_chunk *chunk;
693 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
696 for (i = 0; i < chunk->count; i++) {
697 cairo_box_t *b = &chunk->base[i];
698 int x = _cairo_fixed_integer_part (b->p1.x);
699 int y = _cairo_fixed_integer_part (b->p1.y);
700 int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
701 int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
702 _cairo_xcb_connection_put_image (surface->connection,
703 surface->drawable, gc,
709 x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 +
714 status = CAIRO_STATUS_SUCCESS;
717 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
718 _cairo_xcb_connection_release (surface->connection);
722 static cairo_status_t
723 _cairo_xcb_surface_flush (void *abstract_surface,
726 cairo_xcb_surface_t *surface = abstract_surface;
727 cairo_status_t status;
730 return CAIRO_STATUS_SUCCESS;
732 if (likely (surface->fallback == NULL)) {
733 status = CAIRO_STATUS_SUCCESS;
734 if (! surface->base.finished && surface->deferred_clear)
735 status = _cairo_xcb_surface_clear (surface);
740 status = surface->base.status;
741 if (status == CAIRO_STATUS_SUCCESS &&
742 (! surface->base._finishing || ! surface->owns_pixmap)) {
743 status = cairo_surface_status (&surface->fallback->base);
745 if (status == CAIRO_STATUS_SUCCESS)
746 status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
747 CAIRO_FILL_RULE_WINDING,
748 &surface->fallback_damage);
750 if (status == CAIRO_STATUS_SUCCESS)
751 status = _put_image_boxes (surface,
753 &surface->fallback_damage);
755 if (status == CAIRO_STATUS_SUCCESS && ! surface->base._finishing) {
756 _cairo_surface_attach_snapshot (&surface->base,
757 &surface->fallback->base,
758 cairo_surface_finish);
762 _cairo_boxes_clear (&surface->fallback_damage);
763 cairo_surface_destroy (&surface->fallback->base);
764 surface->fallback = NULL;
769 static cairo_image_surface_t *
770 _cairo_xcb_surface_map_to_image (void *abstract_surface,
771 const cairo_rectangle_int_t *extents)
773 cairo_xcb_surface_t *surface = abstract_surface;
774 cairo_surface_t *image;
775 cairo_status_t status;
777 if (surface->fallback)
778 return _cairo_surface_map_to_image (&surface->fallback->base, extents);
780 image = _get_image (surface, TRUE,
781 extents->x, extents->y,
782 extents->width, extents->height);
783 status = cairo_surface_status (image);
784 if (unlikely (status)) {
785 cairo_surface_destroy(image);
786 return _cairo_image_surface_create_in_error (status);
789 /* Do we have a deferred clear and this image surface does NOT cover the
790 * whole xcb surface? Have to apply the clear in that case, else
791 * uploading the image will handle the problem for us.
793 if (surface->deferred_clear &&
794 ! (extents->width == surface->width &&
795 extents->height == surface->height)) {
796 status = _cairo_xcb_surface_clear (surface);
797 if (unlikely (status)) {
798 cairo_surface_destroy(image);
799 return _cairo_image_surface_create_in_error (status);
802 surface->deferred_clear = FALSE;
804 cairo_surface_set_device_offset (image, -extents->x, -extents->y);
805 return (cairo_image_surface_t *) image;
808 static cairo_int_status_t
809 _cairo_xcb_surface_unmap (void *abstract_surface,
810 cairo_image_surface_t *image)
812 cairo_xcb_surface_t *surface = abstract_surface;
813 cairo_int_status_t status;
815 if (surface->fallback)
816 return _cairo_surface_unmap_image (&surface->fallback->base, image);
818 status = _put_image (abstract_surface, image);
820 cairo_surface_finish (&image->base);
821 cairo_surface_destroy (&image->base);
826 static cairo_surface_t *
827 _cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface,
828 cairo_composite_rectangles_t *composite)
830 cairo_image_surface_t *image;
831 cairo_status_t status;
833 status = _cairo_composite_rectangles_add_to_damage (composite,
834 &surface->fallback_damage);
835 if (unlikely (status))
836 return _cairo_surface_create_in_error (status);
838 if (surface->fallback)
839 return &surface->fallback->base;
841 image = (cairo_image_surface_t *)
842 _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
844 /* If there was a deferred clear, _get_image applied it */
845 if (image->base.status == CAIRO_STATUS_SUCCESS) {
846 surface->deferred_clear = FALSE;
848 surface->fallback = image;
851 return &surface->fallback->base;
854 static cairo_int_status_t
855 _cairo_xcb_fallback_compositor_paint (const cairo_compositor_t *compositor,
856 cairo_composite_rectangles_t *extents)
858 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
859 cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
861 return _cairo_surface_paint (fallback, extents->op,
862 &extents->source_pattern.base,
866 static cairo_int_status_t
867 _cairo_xcb_fallback_compositor_mask (const cairo_compositor_t *compositor,
868 cairo_composite_rectangles_t *extents)
870 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
871 cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
873 return _cairo_surface_mask (fallback, extents->op,
874 &extents->source_pattern.base,
875 &extents->mask_pattern.base,
879 static cairo_int_status_t
880 _cairo_xcb_fallback_compositor_stroke (const cairo_compositor_t *compositor,
881 cairo_composite_rectangles_t *extents,
882 const cairo_path_fixed_t *path,
883 const cairo_stroke_style_t *style,
884 const cairo_matrix_t *ctm,
885 const cairo_matrix_t *ctm_inverse,
887 cairo_antialias_t antialias)
889 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
890 cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
892 return _cairo_surface_stroke (fallback, extents->op,
893 &extents->source_pattern.base,
894 path, style, ctm, ctm_inverse,
895 tolerance, antialias,
899 static cairo_int_status_t
900 _cairo_xcb_fallback_compositor_fill (const cairo_compositor_t *compositor,
901 cairo_composite_rectangles_t *extents,
902 const cairo_path_fixed_t *path,
903 cairo_fill_rule_t fill_rule,
905 cairo_antialias_t antialias)
907 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
908 cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
910 return _cairo_surface_fill (fallback, extents->op,
911 &extents->source_pattern.base,
912 path, fill_rule, tolerance,
913 antialias, extents->clip);
916 static cairo_int_status_t
917 _cairo_xcb_fallback_compositor_glyphs (const cairo_compositor_t *compositor,
918 cairo_composite_rectangles_t *extents,
919 cairo_scaled_font_t *scaled_font,
920 cairo_glyph_t *glyphs,
922 cairo_bool_t overlap)
924 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
925 cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
927 return _cairo_surface_show_text_glyphs (fallback, extents->op,
928 &extents->source_pattern.base,
929 NULL, 0, glyphs, num_glyphs,
931 scaled_font, extents->clip);
934 static const cairo_compositor_t _cairo_xcb_fallback_compositor = {
935 &__cairo_no_compositor,
937 _cairo_xcb_fallback_compositor_paint,
938 _cairo_xcb_fallback_compositor_mask,
939 _cairo_xcb_fallback_compositor_stroke,
940 _cairo_xcb_fallback_compositor_fill,
941 _cairo_xcb_fallback_compositor_glyphs,
944 static const cairo_compositor_t _cairo_xcb_render_compositor = {
945 &_cairo_xcb_fallback_compositor,
947 _cairo_xcb_render_compositor_paint,
948 _cairo_xcb_render_compositor_mask,
949 _cairo_xcb_render_compositor_stroke,
950 _cairo_xcb_render_compositor_fill,
951 _cairo_xcb_render_compositor_glyphs,
954 static inline const cairo_compositor_t *
955 get_compositor (cairo_surface_t **s)
957 cairo_xcb_surface_t *surface = (cairo_xcb_surface_t * )*s;
958 if (surface->fallback) {
959 *s = &surface->fallback->base;
960 return ((cairo_image_surface_t *) *s)->compositor;
963 return &_cairo_xcb_render_compositor;
966 static cairo_int_status_t
967 _cairo_xcb_surface_paint (void *abstract_surface,
969 const cairo_pattern_t *source,
970 const cairo_clip_t *clip)
972 cairo_surface_t *surface = abstract_surface;
973 const cairo_compositor_t *compositor = get_compositor (&surface);
974 return _cairo_compositor_paint (compositor, surface, op, source, clip);
977 static cairo_int_status_t
978 _cairo_xcb_surface_mask (void *abstract_surface,
980 const cairo_pattern_t *source,
981 const cairo_pattern_t *mask,
982 const cairo_clip_t *clip)
984 cairo_surface_t *surface = abstract_surface;
985 const cairo_compositor_t *compositor = get_compositor (&surface);
986 return _cairo_compositor_mask (compositor, surface, op, source, mask, clip);
989 static cairo_int_status_t
990 _cairo_xcb_surface_stroke (void *abstract_surface,
992 const cairo_pattern_t *source,
993 const cairo_path_fixed_t *path,
994 const cairo_stroke_style_t *style,
995 const cairo_matrix_t *ctm,
996 const cairo_matrix_t *ctm_inverse,
998 cairo_antialias_t antialias,
999 const cairo_clip_t *clip)
1001 cairo_surface_t *surface = abstract_surface;
1002 const cairo_compositor_t *compositor = get_compositor (&surface);
1003 return _cairo_compositor_stroke (compositor, surface, op, source,
1004 path, style, ctm, ctm_inverse,
1005 tolerance, antialias, clip);
1008 static cairo_int_status_t
1009 _cairo_xcb_surface_fill (void *abstract_surface,
1010 cairo_operator_t op,
1011 const cairo_pattern_t *source,
1012 const cairo_path_fixed_t*path,
1013 cairo_fill_rule_t fill_rule,
1015 cairo_antialias_t antialias,
1016 const cairo_clip_t *clip)
1018 cairo_surface_t *surface = abstract_surface;
1019 const cairo_compositor_t *compositor = get_compositor (&surface);
1020 return _cairo_compositor_fill (compositor, surface, op,
1021 source, path, fill_rule,
1022 tolerance, antialias, clip);
1025 static cairo_int_status_t
1026 _cairo_xcb_surface_glyphs (void *abstract_surface,
1027 cairo_operator_t op,
1028 const cairo_pattern_t *source,
1029 cairo_glyph_t *glyphs,
1031 cairo_scaled_font_t *scaled_font,
1032 const cairo_clip_t *clip)
1034 cairo_surface_t *surface = abstract_surface;
1035 const cairo_compositor_t *compositor = get_compositor (&surface);
1036 return _cairo_compositor_glyphs (compositor, surface, op,
1037 source, glyphs, num_glyphs,
1041 const cairo_surface_backend_t _cairo_xcb_surface_backend = {
1042 CAIRO_SURFACE_TYPE_XCB,
1043 _cairo_xcb_surface_finish,
1044 _cairo_default_context_create,
1046 _cairo_xcb_surface_create_similar,
1047 _cairo_xcb_surface_create_similar_image,
1048 _cairo_xcb_surface_map_to_image,
1049 _cairo_xcb_surface_unmap,
1051 _cairo_xcb_surface_source,
1052 _cairo_xcb_surface_acquire_source_image,
1053 _cairo_xcb_surface_release_source_image,
1054 NULL, /* snapshot */
1057 NULL, /* copy_page */
1058 NULL, /* show_page */
1060 _cairo_xcb_surface_get_extents,
1061 _cairo_xcb_surface_get_font_options,
1063 _cairo_xcb_surface_flush,
1066 _cairo_xcb_surface_paint,
1067 _cairo_xcb_surface_mask,
1068 _cairo_xcb_surface_stroke,
1069 _cairo_xcb_surface_fill,
1070 NULL, /* fill-stroke */
1071 _cairo_xcb_surface_glyphs,
1075 _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen,
1076 xcb_drawable_t drawable,
1077 cairo_bool_t owns_pixmap,
1078 pixman_format_code_t pixman_format,
1079 xcb_render_pictformat_t xrender_format,
1083 cairo_xcb_surface_t *surface;
1085 surface = malloc (sizeof (cairo_xcb_surface_t));
1086 if (unlikely (surface == NULL))
1087 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1089 _cairo_surface_init (&surface->base,
1090 &_cairo_xcb_surface_backend,
1091 &screen->connection->device,
1092 _cairo_content_from_pixman_format (pixman_format));
1094 surface->connection = _cairo_xcb_connection_reference (screen->connection);
1095 surface->screen = screen;
1096 cairo_list_add (&surface->link, &screen->surfaces);
1098 surface->drawable = drawable;
1099 surface->owns_pixmap = owns_pixmap;
1101 surface->deferred_clear = FALSE;
1102 surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
1104 surface->width = width;
1105 surface->height = height;
1106 surface->depth = PIXMAN_FORMAT_DEPTH (pixman_format);
1108 surface->picture = XCB_NONE;
1109 if (screen->connection->force_precision != -1)
1110 surface->precision = screen->connection->force_precision;
1112 surface->precision = XCB_RENDER_POLY_MODE_IMPRECISE;
1114 surface->pixman_format = pixman_format;
1115 surface->xrender_format = xrender_format;
1117 surface->fallback = NULL;
1118 _cairo_boxes_init (&surface->fallback_damage);
1120 return &surface->base;
1123 static xcb_screen_t *
1124 _cairo_xcb_screen_from_visual (xcb_connection_t *connection,
1125 xcb_visualtype_t *visual,
1128 xcb_depth_iterator_t d;
1129 xcb_screen_iterator_t s;
1131 s = xcb_setup_roots_iterator (xcb_get_setup (connection));
1132 for (; s.rem; xcb_screen_next (&s)) {
1133 if (s.data->root_visual == visual->visual_id) {
1134 *depth = s.data->root_depth;
1138 d = xcb_screen_allowed_depths_iterator(s.data);
1139 for (; d.rem; xcb_depth_next (&d)) {
1140 xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
1142 for (; v.rem; xcb_visualtype_next (&v)) {
1143 if (v.data->visual_id == visual->visual_id) {
1144 *depth = d.data->depth;
1155 * cairo_xcb_surface_create:
1156 * @connection: an XCB connection
1157 * @drawable: an XCB drawable
1158 * @visual: the visual to use for drawing to @drawable. The depth
1159 * of the visual must match the depth of the drawable.
1160 * Currently, only TrueColor visuals are fully supported.
1161 * @width: the current width of @drawable
1162 * @height: the current height of @drawable
1164 * Creates an XCB surface that draws to the given drawable.
1165 * The way that colors are represented in the drawable is specified
1166 * by the provided visual.
1168 * Note: If @drawable is a Window, then the function
1169 * cairo_xcb_surface_set_size() must be called whenever the size of the
1172 * When @drawable is a Window containing child windows then drawing to
1173 * the created surface will be clipped by those child windows. When
1174 * the created surface is used as a source, the contents of the
1175 * children will be included.
1177 * Return value: a pointer to the newly created surface. The caller
1178 * owns the surface and should call cairo_surface_destroy() when done
1181 * This function always returns a valid pointer, but it will return a
1182 * pointer to a "nil" surface if an error such as out of memory
1183 * occurs. You can use cairo_surface_status() to check for this.
1188 cairo_xcb_surface_create (xcb_connection_t *connection,
1189 xcb_drawable_t drawable,
1190 xcb_visualtype_t *visual,
1194 cairo_xcb_screen_t *screen;
1195 xcb_screen_t *xcb_screen;
1196 cairo_format_masks_t image_masks;
1197 pixman_format_code_t pixman_format;
1198 xcb_render_pictformat_t xrender_format;
1201 if (xcb_connection_has_error (connection))
1202 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1204 if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
1205 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1206 if (unlikely (width <= 0 || height <= 0))
1207 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1209 xcb_screen = _cairo_xcb_screen_from_visual (connection, visual, &depth);
1210 if (unlikely (xcb_screen == NULL))
1211 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1213 image_masks.alpha_mask = 0;
1214 image_masks.red_mask = visual->red_mask;
1215 image_masks.green_mask = visual->green_mask;
1216 image_masks.blue_mask = visual->blue_mask;
1217 if (depth == 32) /* XXX visuals have no alpha! */
1218 image_masks.alpha_mask =
1219 0xffffffff & ~(visual->red_mask | visual->green_mask | visual->blue_mask);
1221 image_masks.bpp = 32;
1223 image_masks.bpp = 16;
1225 image_masks.bpp = 8;
1227 image_masks.bpp = 1;
1229 if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1230 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1232 screen = _cairo_xcb_screen_get (connection, xcb_screen);
1233 if (unlikely (screen == NULL))
1234 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1237 _cairo_xcb_connection_get_xrender_format_for_visual (screen->connection,
1240 return _cairo_xcb_surface_create_internal (screen, drawable, FALSE,
1245 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1246 slim_hidden_def (cairo_xcb_surface_create);
1250 * cairo_xcb_surface_create_for_bitmap:
1251 * @connection: an XCB connection
1252 * @screen: the XCB screen associated with @bitmap
1253 * @bitmap: an XCB drawable (a Pixmap with depth 1)
1254 * @width: the current width of @bitmap
1255 * @height: the current height of @bitmap
1257 * Creates an XCB surface that draws to the given bitmap.
1258 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1260 * Return value: a pointer to the newly created surface. The caller
1261 * owns the surface and should call cairo_surface_destroy() when done
1264 * This function always returns a valid pointer, but it will return a
1265 * pointer to a "nil" surface if an error such as out of memory
1266 * occurs. You can use cairo_surface_status() to check for this.
1271 cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection,
1272 xcb_screen_t *screen,
1273 xcb_pixmap_t bitmap,
1277 cairo_xcb_screen_t *cairo_xcb_screen;
1279 if (xcb_connection_has_error (connection))
1280 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1282 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1283 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1284 if (unlikely (width <= 0 || height <= 0))
1285 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1287 cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1288 if (unlikely (cairo_xcb_screen == NULL))
1289 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1291 return _cairo_xcb_surface_create_internal (cairo_xcb_screen, bitmap, FALSE,
1293 cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1],
1296 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1297 slim_hidden_def (cairo_xcb_surface_create_for_bitmap);
1301 * cairo_xcb_surface_create_with_xrender_format:
1302 * @connection: an XCB connection
1303 * @drawable: an XCB drawable
1304 * @screen: the XCB screen associated with @drawable
1305 * @format: the picture format to use for drawing to @drawable. The
1306 * depth of @format mush match the depth of the drawable.
1307 * @width: the current width of @drawable
1308 * @height: the current height of @drawable
1310 * Creates an XCB surface that draws to the given drawable.
1311 * The way that colors are represented in the drawable is specified
1312 * by the provided picture format.
1314 * Note: If @drawable is a Window, then the function
1315 * cairo_xcb_surface_set_size() must be called whenever the size of the
1318 * When @drawable is a Window containing child windows then drawing to
1319 * the created surface will be clipped by those child windows. When
1320 * the created surface is used as a source, the contents of the
1321 * children will be included.
1323 * Return value: a pointer to the newly created surface. The caller
1324 * owns the surface and should call cairo_surface_destroy() when done
1327 * This function always returns a valid pointer, but it will return a
1328 * pointer to a "nil" surface if an error such as out of memory
1329 * occurs. You can use cairo_surface_status() to check for this.
1334 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection,
1335 xcb_screen_t *screen,
1336 xcb_drawable_t drawable,
1337 xcb_render_pictforminfo_t *format,
1341 cairo_xcb_screen_t *cairo_xcb_screen;
1342 cairo_format_masks_t image_masks;
1343 pixman_format_code_t pixman_format;
1345 if (xcb_connection_has_error (connection))
1346 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1348 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1349 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1350 if (unlikely (width <= 0 || height <= 0))
1351 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1353 image_masks.alpha_mask =
1354 (unsigned long) format->direct.alpha_mask << format->direct.alpha_shift;
1355 image_masks.red_mask =
1356 (unsigned long) format->direct.red_mask << format->direct.red_shift;
1357 image_masks.green_mask =
1358 (unsigned long) format->direct.green_mask << format->direct.green_shift;
1359 image_masks.blue_mask =
1360 (unsigned long) format->direct.blue_mask << format->direct.blue_shift;
1362 image_masks.bpp = format->depth;
1364 if (format->depth > 16)
1365 image_masks.bpp = 32;
1366 else if (format->depth > 8)
1367 image_masks.bpp = 16;
1368 else if (format->depth > 1)
1369 image_masks.bpp = 8;
1371 image_masks.bpp = 1;
1374 if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1375 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1377 cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1378 if (unlikely (cairo_xcb_screen == NULL))
1379 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1381 return _cairo_xcb_surface_create_internal (cairo_xcb_screen,
1388 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1389 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format);
1392 /* This does the necessary fixup when a surface's drawable or size changed. */
1394 _drawable_changed (cairo_xcb_surface_t *surface)
1396 _cairo_surface_set_error (&surface->base,
1397 _cairo_surface_begin_modification (&surface->base));
1398 _cairo_boxes_clear (&surface->fallback_damage);
1399 cairo_surface_destroy (&surface->fallback->base);
1401 surface->deferred_clear = FALSE;
1402 surface->fallback = NULL;
1406 * cairo_xcb_surface_set_size:
1407 * @surface: a #cairo_surface_t for the XCB backend
1408 * @width: the new width of the surface
1409 * @height: the new height of the surface
1411 * Informs cairo of the new size of the XCB drawable underlying the
1412 * surface. For a surface created for a window (rather than a pixmap),
1413 * this function must be called each time the size of the window
1414 * changes. (For a subwindow, you are normally resizing the window
1415 * yourself, but for a toplevel window, it is necessary to listen for
1416 * ConfigureNotify events.)
1418 * A pixmap can never change size, so it is never necessary to call
1419 * this function on a surface created for a pixmap.
1421 * If cairo_surface_flush() wasn't called, some pending operations
1422 * might be discarded.
1427 cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
1431 cairo_xcb_surface_t *surface;
1433 if (unlikely (abstract_surface->status))
1435 if (unlikely (abstract_surface->finished)) {
1436 _cairo_surface_set_error (abstract_surface,
1437 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1442 if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1443 _cairo_surface_set_error (abstract_surface,
1444 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1448 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1449 _cairo_surface_set_error (abstract_surface,
1450 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1454 surface = (cairo_xcb_surface_t *) abstract_surface;
1456 _drawable_changed(surface);
1457 surface->width = width;
1458 surface->height = height;
1460 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1461 slim_hidden_def (cairo_xcb_surface_set_size);
1465 * cairo_xcb_surface_set_drawable:
1466 * @surface: a #cairo_surface_t for the XCB backend
1467 * @drawable: the new drawable of the surface
1468 * @width: the new width of the surface
1469 * @height: the new height of the surface
1471 * Informs cairo of the new drawable and size of the XCB drawable underlying the
1474 * If cairo_surface_flush() wasn't called, some pending operations
1475 * might be discarded.
1480 cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
1481 xcb_drawable_t drawable,
1485 cairo_xcb_surface_t *surface;
1487 if (unlikely (abstract_surface->status))
1489 if (unlikely (abstract_surface->finished)) {
1490 _cairo_surface_set_error (abstract_surface,
1491 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1496 if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1497 _cairo_surface_set_error (abstract_surface,
1498 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1502 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1503 _cairo_surface_set_error (abstract_surface,
1504 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1508 surface = (cairo_xcb_surface_t *) abstract_surface;
1510 /* XXX: and what about this case? */
1511 if (surface->owns_pixmap)
1514 _drawable_changed (surface);
1516 if (surface->drawable != drawable) {
1517 cairo_status_t status;
1518 status = _cairo_xcb_connection_acquire (surface->connection);
1519 if (unlikely (status))
1522 if (surface->picture != XCB_NONE) {
1523 _cairo_xcb_connection_render_free_picture (surface->connection,
1525 surface->picture = XCB_NONE;
1528 _cairo_xcb_connection_release (surface->connection);
1530 surface->drawable = drawable;
1532 surface->width = width;
1533 surface->height = height;
1535 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1536 slim_hidden_def (cairo_xcb_surface_set_drawable);