1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2002 University of Southern California
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is University of Southern
34 * Carl D. Worth <cworth@cworth.org>
38 #include "cairo-xcb.h"
39 #include "cairo-xcb-xrender.h"
40 #include "cairo-clip-private.h"
41 #include <xcb/xcb_renderutil.h>
43 #define AllPlanes ((unsigned long)~0L)
45 slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format
);
48 * Instead of taking two round trips for each blending request,
49 * assume that if a particular drawable fails GetImage that it will
50 * fail for a "while"; use temporary pixmaps to avoid the errors
53 #define CAIRO_ASSUME_PIXMAP 20
55 typedef struct cairo_xcb_surface
{
58 xcb_connection_t
*dpy
;
62 xcb_drawable_t drawable
;
63 cairo_bool_t owns_pixmap
;
64 xcb_visualtype_t
*visual
;
75 cairo_bool_t have_clip_rects
;
76 xcb_rectangle_t
*clip_rects
;
79 xcb_render_picture_t src_picture
, dst_picture
;
80 xcb_render_pictforminfo_t xrender_format
;
81 } cairo_xcb_surface_t
;
83 #define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
84 (((surface)->render_major > major) || \
85 (((surface)->render_major == major) && ((surface)->render_minor >= minor)))
87 #define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
88 #define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
89 #define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
91 #define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
92 #define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
94 #define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
95 #define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
97 #define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
98 #define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
99 #define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
100 #define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
102 #define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
103 #define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
104 #define CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
105 #define CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
108 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t
*surface
);
111 _CAIRO_FORMAT_DEPTH (cairo_format_t format
)
114 case CAIRO_FORMAT_A1
:
116 case CAIRO_FORMAT_A8
:
118 case CAIRO_FORMAT_RGB24
:
120 case CAIRO_FORMAT_ARGB32
:
126 static xcb_render_pictforminfo_t
*
127 _CAIRO_FORMAT_TO_XRENDER_FORMAT(xcb_connection_t
*dpy
, cairo_format_t format
)
129 xcb_pict_standard_t std_format
;
131 case CAIRO_FORMAT_A1
:
132 std_format
= XCB_PICT_STANDARD_A_1
; break;
133 case CAIRO_FORMAT_A8
:
134 std_format
= XCB_PICT_STANDARD_A_8
; break;
135 case CAIRO_FORMAT_RGB24
:
136 std_format
= XCB_PICT_STANDARD_RGB_24
; break;
137 case CAIRO_FORMAT_ARGB32
:
139 std_format
= XCB_PICT_STANDARD_ARGB_32
; break;
141 return xcb_render_util_find_standard_format (xcb_render_util_query_formats (dpy
), std_format
);
144 static cairo_content_t
145 _xcb_render_format_to_content (xcb_render_pictforminfo_t
*xrender_format
)
147 cairo_bool_t xrender_format_has_alpha
;
148 cairo_bool_t xrender_format_has_color
;
150 /* This only happens when using a non-Render server. Let's punt
151 * and say there's no alpha here. */
152 if (xrender_format
== NULL
)
153 return CAIRO_CONTENT_COLOR
;
155 xrender_format_has_alpha
= (xrender_format
->direct
.alpha_mask
!= 0);
156 xrender_format_has_color
= (xrender_format
->direct
.red_mask
!= 0 ||
157 xrender_format
->direct
.green_mask
!= 0 ||
158 xrender_format
->direct
.blue_mask
!= 0);
160 if (xrender_format_has_alpha
)
161 if (xrender_format_has_color
)
162 return CAIRO_CONTENT_COLOR_ALPHA
;
164 return CAIRO_CONTENT_ALPHA
;
166 return CAIRO_CONTENT_COLOR
;
169 static cairo_surface_t
*
170 _cairo_xcb_surface_create_similar (void *abstract_src
,
171 cairo_content_t content
,
175 cairo_xcb_surface_t
*src
= abstract_src
;
176 xcb_connection_t
*dpy
= src
->dpy
;
178 cairo_xcb_surface_t
*surface
;
179 cairo_format_t format
= _cairo_format_from_content (content
);
180 xcb_render_pictforminfo_t
*xrender_format
;
182 /* As a good first approximation, if the display doesn't have COMPOSITE,
183 * we're better off using image surfaces for all temporary operations
185 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src
)) {
186 return cairo_image_surface_create (format
, width
, height
);
189 pixmap
= xcb_generate_id (dpy
);
190 xcb_create_pixmap (dpy
, _CAIRO_FORMAT_DEPTH (format
),
191 pixmap
, src
->drawable
,
192 width
<= 0 ? 1 : width
,
193 height
<= 0 ? 1 : height
);
195 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy
, format
);
196 /* XXX: what to do if xrender_format is null? */
197 surface
= (cairo_xcb_surface_t
*)
198 cairo_xcb_surface_create_with_xrender_format (dpy
, pixmap
, src
->screen
,
201 if (surface
->base
.status
)
202 return &surface
->base
;
204 surface
->owns_pixmap
= TRUE
;
206 return &surface
->base
;
209 static cairo_status_t
210 _cairo_xcb_surface_finish (void *abstract_surface
)
212 cairo_xcb_surface_t
*surface
= abstract_surface
;
213 if (surface
->dst_picture
!= XCB_NONE
)
214 xcb_render_free_picture (surface
->dpy
, surface
->dst_picture
);
216 if (surface
->src_picture
!= XCB_NONE
)
217 xcb_render_free_picture (surface
->dpy
, surface
->src_picture
);
219 if (surface
->owns_pixmap
)
220 xcb_free_pixmap (surface
->dpy
, surface
->drawable
);
222 if (surface
->gc
!= XCB_NONE
)
223 xcb_free_gc (surface
->dpy
, surface
->gc
);
225 free (surface
->clip_rects
);
229 return CAIRO_STATUS_SUCCESS
;
233 _bits_per_pixel(xcb_connection_t
*c
, int depth
)
235 xcb_format_t
*fmt
= xcb_setup_pixmap_formats(xcb_get_setup(c
));
236 xcb_format_t
*fmtend
= fmt
+ xcb_setup_pixmap_formats_length(xcb_get_setup(c
));
238 for(; fmt
!= fmtend
; ++fmt
)
239 if(fmt
->depth
== depth
)
240 return fmt
->bits_per_pixel
;
252 _bytes_per_line(xcb_connection_t
*c
, int width
, int bpp
)
254 int bitmap_pad
= xcb_get_setup(c
)->bitmap_format_scanline_pad
;
255 return ((bpp
* width
+ bitmap_pad
- 1) & -bitmap_pad
) >> 3;
259 _CAIRO_MASK_FORMAT (cairo_format_masks_t
*masks
, cairo_format_t
*format
)
261 switch (masks
->bpp
) {
263 if (masks
->alpha_mask
== 0xff000000 &&
264 masks
->red_mask
== 0x00ff0000 &&
265 masks
->green_mask
== 0x0000ff00 &&
266 masks
->blue_mask
== 0x000000ff)
268 *format
= CAIRO_FORMAT_ARGB32
;
271 if (masks
->alpha_mask
== 0x00000000 &&
272 masks
->red_mask
== 0x00ff0000 &&
273 masks
->green_mask
== 0x0000ff00 &&
274 masks
->blue_mask
== 0x000000ff)
276 *format
= CAIRO_FORMAT_RGB24
;
281 if (masks
->alpha_mask
== 0xff)
283 *format
= CAIRO_FORMAT_A8
;
288 if (masks
->alpha_mask
== 0x1)
290 *format
= CAIRO_FORMAT_A1
;
298 static cairo_status_t
299 _get_image_surface (cairo_xcb_surface_t
*surface
,
300 cairo_rectangle_int_t
*interest_rect
,
301 cairo_image_surface_t
**image_out
,
302 cairo_rectangle_int_t
*image_rect
)
304 cairo_image_surface_t
*image
;
305 xcb_get_image_reply_t
*imagerep
;
306 int bpp
, bytes_per_line
;
307 cairo_rectangle_int_t extents
;
309 cairo_format_masks_t masks
;
310 cairo_format_t format
;
314 extents
.width
= surface
->width
;
315 extents
.height
= surface
->height
;
318 if (! _cairo_rectangle_intersect (&extents
, interest_rect
)) {
320 return CAIRO_STATUS_SUCCESS
;
325 *image_rect
= extents
;
327 /* XXX: This should try to use the XShm extension if available */
329 if (surface
->use_pixmap
== 0)
331 xcb_generic_error_t
*error
;
332 imagerep
= xcb_get_image_reply(surface
->dpy
,
333 xcb_get_image(surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
335 extents
.x
, extents
.y
,
336 extents
.width
, extents
.height
,
339 /* If we get an error, the surface must have been a window,
340 * so retry with the safe code path.
343 surface
->use_pixmap
= CAIRO_ASSUME_PIXMAP
;
347 surface
->use_pixmap
--;
353 /* xcb_get_image_t from a window is dangerous because it can
354 * produce errors if the window is unmapped or partially
355 * outside the screen. We could check for errors and
356 * retry, but to keep things simple, we just create a
360 pixmap
= xcb_generate_id (surface
->dpy
);
361 xcb_create_pixmap (surface
->dpy
,
365 extents
.width
, extents
.height
);
366 _cairo_xcb_surface_ensure_gc (surface
);
368 xcb_copy_area (surface
->dpy
, surface
->drawable
, pixmap
, surface
->gc
,
369 extents
.x
, extents
.y
, 0, 0, extents
.width
, extents
.height
);
371 imagerep
= xcb_get_image_reply(surface
->dpy
,
372 xcb_get_image(surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
374 extents
.x
, extents
.y
,
375 extents
.width
, extents
.height
,
377 xcb_free_pixmap (surface
->dpy
, pixmap
);
381 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
383 bpp
= _bits_per_pixel(surface
->dpy
, imagerep
->depth
);
384 bytes_per_line
= _bytes_per_line(surface
->dpy
, surface
->width
, bpp
);
386 data
= _cairo_malloc_ab (surface
->height
, bytes_per_line
);
389 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
392 memcpy (data
, xcb_get_image_data (imagerep
), bytes_per_line
* surface
->height
);
396 * Compute the pixel format masks from either an xcb_visualtype_t or
397 * a xcb_render_pctforminfo_t, failing we assume the drawable is an
398 * alpha-only pixmap as it could only have been created that way
399 * through the cairo_xlib_surface_create_for_bitmap function.
401 if (surface
->visual
) {
403 masks
.alpha_mask
= 0;
404 masks
.red_mask
= surface
->visual
->red_mask
;
405 masks
.green_mask
= surface
->visual
->green_mask
;
406 masks
.blue_mask
= surface
->visual
->blue_mask
;
407 } else if (surface
->xrender_format
.id
!= XCB_NONE
) {
409 masks
.red_mask
= (unsigned long)surface
->xrender_format
.direct
.red_mask
<< surface
->xrender_format
.direct
.red_shift
;
410 masks
.green_mask
= (unsigned long)surface
->xrender_format
.direct
.green_mask
<< surface
->xrender_format
.direct
.green_shift
;
411 masks
.blue_mask
= (unsigned long)surface
->xrender_format
.direct
.blue_mask
<< surface
->xrender_format
.direct
.blue_shift
;
412 masks
.alpha_mask
= (unsigned long)surface
->xrender_format
.direct
.alpha_mask
<< surface
->xrender_format
.direct
.alpha_shift
;
416 masks
.green_mask
= 0;
418 if (surface
->depth
< 32)
419 masks
.alpha_mask
= (1 << surface
->depth
) - 1;
421 masks
.alpha_mask
= 0xffffffff;
425 * Prefer to use a standard pixman format instead of the
426 * general masks case.
428 if (_CAIRO_MASK_FORMAT (&masks
, &format
)) {
429 image
= (cairo_image_surface_t
*)
430 cairo_image_surface_create_for_data (data
,
435 if (image
->base
.status
)
439 * XXX This can't work. We must convert the data to one of the
440 * supported pixman formats. Pixman needs another function
441 * which takes data in an arbitrary format and converts it
442 * to something supported by that library.
444 image
= (cairo_image_surface_t
*)
445 cairo_image_surface_create_with_masks (data
,
450 if (image
->base
.status
)
454 /* Let the surface take ownership of the data */
455 _cairo_image_surface_assume_ownership_of_data (image
);
458 return CAIRO_STATUS_SUCCESS
;
462 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
466 _cairo_xcb_surface_ensure_src_picture (cairo_xcb_surface_t
*surface
)
468 if (!surface
->src_picture
) {
469 surface
->src_picture
= xcb_generate_id(surface
->dpy
);
470 xcb_render_create_picture (surface
->dpy
,
471 surface
->src_picture
,
473 surface
->xrender_format
.id
,
479 _cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t
*surface
)
481 if (surface
->have_clip_rects
)
482 xcb_render_set_picture_clip_rectangles (surface
->dpy
, surface
->dst_picture
,
484 surface
->num_clip_rects
,
485 surface
->clip_rects
);
489 _cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t
*surface
)
491 if (surface
->have_clip_rects
)
492 xcb_set_clip_rectangles(surface
->dpy
, XCB_CLIP_ORDERING_YX_SORTED
, surface
->gc
,
494 surface
->num_clip_rects
,
495 surface
->clip_rects
);
499 _cairo_xcb_surface_ensure_dst_picture (cairo_xcb_surface_t
*surface
)
501 if (!surface
->dst_picture
) {
502 surface
->dst_picture
= xcb_generate_id(surface
->dpy
);
503 xcb_render_create_picture (surface
->dpy
,
504 surface
->dst_picture
,
506 surface
->xrender_format
.id
,
508 _cairo_xcb_surface_set_picture_clip_rects (surface
);
514 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t
*surface
)
519 surface
->gc
= xcb_generate_id(surface
->dpy
);
520 xcb_create_gc (surface
->dpy
, surface
->gc
, surface
->drawable
, 0, 0);
521 _cairo_xcb_surface_set_gc_clip_rects(surface
);
524 static cairo_status_t
525 _draw_image_surface (cairo_xcb_surface_t
*surface
,
526 cairo_image_surface_t
*image
,
536 uint8_t *data
, left_pad
=0;
538 /* equivalent of XPutImage(..., src_x,src_y, dst_x,dst_y, width,height); */
539 /* XXX: assumes image and surface formats and depths are the same */
540 /* XXX: assumes depth is a multiple of 8 (not bitmap) */
542 /* fit src_{x,y,width,height} within image->{0,0,width,height} */
551 if (width
+ src_x
> image
->width
)
552 width
= image
->width
- src_x
;
553 if (height
+ src_y
> image
->height
)
554 height
= image
->height
- src_y
;
555 if (width
<= 0 || height
<= 0)
556 return CAIRO_STATUS_SUCCESS
;
558 bpp
= _bits_per_pixel(surface
->dpy
, image
->depth
);
559 /* XXX: could use bpl = image->stride? */
560 bpl
= _bytes_per_line(surface
->dpy
, image
->width
, bpp
);
562 if (src_x
== 0 && width
== image
->width
) {
563 /* can work in-place */
564 data_len
= height
* bpl
;
565 data
= image
->data
+ src_y
* bpl
;
567 /* must copy {src_x,src_y,width,height} into new data */
569 uint8_t *data_line
, *image_line
;
570 int data_bpl
= _bytes_per_line(surface
->dpy
, width
, bpp
);
571 data_len
= height
* data_bpl
;
572 data_line
= data
= malloc(data_len
);
574 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
576 image_line
= image
->data
+ src_y
* bpl
+ (src_x
* bpp
/ 8);
577 while (line
++ < height
) {
578 memcpy(data_line
, image_line
, data_bpl
);
579 data_line
+= data_bpl
;
583 _cairo_xcb_surface_ensure_gc (surface
);
584 xcb_put_image (surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
585 surface
->drawable
, surface
->gc
,
588 left_pad
, image
->depth
,
591 if (data
< image
->data
|| data
>= image
->data
+ image
->height
* bpl
)
594 return CAIRO_STATUS_SUCCESS
;
597 static cairo_status_t
598 _cairo_xcb_surface_acquire_source_image (void *abstract_surface
,
599 cairo_image_surface_t
**image_out
,
602 cairo_xcb_surface_t
*surface
= abstract_surface
;
603 cairo_image_surface_t
*image
;
604 cairo_status_t status
;
606 status
= _get_image_surface (surface
, NULL
, &image
, NULL
);
613 return CAIRO_STATUS_SUCCESS
;
616 static cairo_surface_t
*
617 _cairo_xcb_surface_snapshot (void *abstract_surface
)
619 cairo_xcb_surface_t
*surface
= abstract_surface
;
620 cairo_image_surface_t
*image
;
621 cairo_status_t status
;
623 status
= _get_image_surface (surface
, NULL
, &image
, NULL
);
624 if (unlikely (status
))
625 return _cairo_surface_create_in_error (status
);
631 _cairo_xcb_surface_release_source_image (void *abstract_surface
,
632 cairo_image_surface_t
*image
,
635 cairo_surface_destroy (&image
->base
);
638 static cairo_status_t
639 _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
,
640 cairo_rectangle_int_t
*interest_rect
,
641 cairo_image_surface_t
**image_out
,
642 cairo_rectangle_int_t
*image_rect_out
,
645 cairo_xcb_surface_t
*surface
= abstract_surface
;
646 cairo_image_surface_t
*image
;
647 cairo_status_t status
;
649 status
= _get_image_surface (surface
, interest_rect
, &image
, image_rect_out
);
656 return CAIRO_STATUS_SUCCESS
;
660 _cairo_xcb_surface_release_dest_image (void *abstract_surface
,
661 cairo_rectangle_int_t
*interest_rect
,
662 cairo_image_surface_t
*image
,
663 cairo_rectangle_int_t
*image_rect
,
666 cairo_xcb_surface_t
*surface
= abstract_surface
;
669 _draw_image_surface (surface
, image
, 0, 0, image
->width
, image
->height
,
670 image_rect
->x
, image_rect
->y
);
672 cairo_surface_destroy (&image
->base
);
676 * Return whether two xcb surfaces share the same
677 * screen. Both core and Render drawing require this
678 * when using multiple drawables in an operation.
681 _cairo_xcb_surface_same_screen (cairo_xcb_surface_t
*dst
,
682 cairo_xcb_surface_t
*src
)
684 return dst
->dpy
== src
->dpy
&& dst
->screen
== src
->screen
;
687 static cairo_status_t
688 _cairo_xcb_surface_clone_similar (void *abstract_surface
,
689 cairo_surface_t
*src
,
690 cairo_content_t content
,
697 cairo_surface_t
**clone_out
)
699 cairo_xcb_surface_t
*surface
= abstract_surface
;
700 cairo_xcb_surface_t
*clone
;
702 if (src
->backend
== surface
->base
.backend
) {
703 cairo_xcb_surface_t
*xcb_src
= (cairo_xcb_surface_t
*)src
;
705 if (_cairo_xcb_surface_same_screen(surface
, xcb_src
)) {
708 *clone_out
= cairo_surface_reference (src
);
710 return CAIRO_STATUS_SUCCESS
;
712 } else if (_cairo_surface_is_image (src
)) {
713 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*)src
;
714 cairo_content_t content
= _cairo_content_from_format (image_src
->format
);
715 cairo_status_t status
;
717 if (surface
->base
.status
)
718 return surface
->base
.status
;
720 clone
= (cairo_xcb_surface_t
*)
721 _cairo_xcb_surface_create_similar (surface
, content
, width
, height
);
723 return CAIRO_INT_STATUS_UNSUPPORTED
;
724 if (clone
->base
.status
)
725 return clone
->base
.status
;
727 status
= _draw_image_surface (clone
, image_src
,
732 cairo_surface_destroy (&clone
->base
);
736 *clone_offset_x
= src_x
;
737 *clone_offset_y
= src_y
;
738 *clone_out
= &clone
->base
;
740 return CAIRO_STATUS_SUCCESS
;
743 return CAIRO_INT_STATUS_UNSUPPORTED
;
746 static cairo_status_t
747 _cairo_xcb_surface_set_matrix (cairo_xcb_surface_t
*surface
,
748 cairo_matrix_t
*matrix
)
750 xcb_render_transform_t xtransform
;
752 if (!surface
->src_picture
)
753 return CAIRO_STATUS_SUCCESS
;
755 xtransform
.matrix11
= _cairo_fixed_16_16_from_double (matrix
->xx
);
756 xtransform
.matrix12
= _cairo_fixed_16_16_from_double (matrix
->xy
);
757 xtransform
.matrix13
= _cairo_fixed_16_16_from_double (matrix
->x0
);
759 xtransform
.matrix21
= _cairo_fixed_16_16_from_double (matrix
->yx
);
760 xtransform
.matrix22
= _cairo_fixed_16_16_from_double (matrix
->yy
);
761 xtransform
.matrix23
= _cairo_fixed_16_16_from_double (matrix
->y0
);
763 xtransform
.matrix31
= 0;
764 xtransform
.matrix32
= 0;
765 xtransform
.matrix33
= 1 << 16;
767 if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface
))
769 static const xcb_render_transform_t identity
= {
770 1 << 16, 0x00000, 0x00000,
771 0x00000, 1 << 16, 0x00000,
772 0x00000, 0x00000, 1 << 16
775 if (memcmp (&xtransform
, &identity
, sizeof (xcb_render_transform_t
)) == 0)
776 return CAIRO_STATUS_SUCCESS
;
778 return CAIRO_INT_STATUS_UNSUPPORTED
;
781 xcb_render_set_picture_transform (surface
->dpy
, surface
->src_picture
, xtransform
);
783 return CAIRO_STATUS_SUCCESS
;
786 static cairo_status_t
787 _cairo_xcb_surface_set_filter (cairo_xcb_surface_t
*surface
,
788 cairo_filter_t filter
)
790 const char *render_filter
;
792 if (!surface
->src_picture
)
793 return CAIRO_STATUS_SUCCESS
;
795 if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface
))
797 if (filter
== CAIRO_FILTER_FAST
|| filter
== CAIRO_FILTER_NEAREST
)
798 return CAIRO_STATUS_SUCCESS
;
800 return CAIRO_INT_STATUS_UNSUPPORTED
;
804 case CAIRO_FILTER_FAST
:
805 render_filter
= "fast";
807 case CAIRO_FILTER_GOOD
:
808 render_filter
= "good";
810 case CAIRO_FILTER_BEST
:
811 render_filter
= "best";
813 case CAIRO_FILTER_NEAREST
:
814 render_filter
= "nearest";
816 case CAIRO_FILTER_BILINEAR
:
817 render_filter
= "bilinear";
819 case CAIRO_FILTER_GAUSSIAN
:
821 render_filter
= "best";
825 xcb_render_set_picture_filter(surface
->dpy
, surface
->src_picture
,
826 strlen(render_filter
), render_filter
, 0, NULL
);
828 return CAIRO_STATUS_SUCCESS
;
831 static cairo_status_t
832 _cairo_xcb_surface_set_repeat (cairo_xcb_surface_t
*surface
, int repeat
)
834 uint32_t mask
= XCB_RENDER_CP_REPEAT
;
835 uint32_t pa
[] = { repeat
};
837 if (!surface
->src_picture
)
838 return CAIRO_STATUS_SUCCESS
;
840 xcb_render_change_picture (surface
->dpy
, surface
->src_picture
, mask
, pa
);
842 return CAIRO_STATUS_SUCCESS
;
845 static cairo_int_status_t
846 _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t
*surface
,
847 cairo_surface_attributes_t
*attributes
)
849 cairo_int_status_t status
;
851 _cairo_xcb_surface_ensure_src_picture (surface
);
853 status
= _cairo_xcb_surface_set_matrix (surface
, &attributes
->matrix
);
857 switch (attributes
->extend
) {
858 case CAIRO_EXTEND_NONE
:
859 _cairo_xcb_surface_set_repeat (surface
, XCB_RENDER_REPEAT_NONE
);
861 case CAIRO_EXTEND_REPEAT
:
862 _cairo_xcb_surface_set_repeat (surface
, XCB_RENDER_REPEAT_NORMAL
);
864 case CAIRO_EXTEND_REFLECT
:
865 if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface
))
866 return CAIRO_INT_STATUS_UNSUPPORTED
;
867 _cairo_xcb_surface_set_repeat (surface
, XCB_RENDER_REPEAT_REFLECT
);
869 case CAIRO_EXTEND_PAD
:
870 if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface
))
871 return CAIRO_INT_STATUS_UNSUPPORTED
;
872 _cairo_xcb_surface_set_repeat (surface
, XCB_RENDER_REPEAT_PAD
);
875 return CAIRO_INT_STATUS_UNSUPPORTED
;
878 status
= _cairo_xcb_surface_set_filter (surface
, attributes
->filter
);
882 return CAIRO_STATUS_SUCCESS
;
885 /* Checks whether we can can directly draw from src to dst with
886 * the core protocol: either with CopyArea or using src as a
890 _surfaces_compatible (cairo_xcb_surface_t
*dst
,
891 cairo_xcb_surface_t
*src
)
894 if (!_cairo_xcb_surface_same_screen (dst
, src
))
897 /* same depth (for core) */
898 if (src
->depth
!= dst
->depth
)
901 /* if Render is supported, match picture formats */
902 if (src
->xrender_format
.id
!= dst
->xrender_format
.id
)
904 else if (src
->xrender_format
.id
!= XCB_NONE
)
907 /* Without Render, match visuals instead */
908 if (src
->visual
== dst
->visual
)
915 _surface_has_alpha (cairo_xcb_surface_t
*surface
)
917 if (surface
->xrender_format
.id
!= XCB_NONE
) {
918 if (surface
->xrender_format
.type
== XCB_RENDER_PICT_TYPE_DIRECT
&&
919 surface
->xrender_format
.direct
.alpha_mask
!= 0)
925 /* In the no-render case, we never have alpha */
930 /* Returns true if the given operator and source-alpha combination
931 * requires alpha compositing to complete.
934 _operator_needs_alpha_composite (cairo_operator_t op
,
935 cairo_bool_t surface_has_alpha
)
937 if (op
== CAIRO_OPERATOR_SOURCE
||
938 (!surface_has_alpha
&&
939 (op
== CAIRO_OPERATOR_OVER
||
940 op
== CAIRO_OPERATOR_ATOP
||
941 op
== CAIRO_OPERATOR_IN
)))
947 /* There is a bug in most older X servers with compositing using a
948 * untransformed repeating source pattern when the source is in off-screen
949 * video memory, and another with repeated transformed images using a
950 * general transform matrix. When these bugs could be triggered, we need a
951 * fallback: in the common case where we have no transformation and the
952 * source and destination have the same format/visual, we can do the
953 * operation using the core protocol for the first bug, otherwise, we need
954 * a software fallback.
956 * We can also often optimize a compositing operation by calling XCopyArea
957 * for some common cases where there is no alpha compositing to be done.
958 * We figure that out here as well.
961 DO_RENDER
, /* use render */
962 DO_XCOPYAREA
, /* core protocol XCopyArea optimization/fallback */
963 DO_XTILE
, /* core protocol XSetTile optimization/fallback */
964 DO_UNSUPPORTED
/* software fallback */
965 } composite_operation_t
;
967 /* Initial check for the render bugs; we need to recheck for the
968 * offscreen-memory bug after we turn patterns into surfaces, since that
969 * may introduce a repeating pattern for gradient patterns. We don't need
970 * to check for the repeat+transform bug because gradient surfaces aren't
973 * All we do here is reject cases where we *know* are going to
974 * hit the bug and won't be able to use a core protocol fallback.
976 static composite_operation_t
977 _categorize_composite_operation (cairo_xcb_surface_t
*dst
,
979 const cairo_pattern_t
*src_pattern
,
980 cairo_bool_t have_mask
)
984 if (!dst
->buggy_repeat
)
987 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
)
989 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*)src_pattern
;
991 if (_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
992 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
994 /* This is the case where we have the bug involving
995 * untransformed repeating source patterns with off-screen
996 * video memory; reject some cases where a core protocol
997 * fallback is impossible.
1000 !(op
== CAIRO_OPERATOR_SOURCE
|| op
== CAIRO_OPERATOR_OVER
))
1001 return DO_UNSUPPORTED
;
1003 if (_cairo_surface_is_xcb (surface_pattern
->surface
)) {
1004 cairo_xcb_surface_t
*src
= (cairo_xcb_surface_t
*)surface_pattern
->surface
;
1006 if (op
== CAIRO_OPERATOR_OVER
&& _surface_has_alpha (src
))
1007 return DO_UNSUPPORTED
;
1009 /* If these are on the same screen but otherwise incompatible,
1010 * make a copy as core drawing can't cross depths and doesn't
1011 * work rightacross visuals of the same depth
1013 if (_cairo_xcb_surface_same_screen (dst
, src
) &&
1014 !_surfaces_compatible (dst
, src
))
1015 return DO_UNSUPPORTED
;
1019 /* Check for the other bug involving repeat patterns with general
1021 if (!_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
1022 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
1023 return DO_UNSUPPORTED
;
1029 /* Recheck for composite-repeat once we've turned patterns into Xlib surfaces
1030 * If we end up returning DO_UNSUPPORTED here, we're throwing away work we
1031 * did to turn gradients into a pattern, but most of the time we can handle
1032 * that case with core protocol fallback.
1034 * Also check here if we can just use XCopyArea, instead of going through
1037 static composite_operation_t
1038 _recategorize_composite_operation (cairo_xcb_surface_t
*dst
,
1039 cairo_operator_t op
,
1040 cairo_xcb_surface_t
*src
,
1041 cairo_surface_attributes_t
*src_attr
,
1042 cairo_bool_t have_mask
)
1044 cairo_bool_t is_integer_translation
=
1045 _cairo_matrix_is_integer_translation (&src_attr
->matrix
, NULL
, NULL
);
1046 cairo_bool_t needs_alpha_composite
=
1047 _operator_needs_alpha_composite (op
, _surface_has_alpha (src
));
1050 is_integer_translation
&&
1051 src_attr
->extend
== CAIRO_EXTEND_NONE
&&
1052 !needs_alpha_composite
&&
1053 _surfaces_compatible(src
, dst
))
1055 return DO_XCOPYAREA
;
1057 #if XXX_BUGGY_REPEAT
1058 if (!dst
->buggy_repeat
)
1061 if (is_integer_translation
&&
1062 src_attr
->extend
== CAIRO_EXTEND_REPEAT
&&
1063 (src
->width
!= 1 || src
->height
!= 1))
1066 !needs_alpha_composite
&&
1067 _surfaces_compatible (dst
, src
))
1072 return DO_UNSUPPORTED
;
1079 _render_operator (cairo_operator_t op
)
1082 case CAIRO_OPERATOR_CLEAR
:
1083 return XCB_RENDER_PICT_OP_CLEAR
;
1084 case CAIRO_OPERATOR_SOURCE
:
1085 return XCB_RENDER_PICT_OP_SRC
;
1086 case CAIRO_OPERATOR_DEST
:
1087 return XCB_RENDER_PICT_OP_DST
;
1088 case CAIRO_OPERATOR_OVER
:
1089 return XCB_RENDER_PICT_OP_OVER
;
1090 case CAIRO_OPERATOR_DEST_OVER
:
1091 return XCB_RENDER_PICT_OP_OVER_REVERSE
;
1092 case CAIRO_OPERATOR_IN
:
1093 return XCB_RENDER_PICT_OP_IN
;
1094 case CAIRO_OPERATOR_DEST_IN
:
1095 return XCB_RENDER_PICT_OP_IN_REVERSE
;
1096 case CAIRO_OPERATOR_OUT
:
1097 return XCB_RENDER_PICT_OP_OUT
;
1098 case CAIRO_OPERATOR_DEST_OUT
:
1099 return XCB_RENDER_PICT_OP_OUT_REVERSE
;
1100 case CAIRO_OPERATOR_ATOP
:
1101 return XCB_RENDER_PICT_OP_ATOP
;
1102 case CAIRO_OPERATOR_DEST_ATOP
:
1103 return XCB_RENDER_PICT_OP_ATOP_REVERSE
;
1104 case CAIRO_OPERATOR_XOR
:
1105 return XCB_RENDER_PICT_OP_XOR
;
1106 case CAIRO_OPERATOR_ADD
:
1107 return XCB_RENDER_PICT_OP_ADD
;
1108 case CAIRO_OPERATOR_SATURATE
:
1109 return XCB_RENDER_PICT_OP_SATURATE
;
1111 return XCB_RENDER_PICT_OP_OVER
;
1115 static cairo_int_status_t
1116 _cairo_xcb_surface_composite (cairo_operator_t op
,
1117 const cairo_pattern_t
*src_pattern
,
1118 const cairo_pattern_t
*mask_pattern
,
1127 unsigned int height
)
1129 cairo_surface_attributes_t src_attr
, mask_attr
;
1130 cairo_xcb_surface_t
*dst
= abstract_dst
;
1131 cairo_xcb_surface_t
*src
;
1132 cairo_xcb_surface_t
*mask
;
1133 cairo_int_status_t status
;
1134 composite_operation_t operation
;
1136 cairo_bool_t is_integer_translation
;
1138 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst
))
1139 return CAIRO_INT_STATUS_UNSUPPORTED
;
1141 operation
= _categorize_composite_operation (dst
, op
, src_pattern
,
1142 mask_pattern
!= NULL
);
1143 if (operation
== DO_UNSUPPORTED
)
1144 return CAIRO_INT_STATUS_UNSUPPORTED
;
1146 status
= _cairo_pattern_acquire_surfaces (src_pattern
, mask_pattern
,
1148 CAIRO_CONTENT_COLOR_ALPHA
,
1152 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
,
1153 (cairo_surface_t
**) &src
,
1154 (cairo_surface_t
**) &mask
,
1155 &src_attr
, &mask_attr
);
1159 operation
= _recategorize_composite_operation (dst
, op
, src
, &src_attr
,
1160 mask_pattern
!= NULL
);
1161 if (operation
== DO_UNSUPPORTED
) {
1162 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1166 status
= _cairo_xcb_surface_set_attributes (src
, &src_attr
);
1173 _cairo_xcb_surface_ensure_dst_picture (dst
);
1175 status
= _cairo_xcb_surface_set_attributes (mask
, &mask_attr
);
1179 xcb_render_composite (dst
->dpy
,
1180 _render_operator (op
),
1184 src_x
+ src_attr
.x_offset
,
1185 src_y
+ src_attr
.y_offset
,
1186 mask_x
+ mask_attr
.x_offset
,
1187 mask_y
+ mask_attr
.y_offset
,
1191 static xcb_render_picture_t maskpict
= { XCB_NONE
};
1193 xcb_render_composite (dst
->dpy
,
1194 _render_operator (op
),
1198 src_x
+ src_attr
.x_offset
,
1199 src_y
+ src_attr
.y_offset
,
1207 _cairo_xcb_surface_ensure_gc (dst
);
1208 xcb_copy_area (dst
->dpy
,
1212 src_x
+ src_attr
.x_offset
,
1213 src_y
+ src_attr
.y_offset
,
1219 /* This case is only used for bug fallbacks, though it is theoretically
1220 * applicable to the case where we don't have the RENDER extension as
1223 * We've checked that we have a repeating unscaled source in
1224 * _recategorize_composite_operation.
1227 _cairo_xcb_surface_ensure_gc (dst
);
1228 is_integer_translation
=
1229 _cairo_matrix_is_integer_translation (&src_attr
.matrix
, &itx
, &ity
);
1230 assert (is_integer_translation
== TRUE
);
1232 uint32_t mask
= XCB_GC_FILL_STYLE
| XCB_GC_TILE
1233 | XCB_GC_TILE_STIPPLE_ORIGIN_X
1234 | XCB_GC_TILE_STIPPLE_ORIGIN_Y
;
1235 uint32_t values
[] = {
1236 XCB_FILL_STYLE_TILED
, src
->drawable
,
1237 - (itx
+ src_attr
.x_offset
),
1238 - (ity
+ src_attr
.y_offset
)
1240 xcb_rectangle_t rect
= { dst_x
, dst_y
, width
, height
};
1242 xcb_change_gc( dst
->dpy
, dst
->gc
, mask
, values
);
1243 xcb_poly_fill_rectangle(dst
->dpy
, dst
->drawable
, dst
->gc
, 1, &rect
);
1247 case DO_UNSUPPORTED
:
1252 if (!_cairo_operator_bounded_by_source (op
))
1253 status
= _cairo_surface_composite_fixup_unbounded (&dst
->base
,
1254 &src_attr
, src
->width
, src
->height
,
1255 mask
? &mask_attr
: NULL
,
1256 mask
? mask
->width
: 0,
1257 mask
? mask
->height
: 0,
1260 dst_x
, dst_y
, width
, height
);
1264 _cairo_pattern_release_surface (mask_pattern
, &mask
->base
, &mask_attr
);
1266 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
1271 static cairo_int_status_t
1272 _cairo_xcb_surface_fill_rectangles (void *abstract_surface
,
1273 cairo_operator_t op
,
1274 const cairo_color_t
* color
,
1275 cairo_rectangle_int_t
*rects
,
1278 cairo_xcb_surface_t
*surface
= abstract_surface
;
1279 xcb_render_color_t render_color
;
1280 xcb_rectangle_t static_xrects
[16];
1281 xcb_rectangle_t
*xrects
= static_xrects
;
1284 if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface
))
1285 return CAIRO_INT_STATUS_UNSUPPORTED
;
1287 render_color
.red
= color
->red_short
;
1288 render_color
.green
= color
->green_short
;
1289 render_color
.blue
= color
->blue_short
;
1290 render_color
.alpha
= color
->alpha_short
;
1292 if (num_rects
> ARRAY_LENGTH(static_xrects
)) {
1293 xrects
= _cairo_malloc_ab (num_rects
, sizeof(xcb_rectangle_t
));
1295 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1298 for (i
= 0; i
< num_rects
; i
++) {
1299 xrects
[i
].x
= rects
[i
].x
;
1300 xrects
[i
].y
= rects
[i
].y
;
1301 xrects
[i
].width
= rects
[i
].width
;
1302 xrects
[i
].height
= rects
[i
].height
;
1305 _cairo_xcb_surface_ensure_dst_picture (surface
);
1306 xcb_render_fill_rectangles (surface
->dpy
,
1307 _render_operator (op
),
1308 surface
->dst_picture
,
1309 render_color
, num_rects
, xrects
);
1311 if (xrects
!= static_xrects
)
1314 return CAIRO_STATUS_SUCCESS
;
1317 /* Creates an A8 picture of size @width x @height, initialized with @color
1319 static xcb_render_picture_t
1320 _create_a8_picture (cairo_xcb_surface_t
*surface
,
1321 xcb_render_color_t
*color
,
1324 cairo_bool_t repeat
)
1326 uint32_t values
[] = { TRUE
};
1327 uint32_t mask
= repeat
? XCB_RENDER_CP_REPEAT
: 0;
1329 xcb_pixmap_t pixmap
= xcb_generate_id (surface
->dpy
);
1330 xcb_render_picture_t picture
= xcb_generate_id (surface
->dpy
);
1332 xcb_render_pictforminfo_t
*format
1333 = _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface
->dpy
, CAIRO_FORMAT_A8
);
1334 xcb_rectangle_t rect
= { 0, 0, width
, height
};
1336 xcb_create_pixmap (surface
->dpy
, 8, pixmap
, surface
->drawable
,
1337 width
<= 0 ? 1 : width
,
1338 height
<= 0 ? 1 : height
);
1339 xcb_render_create_picture (surface
->dpy
, picture
, pixmap
, format
->id
, mask
, values
);
1340 xcb_render_fill_rectangles (surface
->dpy
, XCB_RENDER_PICT_OP_SRC
, picture
, *color
, 1, &rect
);
1341 xcb_free_pixmap (surface
->dpy
, pixmap
);
1346 /* Creates a temporary mask for the trapezoids covering the area
1347 * [@dst_x, @dst_y, @width, @height] of the destination surface.
1349 static cairo_status_t
1350 _create_trapezoid_mask (cairo_xcb_surface_t
*dst
,
1351 cairo_trapezoid_t
*traps
,
1357 xcb_render_pictforminfo_t
*pict_format
,
1358 xcb_render_picture_t
*mask_picture_out
)
1360 xcb_render_color_t transparent
= { 0, 0, 0, 0 };
1361 xcb_render_color_t solid
= { 0xffff, 0xffff, 0xffff, 0xffff };
1362 xcb_render_picture_t mask_picture
, solid_picture
;
1363 xcb_render_trapezoid_t
*offset_traps
;
1366 /* This would be considerably simpler using XRenderAddTraps(), but since
1367 * we are only using this in the unbounded-operator case, we stick with
1368 * XRenderCompositeTrapezoids, which is available on older versions
1369 * of RENDER rather than conditionalizing. We should still hit an
1370 * optimization that avoids creating another intermediate surface on
1371 * the servers that have XRenderAddTraps().
1373 mask_picture
= _create_a8_picture (dst
, &transparent
, width
, height
, FALSE
);
1374 solid_picture
= _create_a8_picture (dst
, &solid
, width
, height
, TRUE
);
1376 offset_traps
= _cairo_malloc_ab (num_traps
, sizeof (xcb_render_trapezoid_t
));
1377 if (offset_traps
== NULL
)
1378 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1380 for (i
= 0; i
< num_traps
; i
++) {
1381 offset_traps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
) - 0x10000 * dst_y
;
1382 offset_traps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
) - 0x10000 * dst_y
;
1383 offset_traps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
) - 0x10000 * dst_x
;
1384 offset_traps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
) - 0x10000 * dst_y
;
1385 offset_traps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
) - 0x10000 * dst_x
;
1386 offset_traps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
) - 0x10000 * dst_y
;
1387 offset_traps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
) - 0x10000 * dst_x
;
1388 offset_traps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
) - 0x10000 * dst_y
;
1389 offset_traps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
) - 0x10000 * dst_x
;
1390 offset_traps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
) - 0x10000 * dst_y
;
1393 xcb_render_trapezoids (dst
->dpy
, XCB_RENDER_PICT_OP_ADD
,
1394 solid_picture
, mask_picture
,
1397 num_traps
, offset_traps
);
1399 xcb_render_free_picture (dst
->dpy
, solid_picture
);
1400 free (offset_traps
);
1402 *mask_picture_out
= mask_picture
;
1403 return CAIRO_STATUS_SUCCESS
;
1406 static cairo_int_status_t
1407 _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op
,
1408 const cairo_pattern_t
*pattern
,
1410 cairo_antialias_t antialias
,
1416 unsigned int height
,
1417 cairo_trapezoid_t
*traps
,
1420 cairo_surface_attributes_t attributes
;
1421 cairo_xcb_surface_t
*dst
= abstract_dst
;
1422 cairo_xcb_surface_t
*src
;
1423 cairo_int_status_t status
;
1424 composite_operation_t operation
;
1425 int render_reference_x
, render_reference_y
;
1426 int render_src_x
, render_src_y
;
1428 xcb_render_pictforminfo_t
*render_format
;
1430 if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst
))
1431 return CAIRO_INT_STATUS_UNSUPPORTED
;
1433 operation
= _categorize_composite_operation (dst
, op
, pattern
, TRUE
);
1434 if (operation
== DO_UNSUPPORTED
)
1435 return CAIRO_INT_STATUS_UNSUPPORTED
;
1437 status
= _cairo_pattern_acquire_surface (pattern
, &dst
->base
,
1438 CAIRO_CONTENT_COLOR_ALPHA
,
1439 src_x
, src_y
, width
, height
,
1440 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
,
1441 (cairo_surface_t
**) &src
,
1446 operation
= _recategorize_composite_operation (dst
, op
, src
, &attributes
, TRUE
);
1447 if (operation
== DO_UNSUPPORTED
) {
1448 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1452 if(antialias
== CAIRO_ANTIALIAS_NONE
)
1453 cairo_format
= CAIRO_FORMAT_A1
;
1455 cairo_format
= CAIRO_FORMAT_A8
;
1457 render_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dst
->dpy
, cairo_format
);
1458 /* XXX: what to do if render_format is null? */
1460 if (traps
[0].left
.p1
.y
< traps
[0].left
.p2
.y
) {
1461 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.x
);
1462 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.y
);
1464 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.x
);
1465 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.y
);
1468 render_src_x
= src_x
+ render_reference_x
- dst_x
;
1469 render_src_y
= src_y
+ render_reference_y
- dst_y
;
1471 _cairo_xcb_surface_ensure_dst_picture (dst
);
1472 status
= _cairo_xcb_surface_set_attributes (src
, &attributes
);
1476 if (!_cairo_operator_bounded_by_mask (op
)) {
1477 /* xcb_render_composite+trapezoids() creates a mask only large enough for the
1478 * trapezoids themselves, but if the operator is unbounded, then we need
1479 * to actually composite all the way out to the bounds, so we create
1480 * the mask and composite ourselves. There actually would
1481 * be benefit to doing this in all cases, since RENDER implementations
1482 * will frequently create a too temporary big mask, ignoring destination
1483 * bounds and clip. (xcb_render_add_traps() could be used to make creating
1484 * the mask somewhat cheaper.)
1486 xcb_render_picture_t mask_picture
= 0; /* silence compiler */
1488 status
= _create_trapezoid_mask (dst
, traps
, num_traps
,
1489 dst_x
, dst_y
, width
, height
,
1495 xcb_render_composite (dst
->dpy
,
1496 _render_operator (op
),
1500 src_x
+ attributes
.x_offset
,
1501 src_y
+ attributes
.y_offset
,
1506 xcb_render_free_picture (dst
->dpy
, mask_picture
);
1508 status
= _cairo_surface_composite_shape_fixup_unbounded (&dst
->base
,
1509 &attributes
, src
->width
, src
->height
,
1513 dst_x
, dst_y
, width
, height
);
1516 xcb_render_trapezoid_t xtraps_stack
[16];
1517 xcb_render_trapezoid_t
*xtraps
= xtraps_stack
;
1520 if (num_traps
> ARRAY_LENGTH(xtraps_stack
)) {
1521 xtraps
= _cairo_malloc_ab (num_traps
, sizeof(xcb_render_trapezoid_t
));
1522 if (xtraps
== NULL
) {
1523 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1528 for (i
= 0; i
< num_traps
; i
++) {
1529 xtraps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
);
1530 xtraps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
);
1531 xtraps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
);
1532 xtraps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
);
1533 xtraps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
);
1534 xtraps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
);
1535 xtraps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
);
1536 xtraps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
);
1537 xtraps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
);
1538 xtraps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
);
1541 xcb_render_trapezoids (dst
->dpy
,
1542 _render_operator (op
),
1543 src
->src_picture
, dst
->dst_picture
,
1545 render_src_x
+ attributes
.x_offset
,
1546 render_src_y
+ attributes
.y_offset
,
1549 if (xtraps
!= xtraps_stack
)
1554 _cairo_pattern_release_surface (pattern
, &src
->base
, &attributes
);
1559 static cairo_int_status_t
1560 _cairo_xcb_surface_set_clip_region (void *abstract_surface
,
1561 cairo_region_t
*region
)
1563 cairo_xcb_surface_t
*surface
= abstract_surface
;
1565 if (surface
->clip_rects
) {
1566 free (surface
->clip_rects
);
1567 surface
->clip_rects
= NULL
;
1570 surface
->have_clip_rects
= FALSE
;
1571 surface
->num_clip_rects
= 0;
1573 if (region
== NULL
) {
1574 uint32_t none
[] = { XCB_NONE
};
1576 xcb_change_gc (surface
->dpy
, surface
->gc
, XCB_GC_CLIP_MASK
, none
);
1578 if (surface
->xrender_format
.id
!= XCB_NONE
&& surface
->dst_picture
)
1579 xcb_render_change_picture (surface
->dpy
, surface
->dst_picture
,
1580 XCB_RENDER_CP_CLIP_MASK
, none
);
1582 xcb_rectangle_t
*rects
= NULL
;
1585 n_rects
= cairo_region_num_rectangles (region
);
1588 rects
= _cairo_malloc_ab (n_rects
, sizeof(xcb_rectangle_t
));
1590 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1595 for (i
= 0; i
< n_rects
; i
++) {
1596 cairo_rectangle_int_t rect
;
1598 cairo_region_get_rectangle (region
, i
, &rect
);
1600 rects
[i
].x
= rect
.x
;
1601 rects
[i
].y
= rect
.y
;
1602 rects
[i
].width
= rect
.width
;
1603 rects
[i
].height
= rect
.height
;
1606 surface
->have_clip_rects
= TRUE
;
1607 surface
->clip_rects
= rects
;
1608 surface
->num_clip_rects
= n_rects
;
1611 _cairo_xcb_surface_set_gc_clip_rects (surface
);
1613 if (surface
->dst_picture
)
1614 _cairo_xcb_surface_set_picture_clip_rects (surface
);
1617 return CAIRO_STATUS_SUCCESS
;
1620 static cairo_int_status_t
1621 _cairo_xcb_surface_get_extents (void *abstract_surface
,
1622 cairo_rectangle_int_t
*rectangle
)
1624 cairo_xcb_surface_t
*surface
= abstract_surface
;
1629 rectangle
->width
= surface
->width
;
1630 rectangle
->height
= surface
->height
;
1632 return CAIRO_STATUS_SUCCESS
;
1635 /* XXX: _cairo_xcb_surface_get_font_options */
1638 _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
);
1641 _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
1642 cairo_scaled_font_t
*scaled_font
);
1644 static cairo_int_status_t
1645 _cairo_xcb_surface_show_glyphs (void *abstract_dst
,
1646 cairo_operator_t op
,
1647 const cairo_pattern_t
*src_pattern
,
1648 cairo_glyph_t
*glyphs
,
1650 cairo_scaled_font_t
*scaled_font
,
1651 int *remaining_glyphs
,
1652 cairo_rectangle_int_t
*extents
);
1655 _cairo_xcb_surface_is_similar (void *surface_a
,
1657 cairo_content_t content
)
1659 cairo_xcb_surface_t
*a
= surface_a
;
1660 cairo_xcb_surface_t
*b
= surface_b
;
1661 xcb_render_pictforminfo_t
*xrender_format
;
1663 /* XXX: disable caching by the solid pattern cache until we implement
1664 * display notification to avoid issuing xcb calls from the wrong thread
1665 * or accessing the surface after the Display has been closed.
1669 if (! _cairo_xcb_surface_same_screen (a
, b
))
1672 /* now check that the target is a similar format */
1673 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (b
->dpy
,
1674 _cairo_format_from_content (content
));
1676 return a
->xrender_format
.id
== xrender_format
->id
;
1679 static cairo_status_t
1680 _cairo_xcb_surface_reset (void *abstract_surface
)
1682 cairo_xcb_surface_t
*surface
= abstract_surface
;
1683 cairo_status_t status
;
1685 status
= _cairo_xcb_surface_set_clip_region (surface
, NULL
);
1689 return CAIRO_STATUS_SUCCESS
;
1693 /* XXX: move this to the bottom of the file, XCB and Xlib */
1695 static const cairo_surface_backend_t cairo_xcb_surface_backend
= {
1696 CAIRO_SURFACE_TYPE_XCB
,
1697 _cairo_xcb_surface_create_similar
,
1698 _cairo_xcb_surface_finish
,
1699 _cairo_xcb_surface_acquire_source_image
,
1700 _cairo_xcb_surface_release_source_image
,
1701 _cairo_xcb_surface_acquire_dest_image
,
1702 _cairo_xcb_surface_release_dest_image
,
1703 _cairo_xcb_surface_clone_similar
,
1704 _cairo_xcb_surface_composite
,
1705 _cairo_xcb_surface_fill_rectangles
,
1706 _cairo_xcb_surface_composite_trapezoids
,
1707 NULL
, /* create_span_renderer */
1708 NULL
, /* check_span_renderer */
1709 NULL
, /* copy_page */
1710 NULL
, /* show_page */
1711 _cairo_xcb_surface_set_clip_region
,
1712 NULL
, /* intersect_clip_path */
1713 _cairo_xcb_surface_get_extents
,
1714 NULL
, /* old_show_glyphs */
1715 NULL
, /* get_font_options */
1717 NULL
, /* mark_dirty_rectangle */
1718 _cairo_xcb_surface_scaled_font_fini
,
1719 _cairo_xcb_surface_scaled_glyph_fini
,
1725 _cairo_xcb_surface_show_glyphs
,
1727 _cairo_xcb_surface_snapshot
,
1729 _cairo_xcb_surface_is_similar
,
1731 _cairo_xcb_surface_reset
1735 * _cairo_surface_is_xcb:
1736 * @surface: a #cairo_surface_t
1738 * Checks if a surface is a #cairo_xcb_surface_t
1740 * Return value: True if the surface is an xcb surface
1743 _cairo_surface_is_xcb (cairo_surface_t
*surface
)
1745 return surface
->backend
== &cairo_xcb_surface_backend
;
1748 static cairo_surface_t
*
1749 _cairo_xcb_surface_create_internal (xcb_connection_t
*dpy
,
1750 xcb_drawable_t drawable
,
1751 xcb_screen_t
*screen
,
1752 xcb_visualtype_t
*visual
,
1753 xcb_render_pictforminfo_t
*xrender_format
,
1758 cairo_xcb_surface_t
*surface
;
1759 const xcb_query_extension_reply_t
*er
;
1760 const xcb_render_query_version_reply_t
*r
= NULL
;
1762 surface
= malloc (sizeof (cairo_xcb_surface_t
));
1763 if (surface
== NULL
)
1764 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1766 if (xrender_format
) {
1767 depth
= xrender_format
->depth
;
1768 } else if (visual
) {
1769 xcb_depth_iterator_t depths
;
1770 xcb_visualtype_iterator_t visuals
;
1772 /* This is ugly, but we have to walk over all visuals
1773 * for the screen to find the depth.
1775 depths
= xcb_screen_allowed_depths_iterator(screen
);
1776 for(; depths
.rem
; xcb_depth_next(&depths
))
1778 visuals
= xcb_depth_visuals_iterator(depths
.data
);
1779 for(; visuals
.rem
; xcb_visualtype_next(&visuals
))
1781 if(visuals
.data
->visual_id
== visual
->visual_id
)
1783 depth
= depths
.data
->depth
;
1792 er
= xcb_get_extension_data(dpy
, &xcb_render_id
);
1793 if(er
&& er
->present
) {
1794 r
= xcb_render_util_query_version(dpy
);
1797 surface
->render_major
= r
->major_version
;
1798 surface
->render_minor
= r
->minor_version
;
1800 surface
->render_major
= -1;
1801 surface
->render_minor
= -1;
1804 if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface
)) {
1805 if (!xrender_format
) {
1807 const xcb_render_query_pict_formats_reply_t
*formats
;
1808 xcb_render_pictvisual_t
*pict_visual
;
1809 formats
= xcb_render_util_query_formats (dpy
);
1810 pict_visual
= xcb_render_util_find_visual_format (formats
, visual
->visual_id
);
1812 xcb_render_pictforminfo_t
template;
1813 template.id
= pict_visual
->format
;
1814 xrender_format
= xcb_render_util_find_format (formats
, XCB_PICT_FORMAT_ID
, &template, 0);
1816 } else if (depth
== 1) {
1817 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy
, CAIRO_FORMAT_A1
);
1821 xrender_format
= NULL
;
1824 _cairo_surface_init (&surface
->base
, &cairo_xcb_surface_backend
,
1825 _xcb_render_format_to_content (xrender_format
));
1829 surface
->gc
= XCB_NONE
;
1830 surface
->drawable
= drawable
;
1831 surface
->screen
= screen
;
1832 surface
->owns_pixmap
= FALSE
;
1833 surface
->use_pixmap
= 0;
1834 surface
->width
= width
;
1835 surface
->height
= height
;
1837 /* XXX: set buggy_repeat based on ServerVendor and VendorRelease */
1839 surface
->dst_picture
= XCB_NONE
;
1840 surface
->src_picture
= XCB_NONE
;
1842 surface
->visual
= visual
;
1843 surface
->xrender_format
.id
= XCB_NONE
;
1844 if (xrender_format
) surface
->xrender_format
= *xrender_format
;
1845 surface
->depth
= depth
;
1847 surface
->have_clip_rects
= FALSE
;
1848 surface
->clip_rects
= NULL
;
1849 surface
->num_clip_rects
= 0;
1851 return (cairo_surface_t
*) surface
;
1854 static xcb_screen_t
*
1855 _cairo_xcb_screen_from_visual (xcb_connection_t
*c
, xcb_visualtype_t
*visual
)
1857 xcb_depth_iterator_t d
;
1858 xcb_screen_iterator_t s
= xcb_setup_roots_iterator(xcb_get_setup(c
));
1859 for (; s
.rem
; xcb_screen_next(&s
))
1861 if (s
.data
->root_visual
== visual
->visual_id
)
1864 d
= xcb_screen_allowed_depths_iterator(s
.data
);
1865 for (; d
.rem
; xcb_depth_next(&d
))
1867 xcb_visualtype_iterator_t v
= xcb_depth_visuals_iterator(d
.data
);
1868 for (; v
.rem
; xcb_visualtype_next(&v
))
1870 if (v
.data
->visual_id
== visual
->visual_id
)
1879 * cairo_xcb_surface_create:
1880 * @c: an XCB connection
1881 * @drawable: an XCB drawable
1882 * @visual: the visual to use for drawing to @drawable. The depth
1883 * of the visual must match the depth of the drawable.
1884 * Currently, only TrueColor visuals are fully supported.
1885 * @width: the current width of @drawable.
1886 * @height: the current height of @drawable.
1888 * Creates an XCB surface that draws to the given drawable.
1889 * The way that colors are represented in the drawable is specified
1890 * by the provided visual.
1892 * Note: If @drawable is a window, then the function
1893 * cairo_xcb_surface_set_size() must be called whenever the size of the
1896 * Return value: the newly created surface
1899 cairo_xcb_surface_create (xcb_connection_t
*c
,
1900 xcb_drawable_t drawable
,
1901 xcb_visualtype_t
*visual
,
1905 xcb_screen_t
*screen
= _cairo_xcb_screen_from_visual (c
, visual
);
1908 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
1910 return _cairo_xcb_surface_create_internal (c
, drawable
, screen
,
1916 * cairo_xcb_surface_create_for_bitmap:
1917 * @c: an XCB connection
1918 * @bitmap: an XCB Pixmap (a depth-1 pixmap)
1919 * @screen: an XCB Screen
1920 * @width: the current width of @bitmap
1921 * @height: the current height of @bitmap
1923 * Creates an XCB surface that draws to the given bitmap.
1924 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1926 * Return value: the newly created surface
1929 cairo_xcb_surface_create_for_bitmap (xcb_connection_t
*c
,
1930 xcb_pixmap_t bitmap
,
1931 xcb_screen_t
*screen
,
1935 return _cairo_xcb_surface_create_internal (c
, bitmap
, screen
,
1941 * cairo_xcb_surface_create_with_xrender_format:
1942 * @c: an XCB connection
1943 * @drawable: an XCB drawable
1944 * @screen: the XCB screen associated with @drawable
1945 * @format: the picture format to use for drawing to @drawable. The
1946 * depth of @format mush match the depth of the drawable.
1947 * @width: the current width of @drawable
1948 * @height: the current height of @drawable
1950 * Creates an XCB surface that draws to the given drawable.
1951 * The way that colors are represented in the drawable is specified
1952 * by the provided picture format.
1954 * Note: If @drawable is a Window, then the function
1955 * cairo_xcb_surface_set_size() must be called whenever the size of the
1958 * Return value: the newly created surface.
1961 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t
*c
,
1962 xcb_drawable_t drawable
,
1963 xcb_screen_t
*screen
,
1964 xcb_render_pictforminfo_t
*format
,
1968 return _cairo_xcb_surface_create_internal (c
, drawable
, screen
,
1972 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format
);
1975 * cairo_xcb_surface_set_size:
1976 * @surface: a #cairo_surface_t for the XCB backend
1977 * @width: the new width of the surface
1978 * @height: the new height of the surface
1980 * Informs cairo of the new size of the XCB drawable underlying the
1981 * surface. For a surface created for a window (rather than a pixmap),
1982 * this function must be called each time the size of the window
1983 * changes. (For a subwindow, you are normally resizing the window
1984 * yourself, but for a toplevel window, it is necessary to listen for
1985 * ConfigureNotify events.)
1987 * A pixmap can never change size, so it is never necessary to call
1988 * this function on a surface created for a pixmap.
1991 cairo_xcb_surface_set_size (cairo_surface_t
*abstract_surface
,
1995 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) abstract_surface
;
1996 cairo_status_t status_ignored
;
1998 if (! _cairo_surface_is_xcb (abstract_surface
)) {
1999 status_ignored
= _cairo_surface_set_error (abstract_surface
,
2000 CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
2004 surface
->width
= width
;
2005 surface
->height
= height
;
2009 * Glyph rendering support
2012 typedef struct _cairo_xcb_surface_font_private
{
2013 xcb_connection_t
*dpy
;
2014 xcb_render_glyphset_t glyphset
;
2015 cairo_format_t format
;
2016 xcb_render_pictforminfo_t
*xrender_format
;
2017 } cairo_xcb_surface_font_private_t
;
2019 static cairo_status_t
2020 _cairo_xcb_surface_font_init (xcb_connection_t
*dpy
,
2021 cairo_scaled_font_t
*scaled_font
,
2022 cairo_format_t format
)
2024 cairo_xcb_surface_font_private_t
*font_private
;
2026 font_private
= malloc (sizeof (cairo_xcb_surface_font_private_t
));
2028 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2030 font_private
->dpy
= dpy
;
2031 font_private
->format
= format
;
2032 font_private
->xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy
, format
);
2033 font_private
->glyphset
= xcb_generate_id(dpy
);
2034 xcb_render_create_glyph_set (dpy
, font_private
->glyphset
, font_private
->xrender_format
->id
);
2036 scaled_font
->surface_private
= font_private
;
2037 scaled_font
->surface_backend
= &cairo_xcb_surface_backend
;
2038 return CAIRO_STATUS_SUCCESS
;
2042 _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
2044 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2047 xcb_render_free_glyph_set (font_private
->dpy
, font_private
->glyphset
);
2048 free (font_private
);
2053 _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
2054 cairo_scaled_font_t
*scaled_font
)
2056 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2058 if (font_private
!= NULL
&& scaled_glyph
->surface_private
!= NULL
) {
2059 xcb_render_glyph_t glyph_index
= _cairo_scaled_glyph_index(scaled_glyph
);
2060 xcb_render_free_glyphs (font_private
->dpy
,
2061 font_private
->glyphset
,
2067 _native_byte_order_lsb (void)
2071 return *((char *) &x
) == 1;
2074 static cairo_status_t
2075 _cairo_xcb_surface_add_glyph (xcb_connection_t
*dpy
,
2076 cairo_scaled_font_t
*scaled_font
,
2077 cairo_scaled_glyph_t
*scaled_glyph
)
2079 xcb_render_glyphinfo_t glyph_info
;
2080 xcb_render_glyph_t glyph_index
;
2081 unsigned char *data
;
2082 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
2083 cairo_xcb_surface_font_private_t
*font_private
;
2084 cairo_image_surface_t
*glyph_surface
= scaled_glyph
->surface
;
2086 if (scaled_font
->surface_private
== NULL
) {
2087 status
= _cairo_xcb_surface_font_init (dpy
, scaled_font
,
2088 glyph_surface
->format
);
2092 font_private
= scaled_font
->surface_private
;
2094 /* If the glyph format does not match the font format, then we
2095 * create a temporary surface for the glyph image with the font's
2098 if (glyph_surface
->format
!= font_private
->format
) {
2100 cairo_surface_t
*tmp_surface
;
2101 double x_offset
, y_offset
;
2103 tmp_surface
= cairo_image_surface_create (font_private
->format
,
2104 glyph_surface
->width
,
2105 glyph_surface
->height
);
2106 cr
= cairo_create (tmp_surface
);
2107 cairo_surface_get_device_offset (&glyph_surface
->base
, &x_offset
, &y_offset
);
2108 cairo_set_source_surface (cr
, &glyph_surface
->base
, x_offset
, y_offset
);
2109 cairo_set_operator (cr
, CAIRO_OPERATOR_SOURCE
);
2112 status
= cairo_status (cr
);
2116 tmp_surface
->device_transform
= glyph_surface
->base
.device_transform
;
2117 tmp_surface
->device_transform_inverse
= glyph_surface
->base
.device_transform_inverse
;
2119 glyph_surface
= (cairo_image_surface_t
*) tmp_surface
;
2125 /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
2126 glyph_info
.x
= _cairo_lround (glyph_surface
->base
.device_transform
.x0
);
2127 glyph_info
.y
= _cairo_lround (glyph_surface
->base
.device_transform
.y0
);
2128 glyph_info
.width
= glyph_surface
->width
;
2129 glyph_info
.height
= glyph_surface
->height
;
2130 glyph_info
.x_off
= 0;
2131 glyph_info
.y_off
= 0;
2133 data
= glyph_surface
->data
;
2135 /* flip formats around */
2136 switch (scaled_glyph
->surface
->format
) {
2137 case CAIRO_FORMAT_A1
:
2138 /* local bitmaps are always stored with bit == byte */
2139 if (_native_byte_order_lsb() != (xcb_get_setup(dpy
)->bitmap_format_bit_order
== XCB_IMAGE_ORDER_LSB_FIRST
)) {
2140 int c
= glyph_surface
->stride
* glyph_surface
->height
;
2142 unsigned char *new, *n
;
2146 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2154 b
= ((b
<< 1) & 0xaa) | ((b
>> 1) & 0x55);
2155 b
= ((b
<< 2) & 0xcc) | ((b
>> 2) & 0x33);
2156 b
= ((b
<< 4) & 0xf0) | ((b
>> 4) & 0x0f);
2162 case CAIRO_FORMAT_A8
:
2164 case CAIRO_FORMAT_ARGB32
:
2165 if (_native_byte_order_lsb() != (xcb_get_setup(dpy
)->image_byte_order
== XCB_IMAGE_ORDER_LSB_FIRST
)) {
2166 unsigned int c
= glyph_surface
->stride
* glyph_surface
->height
;
2168 unsigned char *new, *n
;
2172 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2190 case CAIRO_FORMAT_RGB24
:
2195 /* XXX assume X server wants pixman padding. Xft assumes this as well */
2197 glyph_index
= _cairo_scaled_glyph_index (scaled_glyph
);
2199 xcb_render_add_glyphs (dpy
, font_private
->glyphset
,
2200 1, &glyph_index
, &glyph_info
,
2201 glyph_surface
->stride
* glyph_surface
->height
,
2204 if (data
!= glyph_surface
->data
)
2208 if (glyph_surface
!= scaled_glyph
->surface
)
2209 cairo_surface_destroy (&glyph_surface
->base
);
2214 #define N_STACK_BUF 1024
2216 static cairo_status_t
2217 _cairo_xcb_surface_show_glyphs_8 (cairo_xcb_surface_t
*dst
,
2218 cairo_operator_t op
,
2219 cairo_xcb_surface_t
*src
,
2220 int src_x_offset
, int src_y_offset
,
2221 const cairo_glyph_t
*glyphs
,
2223 cairo_scaled_font_t
*scaled_font
)
2225 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2226 xcb_render_util_composite_text_stream_t
*stream
;
2229 int lastX
= 0, lastY
= 0;
2232 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2234 for (i
= 0; i
< num_glyphs
; ++i
) {
2235 thisX
= _cairo_lround (glyphs
[i
].x
);
2236 thisY
= _cairo_lround (glyphs
[i
].y
);
2237 glyph
= glyphs
[i
].index
;
2238 xcb_render_util_glyphs_8 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2243 xcb_render_util_composite_text (dst
->dpy
,
2244 _render_operator (op
),
2247 font_private
->xrender_format
->id
,
2248 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2249 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2252 xcb_render_util_composite_text_free (stream
);
2254 return CAIRO_STATUS_SUCCESS
;
2257 static cairo_status_t
2258 _cairo_xcb_surface_show_glyphs_16 (cairo_xcb_surface_t
*dst
,
2259 cairo_operator_t op
,
2260 cairo_xcb_surface_t
*src
,
2261 int src_x_offset
, int src_y_offset
,
2262 const cairo_glyph_t
*glyphs
,
2264 cairo_scaled_font_t
*scaled_font
)
2266 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2267 xcb_render_util_composite_text_stream_t
*stream
;
2270 int lastX
= 0, lastY
= 0;
2273 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2275 for (i
= 0; i
< num_glyphs
; ++i
) {
2276 thisX
= _cairo_lround (glyphs
[i
].x
);
2277 thisY
= _cairo_lround (glyphs
[i
].y
);
2278 glyph
= glyphs
[i
].index
;
2279 xcb_render_util_glyphs_16 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2284 xcb_render_util_composite_text (dst
->dpy
,
2285 _render_operator (op
),
2288 font_private
->xrender_format
->id
,
2289 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2290 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2293 xcb_render_util_composite_text_free (stream
);
2295 return CAIRO_STATUS_SUCCESS
;
2298 static cairo_status_t
2299 _cairo_xcb_surface_show_glyphs_32 (cairo_xcb_surface_t
*dst
,
2300 cairo_operator_t op
,
2301 cairo_xcb_surface_t
*src
,
2302 int src_x_offset
, int src_y_offset
,
2303 const cairo_glyph_t
*glyphs
,
2305 cairo_scaled_font_t
*scaled_font
)
2307 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2308 xcb_render_util_composite_text_stream_t
*stream
;
2311 int lastX
= 0, lastY
= 0;
2314 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2316 for (i
= 0; i
< num_glyphs
; ++i
) {
2317 thisX
= _cairo_lround (glyphs
[i
].x
);
2318 thisY
= _cairo_lround (glyphs
[i
].y
);
2319 glyph
= glyphs
[i
].index
;
2320 xcb_render_util_glyphs_32 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2325 xcb_render_util_composite_text (dst
->dpy
,
2326 _render_operator (op
),
2329 font_private
->xrender_format
->id
,
2330 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2331 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2334 xcb_render_util_composite_text_free (stream
);
2336 return CAIRO_STATUS_SUCCESS
;
2339 typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t
)
2340 (cairo_xcb_surface_t
*, cairo_operator_t
, cairo_xcb_surface_t
*, int, int,
2341 const cairo_glyph_t
*, int, cairo_scaled_font_t
*);
2344 _cairo_xcb_surface_owns_font (cairo_xcb_surface_t
*dst
,
2345 cairo_scaled_font_t
*scaled_font
)
2347 cairo_xcb_surface_font_private_t
*font_private
;
2349 font_private
= scaled_font
->surface_private
;
2350 if ((scaled_font
->surface_backend
!= NULL
&&
2351 scaled_font
->surface_backend
!= &cairo_xcb_surface_backend
) ||
2352 (font_private
!= NULL
&& font_private
->dpy
!= dst
->dpy
))
2362 static cairo_status_t
2363 _cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t
*dst
,
2364 cairo_glyph_t
*glyphs
,
2366 cairo_scaled_font_t
*scaled_font
,
2367 cairo_operator_t op
,
2368 cairo_xcb_surface_t
*src
,
2369 cairo_surface_attributes_t
*attributes
,
2370 int *remaining_glyphs
)
2372 cairo_scaled_glyph_t
*scaled_glyph
;
2374 unsigned long max_index
= 0;
2375 cairo_status_t status
;
2376 cairo_glyph_t
*output_glyphs
;
2377 const cairo_glyph_t
*glyphs_chunk
;
2378 int glyphs_remaining
, chunk_size
, max_chunk_size
;
2379 cairo_xcb_surface_show_glyphs_func_t show_glyphs_func
;
2381 /* We make a copy of the glyphs so that we can elide any size-zero
2382 * glyphs to workaround an X server bug, (present in at least Xorg
2383 * 7.1 without EXA). */
2384 output_glyphs
= _cairo_malloc_ab (num_glyphs
, sizeof (cairo_glyph_t
));
2385 if (output_glyphs
== NULL
)
2386 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2388 for (i
= 0, o
= 0; i
< num_glyphs
; i
++) {
2389 if (glyphs
[i
].index
> max_index
)
2390 max_index
= glyphs
[i
].index
;
2391 status
= _cairo_scaled_glyph_lookup (scaled_font
,
2393 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
2396 free (output_glyphs
);
2400 /* Don't put any size-zero glyphs into output_glyphs to avoid
2401 * an X server bug which stops rendering glyphs after the
2402 * first size-zero glyph. */
2403 if (scaled_glyph
->surface
->width
&& scaled_glyph
->surface
->height
) {
2404 output_glyphs
[o
++] = glyphs
[i
];
2405 if (scaled_glyph
->surface_private
== NULL
) {
2406 _cairo_xcb_surface_add_glyph (dst
->dpy
, scaled_font
, scaled_glyph
);
2407 scaled_glyph
->surface_private
= (void *) 1;
2413 _cairo_xcb_surface_ensure_dst_picture (dst
);
2415 max_chunk_size
= xcb_get_maximum_request_length (dst
->dpy
);
2416 if (max_index
< 256) {
2417 /* XXX: these are all the same size! (28) */
2418 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_8_request_t
);
2419 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_8
;
2420 } else if (max_index
< 65536) {
2421 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_16_request_t
);
2422 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_16
;
2424 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_32_request_t
);
2425 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_32
;
2427 /* XXX: I think this is wrong; this is only the header size (2 longs) */
2428 /* but should also include the glyph (1 long) */
2429 /* max_chunk_size /= sz_xGlyphElt; */
2430 max_chunk_size
/= 3*sizeof(uint32_t);
2432 for (glyphs_remaining
= num_glyphs
, glyphs_chunk
= output_glyphs
;
2434 glyphs_remaining
-= chunk_size
, glyphs_chunk
+= chunk_size
)
2436 chunk_size
= MIN (glyphs_remaining
, max_chunk_size
);
2438 status
= show_glyphs_func (dst
, op
, src
,
2439 attributes
->x_offset
, attributes
->y_offset
,
2440 glyphs_chunk
, chunk_size
, scaled_font
);
2442 free (output_glyphs
);
2447 /* We wouldn't want to leak memory, would we? */
2448 free(output_glyphs
);
2450 return CAIRO_STATUS_SUCCESS
;
2453 static cairo_int_status_t
2454 _cairo_xcb_surface_show_glyphs (void *abstract_dst
,
2455 cairo_operator_t op
,
2456 const cairo_pattern_t
*src_pattern
,
2457 cairo_glyph_t
*glyphs
,
2459 cairo_scaled_font_t
*scaled_font
,
2460 int *remaining_glyphs
,
2461 cairo_rectangle_int_t
*extents
)
2463 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
2464 cairo_xcb_surface_t
*dst
= abstract_dst
;
2466 composite_operation_t operation
;
2467 cairo_surface_attributes_t attributes
;
2468 cairo_xcb_surface_t
*src
= NULL
;
2470 cairo_solid_pattern_t solid_pattern
;
2472 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst
) || dst
->xrender_format
.id
== XCB_NONE
)
2473 return CAIRO_INT_STATUS_UNSUPPORTED
;
2475 /* Just let unbounded operators go through the fallback code
2476 * instead of trying to do the fixups here */
2477 if (!_cairo_operator_bounded_by_mask (op
))
2478 return CAIRO_INT_STATUS_UNSUPPORTED
;
2480 /* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs --
2481 * the solid source seems to be multiplied by the glyph mask, and
2482 * then the entire thing is copied to the destination surface,
2483 * including the fully transparent "background" of the rectangular
2485 if (op
== CAIRO_OPERATOR_SOURCE
&&
2486 !CAIRO_SURFACE_RENDER_AT_LEAST(dst
, 0, 11))
2487 return CAIRO_INT_STATUS_UNSUPPORTED
;
2489 /* We can only use our code if we either have no clip or
2490 * have a real native clip region set. If we're using
2491 * fallback clip masking, we have to go through the full
2494 if (dst
->base
.clip
&&
2495 (dst
->base
.clip
->mode
!= CAIRO_CLIP_MODE_REGION
||
2496 dst
->base
.clip
->surface
!= NULL
))
2497 return CAIRO_INT_STATUS_UNSUPPORTED
;
2499 operation
= _categorize_composite_operation (dst
, op
, src_pattern
, TRUE
);
2500 if (operation
== DO_UNSUPPORTED
)
2501 return CAIRO_INT_STATUS_UNSUPPORTED
;
2503 if (! _cairo_xcb_surface_owns_font (dst
, scaled_font
))
2504 return CAIRO_INT_STATUS_UNSUPPORTED
;
2506 /* After passing all those tests, we're now committed to rendering
2507 * these glyphs or to fail trying. We first upload any glyphs to
2508 * the X server that it doesn't have already, then we draw
2509 * them. We tie into the scaled_font's glyph cache and remove
2510 * glyphs from the X server when they are ejected from the
2511 * scaled_font cache.
2514 /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
2515 * the mask (the glyphs). This code below was executed as a side effect
2516 * of going through the _clip_and_composite fallback code for old_show_glyphs,
2517 * so PictOpClear was never used with CompositeText before.
2519 if (op
== CAIRO_OPERATOR_CLEAR
) {
2520 _cairo_pattern_init_solid (&solid_pattern
, CAIRO_COLOR_WHITE
,
2521 CAIRO_CONTENT_COLOR
);
2522 src_pattern
= &solid_pattern
.base
;
2523 op
= CAIRO_OPERATOR_DEST_OUT
;
2526 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
) {
2527 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
2528 CAIRO_CONTENT_COLOR_ALPHA
,
2530 CAIRO_PATTERN_ACQUIRE_NONE
,
2531 (cairo_surface_t
**) &src
,
2534 cairo_rectangle_int_t glyph_extents
;
2536 status
= _cairo_scaled_font_glyph_device_extents (scaled_font
,
2543 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
2544 CAIRO_CONTENT_COLOR_ALPHA
,
2545 glyph_extents
.x
, glyph_extents
.y
,
2546 glyph_extents
.width
, glyph_extents
.height
,
2547 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
,
2548 (cairo_surface_t
**) &src
,
2555 operation
= _recategorize_composite_operation (dst
, op
, src
, &attributes
, TRUE
);
2556 if (operation
== DO_UNSUPPORTED
) {
2557 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2561 status
= _cairo_xcb_surface_set_attributes (src
, &attributes
);
2565 /* Send all unsent glyphs to the server, and count the max of the glyph indices */
2566 _cairo_scaled_font_freeze_cache (scaled_font
);
2568 if (_cairo_xcb_surface_owns_font (dst
, scaled_font
))
2569 status
= _cairo_xcb_surface_emit_glyphs (dst
,
2577 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2578 _cairo_scaled_font_thaw_cache (scaled_font
);
2582 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &attributes
);
2583 if (src_pattern
== &solid_pattern
.base
)
2584 _cairo_pattern_fini (&solid_pattern
.base
);
2593 xcb_connection_t
* conn
;
2594 xcb_screen_t
* screen
;
2597 } cairo_xcb_space_t
;
2600 _cairo_xcb_space_destroy(void* abstract_space
)
2602 cairo_xcb_space_t
* space
= abstract_space
;
2603 if(space
->owns_conn
)
2604 xcb_disconnect(space
->conn
);
2606 XCloseDisplay(space
->dpy
);
2610 static cairo_surface_t
*
2611 _cairo_xcb_space_surface_create(void* abstract_space
, cairo_content_t content
, int width
, int height
, int mantissa_bits
, int shared_exponent_bits
, int component_exponent_bits
)
2613 cairo_xcb_space_t
* space
= abstract_space
;
2614 cairo_xlib_display_t
* display
;
2616 cairo_xlib_surface_t
*surface
;
2617 XRenderPictFormat
*xrender_format
;
2619 assert (width
<= XLIB_COORD_MAX
&& height
<= XLIB_COORD_MAX
);
2621 if(_cairo_xlib_display_get(space
->dpy
, &display
))
2624 /* As a good first approximation, if the display doesn't have even
2625 * the most elementary RENDER operation, then we're better off
2626 * using image surfaces for all temporary operations, so return NULL
2627 * and let the fallback code happen.
2629 if (CAIRO_SURFACE_RENDER_HAS_COMPOSITE (display
))
2632 xrender_format
= _cairo_xlib_display_get_xrender_format (display
,
2633 _cairo_format_from_content(content
));
2634 if (xrender_format
== NULL
)
2637 pix
= XCreatePixmap (space
->dpy
, RootWindowOfScreen(space
->screen
),
2638 width
<= 0 ? 1 : width
, height
<= 0 ? 1 : height
,
2639 xrender_format
->depth
);
2641 surface
= (cairo_xlib_surface_t
*)
2642 _cairo_xlib_surface_create_internal (space
->dpy
, pix
,
2643 space
->screen
, NULL
,
2646 xrender_format
->depth
);
2647 if (surface
->base
.status
) {
2648 XFreePixmap (space
->dpy
, pix
);
2649 return &surface
->base
;
2652 surface
->owns_pixmap
= TRUE
;
2654 return &surface
->base
;
2658 _cairo_get_visualtype(xcb_connection_t
* conn
, xcb_screen
* screen
, unsigned long drawable
, unsigned long visualid
)
2660 xcb_depth_iterator_t depths
;
2661 xcb_visualtype_iterator_t visuals
;
2662 xcb_screen_t
* screen
;
2667 visualid
= screen
->root_visual
;
2670 xcb_generic_error_t
* e
= 0;
2671 xcb_get_window_attributes_reply_t
* gwa
;
2673 gwa
= xcb_get_window_attributes_reply(conn
, xcb_get_window_attributes(conn
, drawable
), &e
);
2677 visualid
= gwa
->visualid
;
2683 xcb_depth_iterator_t d
;
2684 xcb_screen_iterator_t s
= xcb_setup_roots_iterator(xcb_get_setup(conn
));
2685 for (; s
.rem
; xcb_screen_next(&s
))
2687 if (s
.data
->root_visual
== visual
->visual_id
)
2690 d
= xcb_screen_allowed_depths_iterator(s
.data
);
2691 for (; d
.rem
; xcb_depth_next(&d
))
2693 xcb_visualtype_iterator_t v
= xcb_depth_visuals_iterator(d
.data
);
2694 for (; v
.rem
; xcb_visualtype_next(&v
))
2696 if (v
.data
->visual_id
== visualid
)
2704 static cairo_surface_t
*
2705 _cairo_xcb_space_surface_create_for_drawable(void* abstract_space
, unsigned long drawable
, unsigned long visualid
, int width
, int height
)
2707 cairo_xcb_space_t
* space
= abstract_space
;
2708 xcb_visualtype
* vi
= _cairo_get_visualtype(space
->conn
, space
->screen
, drawable
, visual
);
2710 return _cairo_surface_create_in_error(CAIRO_STATUS_INVALID_VISUAL
);
2713 cairo_surface_t
* surface
= cairo_xcb_surface_create(space
->conn
, (xcb_drawable_t
)drawable
, vi
->visual
, width
, height
);
2720 cairo_space_backend_t _cairo_xcb_space_backend
=
2722 _cairo_xcb_space_destroy
,
2723 _cairo_xcb_space_surface_create
,
2724 _cairo_xcb_space_surface_create_for_drawable
,
2727 cairo_public cairo_space_t
*
2728 cairo_xcb_space_create(const char* name
)
2730 xcb_connect_t
* conn
;
2732 conn
= xcb_connect(name
, &screen
);
2736 return cairo_xcb_space_wrap(conn
, screen
, 1);
2739 cairo_public cairo_space_t
*
2740 cairo_xcb_space_wrap(xcb_connection_t
* conn
, int screen
, int owns_conn
)
2742 cairo_xcb_space_t
* space
;
2744 return cairo_xcb_space_create(0);
2746 space
= calloc(sizeof(cairo_xcb_space_t
), 1);
2748 CAIRO_REFERENCE_COUNT_INIT(&space
->base
.ref_count
, 1);
2749 space
->base
.backend
= &_cairo_xcb_space_backend
;
2752 xcb_screen_iterator_t s
= xcb_setup_roots_iterator(xcb_get_setup(conn
));
2753 for (; s
.rem
; xcb_screen_next(&s
))
2755 if(s
.index
== screen
)
2757 space
->screen
= s
.data
;
2762 space
->screen
= s
.data
;
2765 space
->owns_conn
= owns_conn
;
2767 return &space
->base
;
2770 cairo_public cairo_space_t
*
2771 cairo_xcb_space_wrap_xlib(Display
* dpy
, int screen
, int owns_dpy
)
2773 cairo_space_t
* space
= cairo_xcb_space_wrap(XGetXCBConnection(dpy
), screen
, 0);
2775 ((cairo_xcb_space_t
*)space
)->dpy
= dpy
;