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-list-inline.h"
49 #include "cairo-image-surface-private.h"
50 #include "cairo-surface-backend-private.h"
52 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
53 slim_hidden_proto (cairo_xcb_surface_create);
54 slim_hidden_proto (cairo_xcb_surface_create_for_bitmap);
55 slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format);
60 * @Title: XCB Surfaces
61 * @Short_Description: X Window System rendering using the XCB library
62 * @See_Also: #cairo_surface_t
64 * The XCB surface is used to render cairo graphics to X Window System
65 * windows and pixmaps using the XCB library.
67 * Note that the XCB surface automatically takes advantage of the X render
68 * extension if it is available.
72 * CAIRO_HAS_XCB_SURFACE:
74 * Defined if the xcb surface backend is available.
75 * This macro can be used to conditionally compile backend-specific code.
81 _cairo_xcb_surface_create_similar (void *abstract_other,
82 cairo_content_t content,
86 cairo_xcb_surface_t *other = abstract_other;
87 cairo_xcb_surface_t *surface;
88 cairo_xcb_connection_t *connection;
90 cairo_status_t status;
92 if (unlikely(width > XLIB_COORD_MAX ||
93 height > XLIB_COORD_MAX ||
96 return cairo_image_surface_create (_cairo_format_from_content (content),
99 if ((other->connection->flags & CAIRO_XCB_HAS_RENDER) == 0)
100 return _cairo_xcb_surface_create_similar_image (other,
101 _cairo_format_from_content (content),
104 connection = other->connection;
105 status = _cairo_xcb_connection_acquire (connection);
106 if (unlikely (status))
107 return _cairo_surface_create_in_error (status);
109 if (content == other->base.content) {
110 pixmap = _cairo_xcb_connection_create_pixmap (connection,
115 surface = (cairo_xcb_surface_t *)
116 _cairo_xcb_surface_create_internal (other->screen,
118 other->pixman_format,
119 other->xrender_format,
122 cairo_format_t format;
123 pixman_format_code_t pixman_format;
125 /* XXX find a compatible xrender format */
127 case CAIRO_CONTENT_ALPHA:
128 pixman_format = PIXMAN_a8;
129 format = CAIRO_FORMAT_A8;
131 case CAIRO_CONTENT_COLOR:
132 pixman_format = PIXMAN_x8r8g8b8;
133 format = CAIRO_FORMAT_RGB24;
137 case CAIRO_CONTENT_COLOR_ALPHA:
138 pixman_format = PIXMAN_a8r8g8b8;
139 format = CAIRO_FORMAT_ARGB32;
143 pixmap = _cairo_xcb_connection_create_pixmap (connection,
144 PIXMAN_FORMAT_DEPTH (pixman_format),
148 surface = (cairo_xcb_surface_t *)
149 _cairo_xcb_surface_create_internal (other->screen,
152 connection->standard_formats[format],
156 if (unlikely (surface->base.status))
157 _cairo_xcb_connection_free_pixmap (connection, pixmap);
159 _cairo_xcb_connection_release (connection);
161 return &surface->base;
165 _cairo_xcb_surface_create_similar_image (void *abstract_other,
166 cairo_format_t format,
170 cairo_xcb_surface_t *other = abstract_other;
171 cairo_xcb_connection_t *connection = other->connection;
173 cairo_xcb_shm_info_t *shm_info;
174 cairo_image_surface_t *image;
175 cairo_status_t status;
176 pixman_format_code_t pixman_format;
178 if (unlikely(width > XLIB_COORD_MAX ||
179 height > XLIB_COORD_MAX ||
184 pixman_format = _cairo_format_to_pixman_format_code (format);
186 status = _cairo_xcb_shm_image_create (connection, pixman_format,
187 width, height, &image,
189 if (unlikely (status))
190 return _cairo_surface_create_in_error (status);
195 static cairo_status_t
196 _cairo_xcb_surface_finish (void *abstract_surface)
198 cairo_xcb_surface_t *surface = abstract_surface;
199 cairo_status_t status;
201 if (surface->fallback != NULL) {
202 cairo_surface_finish (&surface->fallback->base);
203 cairo_surface_destroy (&surface->fallback->base);
205 _cairo_boxes_fini (&surface->fallback_damage);
207 cairo_list_del (&surface->link);
209 status = _cairo_xcb_connection_acquire (surface->connection);
210 if (status == CAIRO_STATUS_SUCCESS) {
211 if (surface->picture != XCB_NONE) {
212 _cairo_xcb_connection_render_free_picture (surface->connection,
216 if (surface->owns_pixmap)
217 _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
218 _cairo_xcb_connection_release (surface->connection);
221 _cairo_xcb_connection_destroy (surface->connection);
227 _destroy_image (pixman_image_t *image, void *data)
232 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
233 static cairo_surface_t *
234 _cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection,
235 pixman_format_code_t pixman_format,
236 int width, int height,
237 cairo_bool_t might_reuse,
238 cairo_xcb_shm_info_t **shm_info_out)
240 cairo_surface_t *image;
241 cairo_xcb_shm_info_t *shm_info;
242 cairo_int_status_t status;
245 *shm_info_out = NULL;
247 stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
248 PIXMAN_FORMAT_BPP (pixman_format));
249 status = _cairo_xcb_connection_allocate_shm_info (connection,
253 if (unlikely (status)) {
254 if (status == CAIRO_INT_STATUS_UNSUPPORTED)
257 return _cairo_surface_create_in_error (status);
260 image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
264 if (unlikely (image->status)) {
265 _cairo_xcb_shm_info_destroy (shm_info);
269 status = _cairo_user_data_array_set_data (&image->user_data,
270 (const cairo_user_data_key_t *) connection,
272 (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
273 if (unlikely (status)) {
274 cairo_surface_destroy (image);
275 _cairo_xcb_shm_info_destroy (shm_info);
276 return _cairo_surface_create_in_error (status);
279 *shm_info_out = shm_info;
284 static cairo_surface_t *
285 _get_shm_image (cairo_xcb_surface_t *surface,
287 int width, int height)
289 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
290 cairo_xcb_shm_info_t *shm_info;
291 cairo_surface_t *image;
292 cairo_status_t status;
294 if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
297 image = _cairo_xcb_surface_create_shm_image (surface->connection,
298 surface->pixman_format,
302 if (unlikely (image == NULL || image->status))
305 status = _cairo_xcb_connection_shm_get_image (surface->connection,
311 if (unlikely (status)) {
312 cairo_surface_destroy (image);
313 image = _cairo_surface_create_in_error (status);
323 static cairo_surface_t *
324 _get_image (cairo_xcb_surface_t *surface,
325 cairo_bool_t use_shm,
327 int width, int height)
329 cairo_surface_t *image;
330 cairo_xcb_connection_t *connection;
331 xcb_get_image_reply_t *reply;
332 cairo_int_status_t status;
334 assert (surface->fallback == NULL);
337 assert (x + width <= surface->width);
338 assert (y + height <= surface->height);
340 if (surface->deferred_clear) {
342 _cairo_image_surface_create_with_pixman_format (NULL,
343 surface->pixman_format,
346 if (surface->deferred_clear_color.alpha_short > 0x00ff) {
347 cairo_solid_pattern_t solid;
349 _cairo_pattern_init_solid (&solid, &surface->deferred_clear_color);
350 status = _cairo_surface_paint (image,
351 CAIRO_OPERATOR_SOURCE,
354 if (unlikely (status)) {
355 cairo_surface_destroy (image);
356 image = _cairo_surface_create_in_error (status);
362 connection = surface->connection;
364 status = _cairo_xcb_connection_acquire (connection);
365 if (unlikely (status))
366 return _cairo_surface_create_in_error (status);
369 image = _get_shm_image (surface, x, y, width, height);
371 if (image->status == CAIRO_STATUS_SUCCESS) {
372 _cairo_xcb_connection_release (connection);
375 cairo_surface_destroy (image);
379 status = _cairo_xcb_connection_get_image (connection,
384 if (unlikely (status))
387 if (reply == NULL && ! surface->owns_pixmap) {
388 /* xcb_get_image_t from a window is dangerous because it can
389 * produce errors if the window is unmapped or partially
390 * outside the screen. We could check for errors and
391 * retry, but to keep things simple, we just create a
394 * If we hit this fallback too often, we should remember so and
395 * skip the round-trip from the above GetImage request,
396 * similar to what cairo-xlib does.
401 gc = _cairo_xcb_screen_get_gc (surface->screen,
404 pixmap = _cairo_xcb_connection_create_pixmap (connection,
409 /* XXX IncludeInferiors? */
410 _cairo_xcb_connection_copy_area (connection,
417 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
419 status = _cairo_xcb_connection_get_image (connection,
424 _cairo_xcb_connection_free_pixmap (connection, pixmap);
426 if (unlikely (status))
430 if (unlikely (reply == NULL)) {
431 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
436 /* XXX format conversion */
437 assert (reply->depth == surface->depth);
439 image = _cairo_image_surface_create_with_pixman_format
440 (xcb_get_image_data (reply),
441 surface->pixman_format,
443 CAIRO_STRIDE_FOR_WIDTH_BPP (width,
444 PIXMAN_FORMAT_BPP (surface->pixman_format)));
445 status = image->status;
446 if (unlikely (status)) {
452 pixman_image_set_destroy_function (((cairo_image_surface_t *)image)->pixman_image, _destroy_image, reply);
454 _cairo_xcb_connection_release (connection);
459 _cairo_xcb_connection_release (connection);
460 return _cairo_surface_create_in_error (status);
463 static cairo_surface_t *
464 _cairo_xcb_surface_source (void *abstract_surface,
465 cairo_rectangle_int_t *extents)
467 cairo_xcb_surface_t *surface = abstract_surface;
470 extents->x = extents->y = 0;
471 extents->width = surface->width;
472 extents->height = surface->height;
475 return &surface->base;
478 static cairo_status_t
479 _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
480 cairo_image_surface_t **image_out,
483 cairo_xcb_surface_t *surface = abstract_surface;
484 cairo_surface_t *image;
486 if (surface->fallback != NULL) {
487 image = cairo_surface_reference (&surface->fallback->base);
491 image = _cairo_surface_has_snapshot (&surface->base,
492 &_cairo_image_surface_backend);
494 image = cairo_surface_reference (image);
498 image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
499 if (unlikely (image->status))
500 return image->status;
502 _cairo_surface_attach_snapshot (&surface->base, image, NULL);
505 *image_out = (cairo_image_surface_t *) image;
507 return CAIRO_STATUS_SUCCESS;
511 _cairo_xcb_surface_release_source_image (void *abstract_surface,
512 cairo_image_surface_t *image,
515 cairo_surface_destroy (&image->base);
519 _cairo_xcb_surface_get_extents (void *abstract_surface,
520 cairo_rectangle_int_t *extents)
522 cairo_xcb_surface_t *surface = abstract_surface;
524 extents->x = extents->y = 0;
525 extents->width = surface->width;
526 extents->height = surface->height;
531 _cairo_xcb_surface_get_font_options (void *abstract_surface,
532 cairo_font_options_t *options)
534 /* XXX copy from xlib */
535 _cairo_font_options_init_default (options);
536 _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
539 static cairo_status_t
540 _put_shm_image (cairo_xcb_surface_t *surface,
542 cairo_image_surface_t *image)
544 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
545 cairo_xcb_shm_info_t *shm_info;
547 shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
548 (const cairo_user_data_key_t *) surface->connection);
549 if (shm_info == NULL)
550 return CAIRO_INT_STATUS_UNSUPPORTED;
552 _cairo_xcb_connection_shm_put_image (surface->connection,
555 surface->width, surface->height,
557 image->width, image->height,
558 image->base.device_transform_inverse.x0,
559 image->base.device_transform_inverse.y0,
564 return CAIRO_STATUS_SUCCESS;
566 return CAIRO_INT_STATUS_UNSUPPORTED;
570 static cairo_status_t
571 _put_image (cairo_xcb_surface_t *surface,
572 cairo_image_surface_t *image)
574 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
576 /* XXX track damaged region? */
578 status = _cairo_xcb_connection_acquire (surface->connection);
579 if (unlikely (status))
582 if (image->pixman_format == surface->pixman_format) {
585 assert (image->depth == surface->depth);
586 assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
588 gc = _cairo_xcb_screen_get_gc (surface->screen,
592 status = _put_shm_image (surface, gc, image);
593 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
594 _cairo_xcb_connection_put_image (surface->connection,
595 surface->drawable, gc,
596 image->width, image->height,
597 image->base.device_transform_inverse.x0,
598 image->base.device_transform_inverse.y0,
602 status = CAIRO_STATUS_SUCCESS;
605 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
610 _cairo_xcb_connection_release (surface->connection);
614 static cairo_int_status_t
615 _put_shm_image_boxes (cairo_xcb_surface_t *surface,
616 cairo_image_surface_t *image,
618 cairo_boxes_t *boxes)
620 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
621 cairo_xcb_shm_info_t *shm_info;
623 shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
624 (const cairo_user_data_key_t *) surface->connection);
625 if (shm_info != NULL) {
626 struct _cairo_boxes_chunk *chunk;
628 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
631 for (i = 0; i < chunk->count; i++) {
632 cairo_box_t *b = &chunk->base[i];
633 int x = _cairo_fixed_integer_part (b->p1.x);
634 int y = _cairo_fixed_integer_part (b->p1.y);
635 int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
636 int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
638 _cairo_xcb_connection_shm_put_image (surface->connection,
641 surface->width, surface->height,
652 return CAIRO_INT_STATUS_SUCCESS;
655 return CAIRO_INT_STATUS_UNSUPPORTED;
658 static cairo_status_t
659 _put_image_boxes (cairo_xcb_surface_t *surface,
660 cairo_image_surface_t *image,
661 cairo_boxes_t *boxes)
663 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
666 if (boxes->num_boxes == 0)
667 return CAIRO_STATUS_SUCCESS;
669 /* XXX track damaged region? */
671 status = _cairo_xcb_connection_acquire (surface->connection);
672 if (unlikely (status))
675 assert (image->pixman_format == surface->pixman_format);
676 assert (image->depth == surface->depth);
677 assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
679 gc = _cairo_xcb_screen_get_gc (surface->screen,
683 status = _put_shm_image_boxes (surface, image, gc, boxes);
684 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
685 struct _cairo_boxes_chunk *chunk;
687 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
690 for (i = 0; i < chunk->count; i++) {
691 cairo_box_t *b = &chunk->base[i];
692 int x = _cairo_fixed_integer_part (b->p1.x);
693 int y = _cairo_fixed_integer_part (b->p1.y);
694 int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
695 int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
696 _cairo_xcb_connection_put_image (surface->connection,
697 surface->drawable, gc,
703 x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 +
708 status = CAIRO_STATUS_SUCCESS;
711 _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
712 _cairo_xcb_connection_release (surface->connection);
716 static cairo_status_t
717 _cairo_xcb_surface_flush (void *abstract_surface)
719 cairo_xcb_surface_t *surface = abstract_surface;
720 cairo_status_t status;
722 if (likely (surface->fallback == NULL)) {
723 status = CAIRO_STATUS_SUCCESS;
724 if (! surface->base.finished && surface->deferred_clear)
725 status = _cairo_xcb_surface_clear (surface);
730 status = surface->base.status;
731 if (status == CAIRO_STATUS_SUCCESS && ! surface->base.finished) {
732 status = cairo_surface_status (&surface->fallback->base);
734 if (status == CAIRO_STATUS_SUCCESS)
735 status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
736 CAIRO_FILL_RULE_WINDING,
737 &surface->fallback_damage);
739 if (status == CAIRO_STATUS_SUCCESS)
740 status = _put_image_boxes (surface,
742 &surface->fallback_damage);
744 if (status == CAIRO_STATUS_SUCCESS) {
745 _cairo_surface_attach_snapshot (&surface->base,
746 &surface->fallback->base,
747 cairo_surface_finish);
751 _cairo_boxes_clear (&surface->fallback_damage);
752 cairo_surface_destroy (&surface->fallback->base);
753 surface->fallback = NULL;
758 static cairo_surface_t *
759 _cairo_xcb_surface_map_to_image (void *abstract_surface,
760 const cairo_rectangle_int_t *extents)
762 cairo_xcb_surface_t *surface = abstract_surface;
763 cairo_surface_t *image;
765 if (surface->fallback)
766 return surface->fallback->base.backend->map_to_image (&surface->fallback->base, extents);
768 image = _get_image (surface, TRUE,
769 extents->x, extents->y,
770 extents->width, extents->height);
771 if (unlikely (image->status))
774 /* Do we have a deferred clear and this image surface does NOT cover the
775 * whole xcb surface? Have to apply the clear in that case, else
776 * uploading the image will handle the problem for us.
778 if (surface->deferred_clear &&
779 ! (extents->width == surface->width &&
780 extents->height == surface->height)) {
781 cairo_status_t status = _cairo_xcb_surface_clear (surface);
782 if (unlikely (status)) {
783 cairo_surface_destroy(image);
784 return _cairo_surface_create_in_error (status);
787 surface->deferred_clear = FALSE;
789 cairo_surface_set_device_offset (image, -extents->x, -extents->y);
793 static cairo_int_status_t
794 _cairo_xcb_surface_unmap (void *abstract_surface,
795 cairo_image_surface_t *image)
797 cairo_xcb_surface_t *surface = abstract_surface;
799 if (surface->fallback)
800 return surface->fallback->base.backend->unmap_image (&surface->fallback->base, image);
801 return _put_image (abstract_surface, image);
804 static cairo_surface_t *
805 _cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface,
806 cairo_composite_rectangles_t *composite)
808 cairo_image_surface_t *image;
809 cairo_status_t status;
811 status = _cairo_composite_rectangles_add_to_damage (composite,
812 &surface->fallback_damage);
813 if (unlikely (status))
814 return _cairo_surface_create_in_error (status);
816 if (surface->fallback)
817 return &surface->fallback->base;
819 image = (cairo_image_surface_t *)
820 _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
822 /* If there was a deferred clear, _get_image applied it */
823 if (image->base.status == CAIRO_STATUS_SUCCESS) {
824 surface->deferred_clear = FALSE;
826 surface->fallback = image;
829 return &surface->fallback->base;
832 static cairo_int_status_t
833 _cairo_xcb_surface_paint (void *abstract_surface,
835 const cairo_pattern_t *source,
836 const cairo_clip_t *clip)
838 cairo_xcb_surface_t *surface = abstract_surface;
839 cairo_composite_rectangles_t composite;
840 cairo_int_status_t status;
842 status = _cairo_composite_rectangles_init_for_paint (&composite,
846 if (unlikely (status))
849 if (surface->fallback == NULL) {
850 status = _cairo_xcb_surface_cairo_paint (surface, op, source, clip);
851 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
854 status = _cairo_xcb_surface_render_paint (surface, op, source,
856 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
860 status = _cairo_surface_paint (_cairo_xcb_surface_fallback (surface,
865 _cairo_composite_rectangles_fini (&composite);
869 static cairo_int_status_t
870 _cairo_xcb_surface_mask (void *abstract_surface,
872 const cairo_pattern_t *source,
873 const cairo_pattern_t *mask,
874 const cairo_clip_t *clip)
876 cairo_xcb_surface_t *surface = abstract_surface;
877 cairo_composite_rectangles_t composite;
878 cairo_int_status_t status;
880 status = _cairo_composite_rectangles_init_for_mask (&composite,
882 op, source, mask, clip);
883 if (unlikely (status))
886 if (surface->fallback == NULL) {
887 status = _cairo_xcb_surface_cairo_mask (surface,
888 op, source, mask, clip);
889 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
892 status = _cairo_xcb_surface_render_mask (surface,
893 op, source, mask, &composite);
894 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
898 status = _cairo_surface_mask (_cairo_xcb_surface_fallback (surface,
903 _cairo_composite_rectangles_fini (&composite);
907 static cairo_int_status_t
908 _cairo_xcb_surface_stroke (void *abstract_surface,
910 const cairo_pattern_t *source,
911 const cairo_path_fixed_t *path,
912 const cairo_stroke_style_t *style,
913 const cairo_matrix_t *ctm,
914 const cairo_matrix_t *ctm_inverse,
916 cairo_antialias_t antialias,
917 const cairo_clip_t *clip)
919 cairo_xcb_surface_t *surface = abstract_surface;
920 cairo_composite_rectangles_t composite;
921 cairo_int_status_t status;
923 status = _cairo_composite_rectangles_init_for_stroke (&composite,
928 if (unlikely (status))
931 if (surface->fallback == NULL) {
932 status = _cairo_xcb_surface_cairo_stroke (surface, op, source,
935 tolerance, antialias,
938 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
941 status = _cairo_xcb_surface_render_stroke (surface, op, source,
944 tolerance, antialias,
947 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
951 status = _cairo_surface_stroke (_cairo_xcb_surface_fallback (surface,
956 tolerance, antialias,
959 _cairo_composite_rectangles_fini (&composite);
963 static cairo_int_status_t
964 _cairo_xcb_surface_fill (void *abstract_surface,
966 const cairo_pattern_t *source,
967 const cairo_path_fixed_t*path,
968 cairo_fill_rule_t fill_rule,
970 cairo_antialias_t antialias,
971 const cairo_clip_t *clip)
973 cairo_xcb_surface_t *surface = abstract_surface;
974 cairo_composite_rectangles_t composite;
975 cairo_int_status_t status;
977 status = _cairo_composite_rectangles_init_for_fill (&composite,
981 if (unlikely (status))
984 if (surface->fallback == NULL) {
985 status = _cairo_xcb_surface_cairo_fill (surface, op, source,
987 tolerance, antialias,
989 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
992 status = _cairo_xcb_surface_render_fill (surface, op, source,
994 tolerance, antialias,
996 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1000 status = _cairo_surface_fill (_cairo_xcb_surface_fallback (surface,
1004 tolerance, antialias,
1007 _cairo_composite_rectangles_fini (&composite);
1011 static cairo_int_status_t
1012 _cairo_xcb_surface_glyphs (void *abstract_surface,
1013 cairo_operator_t op,
1014 const cairo_pattern_t *source,
1015 cairo_glyph_t *glyphs,
1017 cairo_scaled_font_t *scaled_font,
1018 const cairo_clip_t *clip)
1020 cairo_xcb_surface_t *surface = abstract_surface;
1021 cairo_composite_rectangles_t composite;
1022 cairo_int_status_t status;
1023 cairo_bool_t overlap;
1025 status = _cairo_composite_rectangles_init_for_glyphs (&composite,
1031 if (unlikely (status))
1034 if (surface->fallback == NULL) {
1035 status = _cairo_xcb_surface_cairo_glyphs (surface,
1037 scaled_font, glyphs, num_glyphs,
1039 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1042 status = _cairo_xcb_surface_render_glyphs (surface,
1044 scaled_font, glyphs, num_glyphs,
1045 &composite, overlap);
1046 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1050 status = _cairo_surface_show_text_glyphs (_cairo_xcb_surface_fallback (surface,
1059 _cairo_composite_rectangles_fini (&composite);
1063 const cairo_surface_backend_t _cairo_xcb_surface_backend = {
1064 CAIRO_SURFACE_TYPE_XCB,
1065 _cairo_xcb_surface_finish,
1066 _cairo_default_context_create,
1068 _cairo_xcb_surface_create_similar,
1069 _cairo_xcb_surface_create_similar_image,
1070 _cairo_xcb_surface_map_to_image,
1071 _cairo_xcb_surface_unmap,
1073 _cairo_xcb_surface_source,
1074 _cairo_xcb_surface_acquire_source_image,
1075 _cairo_xcb_surface_release_source_image,
1076 NULL, /* snapshot */
1079 NULL, /* copy_page */
1080 NULL, /* show_page */
1082 _cairo_xcb_surface_get_extents,
1083 _cairo_xcb_surface_get_font_options,
1085 _cairo_xcb_surface_flush,
1088 _cairo_xcb_surface_paint,
1089 _cairo_xcb_surface_mask,
1090 _cairo_xcb_surface_stroke,
1091 _cairo_xcb_surface_fill,
1092 NULL, /* fill-stroke */
1093 _cairo_xcb_surface_glyphs,
1097 _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen,
1098 xcb_drawable_t drawable,
1099 cairo_bool_t owns_pixmap,
1100 pixman_format_code_t pixman_format,
1101 xcb_render_pictformat_t xrender_format,
1105 cairo_xcb_surface_t *surface;
1107 surface = malloc (sizeof (cairo_xcb_surface_t));
1108 if (unlikely (surface == NULL))
1109 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1111 _cairo_surface_init (&surface->base,
1112 &_cairo_xcb_surface_backend,
1113 &screen->connection->device,
1114 _cairo_content_from_pixman_format (pixman_format));
1116 surface->connection = _cairo_xcb_connection_reference (screen->connection);
1117 surface->screen = screen;
1118 cairo_list_add (&surface->link, &screen->surfaces);
1120 surface->drawable = drawable;
1121 surface->owns_pixmap = owns_pixmap;
1123 surface->deferred_clear = FALSE;
1124 surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
1126 surface->width = width;
1127 surface->height = height;
1128 surface->depth = PIXMAN_FORMAT_DEPTH (pixman_format);
1130 surface->picture = XCB_NONE;
1131 if (screen->connection->force_precision != -1)
1132 surface->precision = screen->connection->force_precision;
1134 surface->precision = XCB_RENDER_POLY_MODE_IMPRECISE;
1136 surface->pixman_format = pixman_format;
1137 surface->xrender_format = xrender_format;
1139 surface->fallback = NULL;
1140 _cairo_boxes_init (&surface->fallback_damage);
1142 return &surface->base;
1145 static xcb_screen_t *
1146 _cairo_xcb_screen_from_visual (xcb_connection_t *connection,
1147 xcb_visualtype_t *visual,
1150 xcb_depth_iterator_t d;
1151 xcb_screen_iterator_t s;
1153 s = xcb_setup_roots_iterator (xcb_get_setup (connection));
1154 for (; s.rem; xcb_screen_next (&s)) {
1155 if (s.data->root_visual == visual->visual_id) {
1156 *depth = s.data->root_depth;
1160 d = xcb_screen_allowed_depths_iterator(s.data);
1161 for (; d.rem; xcb_depth_next (&d)) {
1162 xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
1164 for (; v.rem; xcb_visualtype_next (&v)) {
1165 if (v.data->visual_id == visual->visual_id) {
1166 *depth = d.data->depth;
1177 * cairo_xcb_surface_create:
1178 * @connection: an XCB connection
1179 * @drawable: an XCB drawable
1180 * @visual: the visual to use for drawing to @drawable. The depth
1181 * of the visual must match the depth of the drawable.
1182 * Currently, only TrueColor visuals are fully supported.
1183 * @width: the current width of @drawable
1184 * @height: the current height of @drawable
1186 * Creates an XCB surface that draws to the given drawable.
1187 * The way that colors are represented in the drawable is specified
1188 * by the provided visual.
1190 * Note: If @drawable is a Window, then the function
1191 * cairo_xcb_surface_set_size() must be called whenever the size of the
1194 * When @drawable is a Window containing child windows then drawing to
1195 * the created surface will be clipped by those child windows. When
1196 * the created surface is used as a source, the contents of the
1197 * children will be included.
1199 * Return value: a pointer to the newly created surface. The caller
1200 * owns the surface and should call cairo_surface_destroy() when done
1203 * This function always returns a valid pointer, but it will return a
1204 * pointer to a "nil" surface if an error such as out of memory
1205 * occurs. You can use cairo_surface_status() to check for this.
1210 cairo_xcb_surface_create (xcb_connection_t *connection,
1211 xcb_drawable_t drawable,
1212 xcb_visualtype_t *visual,
1216 cairo_xcb_screen_t *screen;
1217 xcb_screen_t *xcb_screen;
1218 cairo_format_masks_t image_masks;
1219 pixman_format_code_t pixman_format;
1220 xcb_render_pictformat_t xrender_format;
1223 if (xcb_connection_has_error (connection))
1224 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1226 if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
1227 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1228 if (unlikely (width <= 0 || height <= 0))
1229 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1231 xcb_screen = _cairo_xcb_screen_from_visual (connection, visual, &depth);
1232 if (unlikely (xcb_screen == NULL))
1233 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1235 image_masks.alpha_mask = 0;
1236 image_masks.red_mask = visual->red_mask;
1237 image_masks.green_mask = visual->green_mask;
1238 image_masks.blue_mask = visual->blue_mask;
1239 if (depth == 32) /* XXX visuals have no alpha! */
1240 image_masks.alpha_mask =
1241 0xffffffff & ~(visual->red_mask | visual->green_mask | visual->blue_mask);
1243 image_masks.bpp = 32;
1245 image_masks.bpp = 16;
1247 image_masks.bpp = 8;
1249 image_masks.bpp = 1;
1251 if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1252 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1254 screen = _cairo_xcb_screen_get (connection, xcb_screen);
1255 if (unlikely (screen == NULL))
1256 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1259 _cairo_xcb_connection_get_xrender_format_for_visual (screen->connection,
1262 return _cairo_xcb_surface_create_internal (screen, drawable, FALSE,
1267 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1268 slim_hidden_def (cairo_xcb_surface_create);
1272 * cairo_xcb_surface_create_for_bitmap:
1273 * @connection: an XCB connection
1274 * @screen: the XCB screen associated with @bitmap
1275 * @bitmap: an XCB drawable (a Pixmap with depth 1)
1276 * @width: the current width of @bitmap
1277 * @height: the current height of @bitmap
1279 * Creates an XCB surface that draws to the given bitmap.
1280 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1282 * Return value: a pointer to the newly created surface. The caller
1283 * owns the surface and should call cairo_surface_destroy() when done
1286 * This function always returns a valid pointer, but it will return a
1287 * pointer to a "nil" surface if an error such as out of memory
1288 * occurs. You can use cairo_surface_status() to check for this.
1293 cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection,
1294 xcb_screen_t *screen,
1295 xcb_pixmap_t bitmap,
1299 cairo_xcb_screen_t *cairo_xcb_screen;
1301 if (xcb_connection_has_error (connection))
1302 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1304 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1305 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1306 if (unlikely (width <= 0 || height <= 0))
1307 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1309 cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1310 if (unlikely (cairo_xcb_screen == NULL))
1311 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1313 return _cairo_xcb_surface_create_internal (cairo_xcb_screen, bitmap, FALSE,
1315 cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1],
1318 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1319 slim_hidden_def (cairo_xcb_surface_create_for_bitmap);
1323 * cairo_xcb_surface_create_with_xrender_format:
1324 * @connection: an XCB connection
1325 * @drawable: an XCB drawable
1326 * @screen: the XCB screen associated with @drawable
1327 * @format: the picture format to use for drawing to @drawable. The
1328 * depth of @format mush match the depth of the drawable.
1329 * @width: the current width of @drawable
1330 * @height: the current height of @drawable
1332 * Creates an XCB surface that draws to the given drawable.
1333 * The way that colors are represented in the drawable is specified
1334 * by the provided picture format.
1336 * Note: If @drawable is a Window, then the function
1337 * cairo_xcb_surface_set_size() must be called whenever the size of the
1340 * When @drawable is a Window containing child windows then drawing to
1341 * the created surface will be clipped by those child windows. When
1342 * the created surface is used as a source, the contents of the
1343 * children will be included.
1345 * Return value: a pointer to the newly created surface. The caller
1346 * owns the surface and should call cairo_surface_destroy() when done
1349 * This function always returns a valid pointer, but it will return a
1350 * pointer to a "nil" surface if an error such as out of memory
1351 * occurs. You can use cairo_surface_status() to check for this.
1356 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection,
1357 xcb_screen_t *screen,
1358 xcb_drawable_t drawable,
1359 xcb_render_pictforminfo_t *format,
1363 cairo_xcb_screen_t *cairo_xcb_screen;
1364 cairo_format_masks_t image_masks;
1365 pixman_format_code_t pixman_format;
1367 if (xcb_connection_has_error (connection))
1368 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1370 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1371 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1372 if (unlikely (width <= 0 || height <= 0))
1373 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1375 image_masks.alpha_mask =
1376 (unsigned long) format->direct.alpha_mask << format->direct.alpha_shift;
1377 image_masks.red_mask =
1378 (unsigned long) format->direct.red_mask << format->direct.red_shift;
1379 image_masks.green_mask =
1380 (unsigned long) format->direct.green_mask << format->direct.green_shift;
1381 image_masks.blue_mask =
1382 (unsigned long) format->direct.blue_mask << format->direct.blue_shift;
1384 image_masks.bpp = format->depth;
1386 if (format->depth > 16)
1387 image_masks.bpp = 32;
1388 else if (format->depth > 8)
1389 image_masks.bpp = 16;
1390 else if (format->depth > 1)
1391 image_masks.bpp = 8;
1393 image_masks.bpp = 1;
1396 if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1397 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1399 cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1400 if (unlikely (cairo_xcb_screen == NULL))
1401 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1403 return _cairo_xcb_surface_create_internal (cairo_xcb_screen,
1410 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1411 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format);
1414 /* This does the necessary fixup when a surface's drawable or size changed. */
1416 _drawable_changed (cairo_xcb_surface_t *surface)
1418 _cairo_surface_begin_modification (&surface->base);
1419 _cairo_boxes_clear (&surface->fallback_damage);
1420 cairo_surface_destroy (&surface->fallback->base);
1422 surface->deferred_clear = FALSE;
1423 surface->fallback = NULL;
1427 * cairo_xcb_surface_set_size:
1428 * @surface: a #cairo_surface_t for the XCB backend
1429 * @width: the new width of the surface
1430 * @height: the new height of the surface
1432 * Informs cairo of the new size of the XCB drawable underlying the
1433 * surface. For a surface created for a window (rather than a pixmap),
1434 * this function must be called each time the size of the window
1435 * changes. (For a subwindow, you are normally resizing the window
1436 * yourself, but for a toplevel window, it is necessary to listen for
1437 * ConfigureNotify events.)
1439 * A pixmap can never change size, so it is never necessary to call
1440 * this function on a surface created for a pixmap.
1442 * If cairo_surface_flush() wasn't called, some pending operations
1443 * might be discarded.
1448 cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
1452 cairo_xcb_surface_t *surface;
1454 if (unlikely (abstract_surface->status))
1456 if (unlikely (abstract_surface->finished)) {
1457 _cairo_surface_set_error (abstract_surface,
1458 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1463 if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1464 _cairo_surface_set_error (abstract_surface,
1465 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1469 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1470 _cairo_surface_set_error (abstract_surface,
1471 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1475 surface = (cairo_xcb_surface_t *) abstract_surface;
1477 _drawable_changed(surface);
1478 surface->width = width;
1479 surface->height = height;
1481 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1482 slim_hidden_def (cairo_xcb_surface_set_size);
1486 * cairo_xcb_surface_set_drawable:
1487 * @surface: a #cairo_surface_t for the XCB backend
1488 * @drawable: the new drawable of the surface
1489 * @width: the new width of the surface
1490 * @height: the new height of the surface
1492 * Informs cairo of the new drawable and size of the XCB drawable underlying the
1495 * If cairo_surface_flush() wasn't called, some pending operations
1496 * might be discarded.
1501 cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
1502 xcb_drawable_t drawable,
1506 cairo_xcb_surface_t *surface;
1508 if (unlikely (abstract_surface->status))
1510 if (unlikely (abstract_surface->finished)) {
1511 _cairo_surface_set_error (abstract_surface,
1512 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1517 if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1518 _cairo_surface_set_error (abstract_surface,
1519 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1523 if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1524 _cairo_surface_set_error (abstract_surface,
1525 _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1529 surface = (cairo_xcb_surface_t *) abstract_surface;
1531 /* XXX: and what about this case? */
1532 if (surface->owns_pixmap)
1535 _drawable_changed (surface);
1537 if (surface->drawable != drawable) {
1538 cairo_status_t status;
1539 status = _cairo_xcb_connection_acquire (surface->connection);
1540 if (unlikely (status))
1543 if (surface->picture != XCB_NONE) {
1544 _cairo_xcb_connection_render_free_picture (surface->connection,
1546 surface->picture = XCB_NONE;
1549 _cairo_xcb_connection_release (surface->connection);
1551 surface->drawable = drawable;
1553 surface->width = width;
1554 surface->height = height;
1556 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1557 slim_hidden_def (cairo_xcb_surface_set_drawable);