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 reply
=_cairo_xcb_connection_get_image (connection
,
390 if (reply
== NULL
&& ! surface
->owns_pixmap
) {
391 /* xcb_get_image_t from a window is dangerous because it can
392 * produce errors if the window is unmapped or partially
393 * outside the screen. We could check for errors and
394 * retry, but to keep things simple, we just create a
397 * If we hit this fallback too often, we should remember so and
398 * skip the round-trip from the above GetImage request,
399 * similar to what cairo-xlib does.
404 gc
= _cairo_xcb_screen_get_gc (surface
->screen
,
407 pixmap
= _cairo_xcb_connection_create_pixmap (connection
,
412 /* XXX IncludeInferiors? */
413 _cairo_xcb_connection_copy_area (connection
,
420 _cairo_xcb_screen_put_gc (surface
->screen
, surface
->depth
, gc
);
422 reply
= _cairo_xcb_connection_get_image (connection
,
426 _cairo_xcb_connection_free_pixmap (connection
, pixmap
);
429 if (unlikely (reply
== NULL
)) {
430 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
435 /* XXX format conversion */
436 assert (reply
->depth
== surface
->depth
);
438 image
= _cairo_image_surface_create_with_pixman_format
439 (xcb_get_image_data (reply
),
440 surface
->pixman_format
,
442 CAIRO_STRIDE_FOR_WIDTH_BPP (width
,
443 PIXMAN_FORMAT_BPP (surface
->pixman_format
)));
444 status
= image
->status
;
445 if (unlikely (status
)) {
451 pixman_image_set_destroy_function (((cairo_image_surface_t
*)image
)->pixman_image
, _destroy_image
, reply
);
453 _cairo_xcb_connection_release (connection
);
458 _cairo_xcb_connection_release (connection
);
459 return _cairo_surface_create_in_error (status
);
462 static cairo_surface_t
*
463 _cairo_xcb_surface_source (void *abstract_surface
,
464 cairo_rectangle_int_t
*extents
)
466 cairo_xcb_surface_t
*surface
= abstract_surface
;
469 extents
->x
= extents
->y
= 0;
470 extents
->width
= surface
->width
;
471 extents
->height
= surface
->height
;
474 return &surface
->base
;
477 static cairo_status_t
478 _cairo_xcb_surface_acquire_source_image (void *abstract_surface
,
479 cairo_image_surface_t
**image_out
,
482 cairo_xcb_surface_t
*surface
= abstract_surface
;
483 cairo_surface_t
*image
;
485 if (surface
->fallback
!= NULL
) {
486 image
= cairo_surface_reference (&surface
->fallback
->base
);
490 image
= _cairo_surface_has_snapshot (&surface
->base
,
491 &_cairo_image_surface_backend
);
493 image
= cairo_surface_reference (image
);
497 image
= _get_image (surface
, FALSE
, 0, 0, surface
->width
, surface
->height
);
498 if (unlikely (image
->status
))
499 return image
->status
;
501 _cairo_surface_attach_snapshot (&surface
->base
, image
, NULL
);
504 *image_out
= (cairo_image_surface_t
*) image
;
506 return CAIRO_STATUS_SUCCESS
;
510 _cairo_xcb_surface_release_source_image (void *abstract_surface
,
511 cairo_image_surface_t
*image
,
514 cairo_surface_destroy (&image
->base
);
518 _cairo_xcb_surface_get_extents (void *abstract_surface
,
519 cairo_rectangle_int_t
*extents
)
521 cairo_xcb_surface_t
*surface
= abstract_surface
;
523 extents
->x
= extents
->y
= 0;
524 extents
->width
= surface
->width
;
525 extents
->height
= surface
->height
;
530 _cairo_xcb_surface_get_font_options (void *abstract_surface
,
531 cairo_font_options_t
*options
)
533 cairo_xcb_surface_t
*surface
= abstract_surface
;
535 *options
= *_cairo_xcb_screen_get_font_options (surface
->screen
);
538 static cairo_status_t
539 _put_shm_image (cairo_xcb_surface_t
*surface
,
541 cairo_image_surface_t
*image
)
543 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
544 cairo_xcb_shm_info_t
*shm_info
;
546 shm_info
= _cairo_user_data_array_get_data (&image
->base
.user_data
,
547 (const cairo_user_data_key_t
*) surface
->connection
);
548 if (shm_info
== NULL
)
549 return CAIRO_INT_STATUS_UNSUPPORTED
;
551 _cairo_xcb_connection_shm_put_image (surface
->connection
,
554 surface
->width
, surface
->height
,
556 image
->width
, image
->height
,
557 image
->base
.device_transform_inverse
.x0
,
558 image
->base
.device_transform_inverse
.y0
,
563 return CAIRO_STATUS_SUCCESS
;
565 return CAIRO_INT_STATUS_UNSUPPORTED
;
569 static cairo_status_t
570 _put_image (cairo_xcb_surface_t
*surface
,
571 cairo_image_surface_t
*image
)
573 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
;
575 /* XXX track damaged region? */
577 status
= _cairo_xcb_connection_acquire (surface
->connection
);
578 if (unlikely (status
))
581 if (image
->pixman_format
== surface
->pixman_format
) {
584 assert (image
->depth
== surface
->depth
);
585 assert (image
->stride
== (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image
->width
, PIXMAN_FORMAT_BPP (image
->pixman_format
)));
587 gc
= _cairo_xcb_screen_get_gc (surface
->screen
,
591 status
= _put_shm_image (surface
, gc
, image
);
592 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
593 _cairo_xcb_connection_put_image (surface
->connection
,
594 surface
->drawable
, gc
,
595 image
->width
, image
->height
,
596 image
->base
.device_transform_inverse
.x0
,
597 image
->base
.device_transform_inverse
.y0
,
601 status
= CAIRO_STATUS_SUCCESS
;
604 _cairo_xcb_screen_put_gc (surface
->screen
, surface
->depth
, gc
);
609 _cairo_xcb_connection_release (surface
->connection
);
613 static cairo_int_status_t
614 _put_shm_image_boxes (cairo_xcb_surface_t
*surface
,
615 cairo_image_surface_t
*image
,
617 cairo_boxes_t
*boxes
)
619 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
620 cairo_xcb_shm_info_t
*shm_info
;
622 shm_info
= _cairo_user_data_array_get_data (&image
->base
.user_data
,
623 (const cairo_user_data_key_t
*) surface
->connection
);
624 if (shm_info
!= NULL
) {
625 struct _cairo_boxes_chunk
*chunk
;
627 for (chunk
= &boxes
->chunks
; chunk
; chunk
= chunk
->next
) {
630 for (i
= 0; i
< chunk
->count
; i
++) {
631 cairo_box_t
*b
= &chunk
->base
[i
];
632 int x
= _cairo_fixed_integer_part (b
->p1
.x
);
633 int y
= _cairo_fixed_integer_part (b
->p1
.y
);
634 int width
= _cairo_fixed_integer_part (b
->p2
.x
- b
->p1
.x
);
635 int height
= _cairo_fixed_integer_part (b
->p2
.y
- b
->p1
.y
);
637 _cairo_xcb_connection_shm_put_image (surface
->connection
,
640 surface
->width
, surface
->height
,
649 return CAIRO_INT_STATUS_SUCCESS
;
653 return CAIRO_INT_STATUS_UNSUPPORTED
;
656 static cairo_status_t
657 _put_image_boxes (cairo_xcb_surface_t
*surface
,
658 cairo_image_surface_t
*image
,
659 cairo_boxes_t
*boxes
)
661 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
;
664 if (boxes
->num_boxes
== 0)
665 return CAIRO_STATUS_SUCCESS
;
667 /* XXX track damaged region? */
669 status
= _cairo_xcb_connection_acquire (surface
->connection
);
670 if (unlikely (status
))
673 assert (image
->pixman_format
== surface
->pixman_format
);
674 assert (image
->depth
== surface
->depth
);
675 assert (image
->stride
== (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image
->width
, PIXMAN_FORMAT_BPP (image
->pixman_format
)));
677 gc
= _cairo_xcb_screen_get_gc (surface
->screen
,
681 status
= _put_shm_image_boxes (surface
, image
, gc
, boxes
);
682 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
) {
683 struct _cairo_boxes_chunk
*chunk
;
685 for (chunk
= &boxes
->chunks
; chunk
; chunk
= chunk
->next
) {
688 for (i
= 0; i
< chunk
->count
; i
++) {
689 cairo_box_t
*b
= &chunk
->base
[i
];
690 int x
= _cairo_fixed_integer_part (b
->p1
.x
);
691 int y
= _cairo_fixed_integer_part (b
->p1
.y
);
692 int width
= _cairo_fixed_integer_part (b
->p2
.x
- b
->p1
.x
);
693 int height
= _cairo_fixed_integer_part (b
->p2
.y
- b
->p1
.y
);
694 _cairo_xcb_connection_put_subimage (surface
->connection
,
695 surface
->drawable
, gc
,
698 PIXMAN_FORMAT_BPP (image
->pixman_format
) / 8,
706 status
= CAIRO_STATUS_SUCCESS
;
709 _cairo_xcb_screen_put_gc (surface
->screen
, surface
->depth
, gc
);
710 _cairo_xcb_connection_release (surface
->connection
);
714 static cairo_status_t
715 _cairo_xcb_surface_flush (void *abstract_surface
,
718 cairo_xcb_surface_t
*surface
= abstract_surface
;
719 cairo_status_t status
;
722 return CAIRO_STATUS_SUCCESS
;
724 if (likely (surface
->fallback
== NULL
)) {
725 status
= CAIRO_STATUS_SUCCESS
;
726 if (! surface
->base
.finished
&& surface
->deferred_clear
)
727 status
= _cairo_xcb_surface_clear (surface
);
732 status
= surface
->base
.status
;
733 if (status
== CAIRO_STATUS_SUCCESS
&&
734 (! surface
->base
._finishing
|| ! surface
->owns_pixmap
)) {
735 status
= cairo_surface_status (&surface
->fallback
->base
);
737 if (status
== CAIRO_STATUS_SUCCESS
)
738 status
= _cairo_bentley_ottmann_tessellate_boxes (&surface
->fallback_damage
,
739 CAIRO_FILL_RULE_WINDING
,
740 &surface
->fallback_damage
);
742 if (status
== CAIRO_STATUS_SUCCESS
)
743 status
= _put_image_boxes (surface
,
745 &surface
->fallback_damage
);
747 if (status
== CAIRO_STATUS_SUCCESS
&& ! surface
->base
._finishing
) {
748 _cairo_surface_attach_snapshot (&surface
->base
,
749 &surface
->fallback
->base
,
750 cairo_surface_finish
);
754 _cairo_boxes_clear (&surface
->fallback_damage
);
755 cairo_surface_destroy (&surface
->fallback
->base
);
756 surface
->fallback
= NULL
;
761 static cairo_image_surface_t
*
762 _cairo_xcb_surface_map_to_image (void *abstract_surface
,
763 const cairo_rectangle_int_t
*extents
)
765 cairo_xcb_surface_t
*surface
= abstract_surface
;
766 cairo_surface_t
*image
;
767 cairo_status_t status
;
769 if (surface
->fallback
)
770 return _cairo_surface_map_to_image (&surface
->fallback
->base
, extents
);
772 image
= _get_image (surface
, TRUE
,
773 extents
->x
, extents
->y
,
774 extents
->width
, extents
->height
);
775 status
= cairo_surface_status (image
);
776 if (unlikely (status
)) {
777 cairo_surface_destroy(image
);
778 return _cairo_image_surface_create_in_error (status
);
781 /* Do we have a deferred clear and this image surface does NOT cover the
782 * whole xcb surface? Have to apply the clear in that case, else
783 * uploading the image will handle the problem for us.
785 if (surface
->deferred_clear
&&
786 ! (extents
->width
== surface
->width
&&
787 extents
->height
== surface
->height
)) {
788 status
= _cairo_xcb_surface_clear (surface
);
789 if (unlikely (status
)) {
790 cairo_surface_destroy(image
);
791 return _cairo_image_surface_create_in_error (status
);
794 surface
->deferred_clear
= FALSE
;
796 cairo_surface_set_device_offset (image
, -extents
->x
, -extents
->y
);
797 return (cairo_image_surface_t
*) image
;
800 static cairo_int_status_t
801 _cairo_xcb_surface_unmap (void *abstract_surface
,
802 cairo_image_surface_t
*image
)
804 cairo_xcb_surface_t
*surface
= abstract_surface
;
805 cairo_int_status_t status
;
807 if (surface
->fallback
)
808 return _cairo_surface_unmap_image (&surface
->fallback
->base
, image
);
810 status
= _put_image (abstract_surface
, image
);
812 cairo_surface_finish (&image
->base
);
813 cairo_surface_destroy (&image
->base
);
818 static cairo_surface_t
*
819 _cairo_xcb_surface_fallback (cairo_xcb_surface_t
*surface
,
820 cairo_composite_rectangles_t
*composite
)
822 cairo_image_surface_t
*image
;
823 cairo_status_t status
;
825 status
= _cairo_composite_rectangles_add_to_damage (composite
,
826 &surface
->fallback_damage
);
827 if (unlikely (status
))
828 return _cairo_surface_create_in_error (status
);
830 if (surface
->fallback
)
831 return &surface
->fallback
->base
;
833 image
= (cairo_image_surface_t
*)
834 _get_image (surface
, TRUE
, 0, 0, surface
->width
, surface
->height
);
836 /* If there was a deferred clear, _get_image applied it */
837 if (image
->base
.status
== CAIRO_STATUS_SUCCESS
) {
838 surface
->deferred_clear
= FALSE
;
840 surface
->fallback
= image
;
843 return &surface
->fallback
->base
;
846 static cairo_int_status_t
847 _cairo_xcb_fallback_compositor_paint (const cairo_compositor_t
*compositor
,
848 cairo_composite_rectangles_t
*extents
)
850 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) extents
->surface
;
851 cairo_surface_t
*fallback
= _cairo_xcb_surface_fallback (surface
, extents
);
853 return _cairo_surface_paint (fallback
, extents
->op
,
854 &extents
->source_pattern
.base
,
858 static cairo_int_status_t
859 _cairo_xcb_fallback_compositor_mask (const cairo_compositor_t
*compositor
,
860 cairo_composite_rectangles_t
*extents
)
862 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) extents
->surface
;
863 cairo_surface_t
*fallback
= _cairo_xcb_surface_fallback (surface
, extents
);
865 return _cairo_surface_mask (fallback
, extents
->op
,
866 &extents
->source_pattern
.base
,
867 &extents
->mask_pattern
.base
,
871 static cairo_int_status_t
872 _cairo_xcb_fallback_compositor_stroke (const cairo_compositor_t
*compositor
,
873 cairo_composite_rectangles_t
*extents
,
874 const cairo_path_fixed_t
*path
,
875 const cairo_stroke_style_t
*style
,
876 const cairo_matrix_t
*ctm
,
877 const cairo_matrix_t
*ctm_inverse
,
879 cairo_antialias_t antialias
)
881 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) extents
->surface
;
882 cairo_surface_t
*fallback
= _cairo_xcb_surface_fallback (surface
, extents
);
884 return _cairo_surface_stroke (fallback
, extents
->op
,
885 &extents
->source_pattern
.base
,
886 path
, style
, ctm
, ctm_inverse
,
887 tolerance
, antialias
,
891 static cairo_int_status_t
892 _cairo_xcb_fallback_compositor_fill (const cairo_compositor_t
*compositor
,
893 cairo_composite_rectangles_t
*extents
,
894 const cairo_path_fixed_t
*path
,
895 cairo_fill_rule_t fill_rule
,
897 cairo_antialias_t antialias
)
899 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) extents
->surface
;
900 cairo_surface_t
*fallback
= _cairo_xcb_surface_fallback (surface
, extents
);
902 return _cairo_surface_fill (fallback
, extents
->op
,
903 &extents
->source_pattern
.base
,
904 path
, fill_rule
, tolerance
,
905 antialias
, extents
->clip
);
908 static cairo_int_status_t
909 _cairo_xcb_fallback_compositor_glyphs (const cairo_compositor_t
*compositor
,
910 cairo_composite_rectangles_t
*extents
,
911 cairo_scaled_font_t
*scaled_font
,
912 cairo_glyph_t
*glyphs
,
914 cairo_bool_t overlap
)
916 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) extents
->surface
;
917 cairo_surface_t
*fallback
= _cairo_xcb_surface_fallback (surface
, extents
);
919 return _cairo_surface_show_text_glyphs (fallback
, extents
->op
,
920 &extents
->source_pattern
.base
,
921 NULL
, 0, glyphs
, num_glyphs
,
923 scaled_font
, extents
->clip
);
926 static const cairo_compositor_t _cairo_xcb_fallback_compositor
= {
927 &__cairo_no_compositor
,
929 _cairo_xcb_fallback_compositor_paint
,
930 _cairo_xcb_fallback_compositor_mask
,
931 _cairo_xcb_fallback_compositor_stroke
,
932 _cairo_xcb_fallback_compositor_fill
,
933 _cairo_xcb_fallback_compositor_glyphs
,
936 static const cairo_compositor_t _cairo_xcb_render_compositor
= {
937 &_cairo_xcb_fallback_compositor
,
939 _cairo_xcb_render_compositor_paint
,
940 _cairo_xcb_render_compositor_mask
,
941 _cairo_xcb_render_compositor_stroke
,
942 _cairo_xcb_render_compositor_fill
,
943 _cairo_xcb_render_compositor_glyphs
,
946 static inline const cairo_compositor_t
*
947 get_compositor (cairo_surface_t
**s
)
949 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
* )*s
;
950 if (surface
->fallback
) {
951 *s
= &surface
->fallback
->base
;
952 return ((cairo_image_surface_t
*) *s
)->compositor
;
955 return &_cairo_xcb_render_compositor
;
958 static cairo_int_status_t
959 _cairo_xcb_surface_paint (void *abstract_surface
,
961 const cairo_pattern_t
*source
,
962 const cairo_clip_t
*clip
)
964 cairo_surface_t
*surface
= abstract_surface
;
965 const cairo_compositor_t
*compositor
= get_compositor (&surface
);
966 return _cairo_compositor_paint (compositor
, surface
, op
, source
, clip
);
969 static cairo_int_status_t
970 _cairo_xcb_surface_mask (void *abstract_surface
,
972 const cairo_pattern_t
*source
,
973 const cairo_pattern_t
*mask
,
974 const cairo_clip_t
*clip
)
976 cairo_surface_t
*surface
= abstract_surface
;
977 const cairo_compositor_t
*compositor
= get_compositor (&surface
);
978 return _cairo_compositor_mask (compositor
, surface
, op
, source
, mask
, clip
);
981 static cairo_int_status_t
982 _cairo_xcb_surface_stroke (void *abstract_surface
,
984 const cairo_pattern_t
*source
,
985 const cairo_path_fixed_t
*path
,
986 const cairo_stroke_style_t
*style
,
987 const cairo_matrix_t
*ctm
,
988 const cairo_matrix_t
*ctm_inverse
,
990 cairo_antialias_t antialias
,
991 const cairo_clip_t
*clip
)
993 cairo_surface_t
*surface
= abstract_surface
;
994 const cairo_compositor_t
*compositor
= get_compositor (&surface
);
995 return _cairo_compositor_stroke (compositor
, surface
, op
, source
,
996 path
, style
, ctm
, ctm_inverse
,
997 tolerance
, antialias
, clip
);
1000 static cairo_int_status_t
1001 _cairo_xcb_surface_fill (void *abstract_surface
,
1002 cairo_operator_t op
,
1003 const cairo_pattern_t
*source
,
1004 const cairo_path_fixed_t
*path
,
1005 cairo_fill_rule_t fill_rule
,
1007 cairo_antialias_t antialias
,
1008 const cairo_clip_t
*clip
)
1010 cairo_surface_t
*surface
= abstract_surface
;
1011 const cairo_compositor_t
*compositor
= get_compositor (&surface
);
1012 return _cairo_compositor_fill (compositor
, surface
, op
,
1013 source
, path
, fill_rule
,
1014 tolerance
, antialias
, clip
);
1017 static cairo_int_status_t
1018 _cairo_xcb_surface_glyphs (void *abstract_surface
,
1019 cairo_operator_t op
,
1020 const cairo_pattern_t
*source
,
1021 cairo_glyph_t
*glyphs
,
1023 cairo_scaled_font_t
*scaled_font
,
1024 const cairo_clip_t
*clip
)
1026 cairo_surface_t
*surface
= abstract_surface
;
1027 const cairo_compositor_t
*compositor
= get_compositor (&surface
);
1028 return _cairo_compositor_glyphs (compositor
, surface
, op
,
1029 source
, glyphs
, num_glyphs
,
1033 const cairo_surface_backend_t _cairo_xcb_surface_backend
= {
1034 CAIRO_SURFACE_TYPE_XCB
,
1035 _cairo_xcb_surface_finish
,
1036 _cairo_default_context_create
,
1038 _cairo_xcb_surface_create_similar
,
1039 _cairo_xcb_surface_create_similar_image
,
1040 _cairo_xcb_surface_map_to_image
,
1041 _cairo_xcb_surface_unmap
,
1043 _cairo_xcb_surface_source
,
1044 _cairo_xcb_surface_acquire_source_image
,
1045 _cairo_xcb_surface_release_source_image
,
1046 NULL
, /* snapshot */
1049 NULL
, /* copy_page */
1050 NULL
, /* show_page */
1052 _cairo_xcb_surface_get_extents
,
1053 _cairo_xcb_surface_get_font_options
,
1055 _cairo_xcb_surface_flush
,
1058 _cairo_xcb_surface_paint
,
1059 _cairo_xcb_surface_mask
,
1060 _cairo_xcb_surface_stroke
,
1061 _cairo_xcb_surface_fill
,
1062 NULL
, /* fill-stroke */
1063 _cairo_xcb_surface_glyphs
,
1067 _cairo_xcb_surface_create_internal (cairo_xcb_screen_t
*screen
,
1068 xcb_drawable_t drawable
,
1069 cairo_bool_t owns_pixmap
,
1070 pixman_format_code_t pixman_format
,
1071 xcb_render_pictformat_t xrender_format
,
1075 cairo_xcb_surface_t
*surface
;
1077 surface
= malloc (sizeof (cairo_xcb_surface_t
));
1078 if (unlikely (surface
== NULL
))
1079 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1081 _cairo_surface_init (&surface
->base
,
1082 &_cairo_xcb_surface_backend
,
1083 &screen
->connection
->device
,
1084 _cairo_content_from_pixman_format (pixman_format
));
1086 surface
->connection
= _cairo_xcb_connection_reference (screen
->connection
);
1087 surface
->screen
= screen
;
1088 cairo_list_add (&surface
->link
, &screen
->surfaces
);
1090 surface
->drawable
= drawable
;
1091 surface
->owns_pixmap
= owns_pixmap
;
1093 surface
->deferred_clear
= FALSE
;
1094 surface
->deferred_clear_color
= *CAIRO_COLOR_TRANSPARENT
;
1096 surface
->width
= width
;
1097 surface
->height
= height
;
1098 surface
->depth
= PIXMAN_FORMAT_DEPTH (pixman_format
);
1100 surface
->picture
= XCB_NONE
;
1101 if (screen
->connection
->force_precision
!= -1)
1102 surface
->precision
= screen
->connection
->force_precision
;
1104 surface
->precision
= XCB_RENDER_POLY_MODE_IMPRECISE
;
1106 surface
->pixman_format
= pixman_format
;
1107 surface
->xrender_format
= xrender_format
;
1109 surface
->fallback
= NULL
;
1110 _cairo_boxes_init (&surface
->fallback_damage
);
1112 return &surface
->base
;
1115 static xcb_screen_t
*
1116 _cairo_xcb_screen_from_visual (xcb_connection_t
*connection
,
1117 xcb_visualtype_t
*visual
,
1120 xcb_depth_iterator_t d
;
1121 xcb_screen_iterator_t s
;
1123 s
= xcb_setup_roots_iterator (xcb_get_setup (connection
));
1124 for (; s
.rem
; xcb_screen_next (&s
)) {
1125 if (s
.data
->root_visual
== visual
->visual_id
) {
1126 *depth
= s
.data
->root_depth
;
1130 d
= xcb_screen_allowed_depths_iterator(s
.data
);
1131 for (; d
.rem
; xcb_depth_next (&d
)) {
1132 xcb_visualtype_iterator_t v
= xcb_depth_visuals_iterator (d
.data
);
1134 for (; v
.rem
; xcb_visualtype_next (&v
)) {
1135 if (v
.data
->visual_id
== visual
->visual_id
) {
1136 *depth
= d
.data
->depth
;
1147 * cairo_xcb_surface_create:
1148 * @connection: an XCB connection
1149 * @drawable: an XCB drawable
1150 * @visual: the visual to use for drawing to @drawable. The depth
1151 * of the visual must match the depth of the drawable.
1152 * Currently, only TrueColor visuals are fully supported.
1153 * @width: the current width of @drawable
1154 * @height: the current height of @drawable
1156 * Creates an XCB surface that draws to the given drawable.
1157 * The way that colors are represented in the drawable is specified
1158 * by the provided visual.
1160 * Note: If @drawable is a Window, then the function
1161 * cairo_xcb_surface_set_size() must be called whenever the size of the
1164 * When @drawable is a Window containing child windows then drawing to
1165 * the created surface will be clipped by those child windows. When
1166 * the created surface is used as a source, the contents of the
1167 * children will be included.
1169 * Return value: a pointer to the newly created surface. The caller
1170 * owns the surface and should call cairo_surface_destroy() when done
1173 * This function always returns a valid pointer, but it will return a
1174 * pointer to a "nil" surface if an error such as out of memory
1175 * occurs. You can use cairo_surface_status() to check for this.
1180 cairo_xcb_surface_create (xcb_connection_t
*connection
,
1181 xcb_drawable_t drawable
,
1182 xcb_visualtype_t
*visual
,
1186 cairo_xcb_screen_t
*screen
;
1187 xcb_screen_t
*xcb_screen
;
1188 cairo_format_masks_t image_masks
;
1189 pixman_format_code_t pixman_format
;
1190 xcb_render_pictformat_t xrender_format
;
1193 if (xcb_connection_has_error (connection
))
1194 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR
));
1196 if (unlikely (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
))
1197 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1198 if (unlikely (width
<= 0 || height
<= 0))
1199 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1201 xcb_screen
= _cairo_xcb_screen_from_visual (connection
, visual
, &depth
);
1202 if (unlikely (xcb_screen
== NULL
))
1203 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
1205 image_masks
.alpha_mask
= 0;
1206 image_masks
.red_mask
= visual
->red_mask
;
1207 image_masks
.green_mask
= visual
->green_mask
;
1208 image_masks
.blue_mask
= visual
->blue_mask
;
1209 if (depth
== 32) /* XXX visuals have no alpha! */
1210 image_masks
.alpha_mask
=
1211 0xffffffff & ~(visual
->red_mask
| visual
->green_mask
| visual
->blue_mask
);
1213 image_masks
.bpp
= 32;
1215 image_masks
.bpp
= 16;
1217 image_masks
.bpp
= 8;
1219 image_masks
.bpp
= 1;
1221 if (! _pixman_format_from_masks (&image_masks
, &pixman_format
))
1222 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT
));
1224 screen
= _cairo_xcb_screen_get (connection
, xcb_screen
);
1225 if (unlikely (screen
== NULL
))
1226 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1229 _cairo_xcb_connection_get_xrender_format_for_visual (screen
->connection
,
1232 return _cairo_xcb_surface_create_internal (screen
, drawable
, FALSE
,
1237 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1238 slim_hidden_def (cairo_xcb_surface_create
);
1242 * cairo_xcb_surface_create_for_bitmap:
1243 * @connection: an XCB connection
1244 * @screen: the XCB screen associated with @bitmap
1245 * @bitmap: an XCB drawable (a Pixmap with depth 1)
1246 * @width: the current width of @bitmap
1247 * @height: the current height of @bitmap
1249 * Creates an XCB surface that draws to the given bitmap.
1250 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1252 * Return value: a pointer to the newly created surface. The caller
1253 * owns the surface and should call cairo_surface_destroy() when done
1256 * This function always returns a valid pointer, but it will return a
1257 * pointer to a "nil" surface if an error such as out of memory
1258 * occurs. You can use cairo_surface_status() to check for this.
1263 cairo_xcb_surface_create_for_bitmap (xcb_connection_t
*connection
,
1264 xcb_screen_t
*screen
,
1265 xcb_pixmap_t bitmap
,
1269 cairo_xcb_screen_t
*cairo_xcb_screen
;
1271 if (xcb_connection_has_error (connection
))
1272 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR
));
1274 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
1275 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1276 if (unlikely (width
<= 0 || height
<= 0))
1277 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1279 cairo_xcb_screen
= _cairo_xcb_screen_get (connection
, screen
);
1280 if (unlikely (cairo_xcb_screen
== NULL
))
1281 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1283 return _cairo_xcb_surface_create_internal (cairo_xcb_screen
, bitmap
, FALSE
,
1285 cairo_xcb_screen
->connection
->standard_formats
[CAIRO_FORMAT_A1
],
1288 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1289 slim_hidden_def (cairo_xcb_surface_create_for_bitmap
);
1293 * cairo_xcb_surface_create_with_xrender_format:
1294 * @connection: an XCB connection
1295 * @drawable: an XCB drawable
1296 * @screen: the XCB screen associated with @drawable
1297 * @format: the picture format to use for drawing to @drawable. The
1298 * depth of @format mush match the depth of the drawable.
1299 * @width: the current width of @drawable
1300 * @height: the current height of @drawable
1302 * Creates an XCB surface that draws to the given drawable.
1303 * The way that colors are represented in the drawable is specified
1304 * by the provided picture format.
1306 * Note: If @drawable is a Window, then the function
1307 * cairo_xcb_surface_set_size() must be called whenever the size of the
1310 * When @drawable is a Window containing child windows then drawing to
1311 * the created surface will be clipped by those child windows. When
1312 * the created surface is used as a source, the contents of the
1313 * children will be included.
1315 * Return value: a pointer to the newly created surface. The caller
1316 * owns the surface and should call cairo_surface_destroy() when done
1319 * This function always returns a valid pointer, but it will return a
1320 * pointer to a "nil" surface if an error such as out of memory
1321 * occurs. You can use cairo_surface_status() to check for this.
1326 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t
*connection
,
1327 xcb_screen_t
*screen
,
1328 xcb_drawable_t drawable
,
1329 xcb_render_pictforminfo_t
*format
,
1333 cairo_xcb_screen_t
*cairo_xcb_screen
;
1334 cairo_format_masks_t image_masks
;
1335 pixman_format_code_t pixman_format
;
1337 if (xcb_connection_has_error (connection
))
1338 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR
));
1340 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
1341 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1342 if (unlikely (width
<= 0 || height
<= 0))
1343 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1345 image_masks
.alpha_mask
=
1346 (unsigned long) format
->direct
.alpha_mask
<< format
->direct
.alpha_shift
;
1347 image_masks
.red_mask
=
1348 (unsigned long) format
->direct
.red_mask
<< format
->direct
.red_shift
;
1349 image_masks
.green_mask
=
1350 (unsigned long) format
->direct
.green_mask
<< format
->direct
.green_shift
;
1351 image_masks
.blue_mask
=
1352 (unsigned long) format
->direct
.blue_mask
<< format
->direct
.blue_shift
;
1354 image_masks
.bpp
= format
->depth
;
1356 if (format
->depth
> 16)
1357 image_masks
.bpp
= 32;
1358 else if (format
->depth
> 8)
1359 image_masks
.bpp
= 16;
1360 else if (format
->depth
> 1)
1361 image_masks
.bpp
= 8;
1363 image_masks
.bpp
= 1;
1366 if (! _pixman_format_from_masks (&image_masks
, &pixman_format
))
1367 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT
));
1369 cairo_xcb_screen
= _cairo_xcb_screen_get (connection
, screen
);
1370 if (unlikely (cairo_xcb_screen
== NULL
))
1371 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1373 return _cairo_xcb_surface_create_internal (cairo_xcb_screen
,
1380 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1381 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format
);
1384 /* This does the necessary fixup when a surface's drawable or size changed. */
1386 _drawable_changed (cairo_xcb_surface_t
*surface
)
1388 _cairo_surface_set_error (&surface
->base
,
1389 _cairo_surface_begin_modification (&surface
->base
));
1390 _cairo_boxes_clear (&surface
->fallback_damage
);
1391 cairo_surface_destroy (&surface
->fallback
->base
);
1393 surface
->deferred_clear
= FALSE
;
1394 surface
->fallback
= NULL
;
1398 * cairo_xcb_surface_set_size:
1399 * @surface: a #cairo_surface_t for the XCB backend
1400 * @width: the new width of the surface
1401 * @height: the new height of the surface
1403 * Informs cairo of the new size of the XCB drawable underlying the
1404 * surface. For a surface created for a window (rather than a pixmap),
1405 * this function must be called each time the size of the window
1406 * changes. (For a subwindow, you are normally resizing the window
1407 * yourself, but for a toplevel window, it is necessary to listen for
1408 * ConfigureNotify events.)
1410 * A pixmap can never change size, so it is never necessary to call
1411 * this function on a surface created for a pixmap.
1413 * If cairo_surface_flush() wasn't called, some pending operations
1414 * might be discarded.
1419 cairo_xcb_surface_set_size (cairo_surface_t
*abstract_surface
,
1423 cairo_xcb_surface_t
*surface
;
1425 if (unlikely (abstract_surface
->status
))
1427 if (unlikely (abstract_surface
->finished
)) {
1428 _cairo_surface_set_error (abstract_surface
,
1429 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
));
1434 if ( !_cairo_surface_is_xcb(abstract_surface
)) {
1435 _cairo_surface_set_error (abstract_surface
,
1436 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
));
1440 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
|| width
<= 0 || height
<= 0) {
1441 _cairo_surface_set_error (abstract_surface
,
1442 _cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1446 surface
= (cairo_xcb_surface_t
*) abstract_surface
;
1448 _drawable_changed(surface
);
1449 surface
->width
= width
;
1450 surface
->height
= height
;
1452 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1453 slim_hidden_def (cairo_xcb_surface_set_size
);
1457 * cairo_xcb_surface_set_drawable:
1458 * @surface: a #cairo_surface_t for the XCB backend
1459 * @drawable: the new drawable of the surface
1460 * @width: the new width of the surface
1461 * @height: the new height of the surface
1463 * Informs cairo of the new drawable and size of the XCB drawable underlying the
1466 * If cairo_surface_flush() wasn't called, some pending operations
1467 * might be discarded.
1472 cairo_xcb_surface_set_drawable (cairo_surface_t
*abstract_surface
,
1473 xcb_drawable_t drawable
,
1477 cairo_xcb_surface_t
*surface
;
1479 if (unlikely (abstract_surface
->status
))
1481 if (unlikely (abstract_surface
->finished
)) {
1482 _cairo_surface_set_error (abstract_surface
,
1483 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED
));
1488 if ( !_cairo_surface_is_xcb(abstract_surface
)) {
1489 _cairo_surface_set_error (abstract_surface
,
1490 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
));
1494 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
|| width
<= 0 || height
<= 0) {
1495 _cairo_surface_set_error (abstract_surface
,
1496 _cairo_error (CAIRO_STATUS_INVALID_SIZE
));
1500 surface
= (cairo_xcb_surface_t
*) abstract_surface
;
1502 /* XXX: and what about this case? */
1503 if (surface
->owns_pixmap
)
1506 _drawable_changed (surface
);
1508 if (surface
->drawable
!= drawable
) {
1509 cairo_status_t status
;
1510 status
= _cairo_xcb_connection_acquire (surface
->connection
);
1511 if (unlikely (status
))
1514 if (surface
->picture
!= XCB_NONE
) {
1515 _cairo_xcb_connection_render_free_picture (surface
->connection
,
1517 surface
->picture
= XCB_NONE
;
1520 _cairo_xcb_connection_release (surface
->connection
);
1522 surface
->drawable
= drawable
;
1524 surface
->width
= width
;
1525 surface
->height
= height
;
1527 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1528 slim_hidden_def (cairo_xcb_surface_set_drawable
);