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)
106 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t
*surface
);
109 _CAIRO_FORMAT_DEPTH (cairo_format_t format
)
112 case CAIRO_FORMAT_A1
:
114 case CAIRO_FORMAT_A8
:
116 case CAIRO_FORMAT_RGB24
:
118 case CAIRO_FORMAT_ARGB32
:
124 static xcb_render_pictforminfo_t
*
125 _CAIRO_FORMAT_TO_XRENDER_FORMAT(xcb_connection_t
*dpy
, cairo_format_t format
)
127 xcb_pict_standard_t std_format
;
129 case CAIRO_FORMAT_A1
:
130 std_format
= XCB_PICT_STANDARD_A_1
; break;
131 case CAIRO_FORMAT_A8
:
132 std_format
= XCB_PICT_STANDARD_A_8
; break;
133 case CAIRO_FORMAT_RGB24
:
134 std_format
= XCB_PICT_STANDARD_RGB_24
; break;
135 case CAIRO_FORMAT_ARGB32
:
137 std_format
= XCB_PICT_STANDARD_ARGB_32
; break;
139 return xcb_render_util_find_standard_format (xcb_render_util_query_formats (dpy
), std_format
);
142 static cairo_content_t
143 _xcb_render_format_to_content (xcb_render_pictforminfo_t
*xrender_format
)
145 cairo_bool_t xrender_format_has_alpha
;
146 cairo_bool_t xrender_format_has_color
;
148 /* This only happens when using a non-Render server. Let's punt
149 * and say there's no alpha here. */
150 if (xrender_format
== NULL
)
151 return CAIRO_CONTENT_COLOR
;
153 xrender_format_has_alpha
= (xrender_format
->direct
.alpha_mask
!= 0);
154 xrender_format_has_color
= (xrender_format
->direct
.red_mask
!= 0 ||
155 xrender_format
->direct
.green_mask
!= 0 ||
156 xrender_format
->direct
.blue_mask
!= 0);
158 if (xrender_format_has_alpha
)
159 if (xrender_format_has_color
)
160 return CAIRO_CONTENT_COLOR_ALPHA
;
162 return CAIRO_CONTENT_ALPHA
;
164 return CAIRO_CONTENT_COLOR
;
167 static cairo_surface_t
*
168 _cairo_xcb_surface_create_similar (void *abstract_src
,
169 cairo_content_t content
,
173 cairo_xcb_surface_t
*src
= abstract_src
;
174 xcb_connection_t
*dpy
= src
->dpy
;
176 cairo_xcb_surface_t
*surface
;
177 cairo_format_t format
= _cairo_format_from_content (content
);
178 xcb_render_pictforminfo_t
*xrender_format
;
180 /* As a good first approximation, if the display doesn't have COMPOSITE,
181 * we're better off using image surfaces for all temporary operations
183 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src
)) {
184 return cairo_image_surface_create (format
, width
, height
);
187 pixmap
= xcb_generate_id (dpy
);
188 xcb_create_pixmap (dpy
, _CAIRO_FORMAT_DEPTH (format
),
189 pixmap
, src
->drawable
,
190 width
<= 0 ? 1 : width
,
191 height
<= 0 ? 1 : height
);
193 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy
, format
);
194 /* XXX: what to do if xrender_format is null? */
195 surface
= (cairo_xcb_surface_t
*)
196 cairo_xcb_surface_create_with_xrender_format (dpy
, pixmap
, src
->screen
,
199 if (surface
->base
.status
)
200 return &surface
->base
;
202 surface
->owns_pixmap
= TRUE
;
204 return &surface
->base
;
207 static cairo_status_t
208 _cairo_xcb_surface_finish (void *abstract_surface
)
210 cairo_xcb_surface_t
*surface
= abstract_surface
;
211 if (surface
->dst_picture
!= XCB_NONE
)
212 xcb_render_free_picture (surface
->dpy
, surface
->dst_picture
);
214 if (surface
->src_picture
!= XCB_NONE
)
215 xcb_render_free_picture (surface
->dpy
, surface
->src_picture
);
217 if (surface
->owns_pixmap
)
218 xcb_free_pixmap (surface
->dpy
, surface
->drawable
);
220 if (surface
->gc
!= XCB_NONE
)
221 xcb_free_gc (surface
->dpy
, surface
->gc
);
223 free (surface
->clip_rects
);
227 return CAIRO_STATUS_SUCCESS
;
231 _bits_per_pixel(xcb_connection_t
*c
, int depth
)
233 xcb_format_t
*fmt
= xcb_setup_pixmap_formats(xcb_get_setup(c
));
234 xcb_format_t
*fmtend
= fmt
+ xcb_setup_pixmap_formats_length(xcb_get_setup(c
));
236 for(; fmt
!= fmtend
; ++fmt
)
237 if(fmt
->depth
== depth
)
238 return fmt
->bits_per_pixel
;
250 _bytes_per_line(xcb_connection_t
*c
, int width
, int bpp
)
252 int bitmap_pad
= xcb_get_setup(c
)->bitmap_format_scanline_pad
;
253 return ((bpp
* width
+ bitmap_pad
- 1) & -bitmap_pad
) >> 3;
257 _CAIRO_MASK_FORMAT (cairo_format_masks_t
*masks
, cairo_format_t
*format
)
259 switch (masks
->bpp
) {
261 if (masks
->alpha_mask
== 0xff000000 &&
262 masks
->red_mask
== 0x00ff0000 &&
263 masks
->green_mask
== 0x0000ff00 &&
264 masks
->blue_mask
== 0x000000ff)
266 *format
= CAIRO_FORMAT_ARGB32
;
269 if (masks
->alpha_mask
== 0x00000000 &&
270 masks
->red_mask
== 0x00ff0000 &&
271 masks
->green_mask
== 0x0000ff00 &&
272 masks
->blue_mask
== 0x000000ff)
274 *format
= CAIRO_FORMAT_RGB24
;
279 if (masks
->alpha_mask
== 0xff)
281 *format
= CAIRO_FORMAT_A8
;
286 if (masks
->alpha_mask
== 0x1)
288 *format
= CAIRO_FORMAT_A1
;
296 static cairo_status_t
297 _get_image_surface (cairo_xcb_surface_t
*surface
,
298 cairo_rectangle_int_t
*interest_rect
,
299 cairo_image_surface_t
**image_out
,
300 cairo_rectangle_int_t
*image_rect
)
302 cairo_image_surface_t
*image
;
303 xcb_get_image_reply_t
*imagerep
;
304 int bpp
, bytes_per_line
;
305 cairo_rectangle_int_t extents
;
307 cairo_format_masks_t masks
;
308 cairo_format_t format
;
312 extents
.width
= surface
->width
;
313 extents
.height
= surface
->height
;
316 if (! _cairo_rectangle_intersect (&extents
, interest_rect
)) {
318 return CAIRO_STATUS_SUCCESS
;
323 *image_rect
= extents
;
325 /* XXX: This should try to use the XShm extension if available */
327 if (surface
->use_pixmap
== 0)
329 xcb_generic_error_t
*error
;
330 imagerep
= xcb_get_image_reply(surface
->dpy
,
331 xcb_get_image(surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
333 extents
.x
, extents
.y
,
334 extents
.width
, extents
.height
,
337 /* If we get an error, the surface must have been a window,
338 * so retry with the safe code path.
341 surface
->use_pixmap
= CAIRO_ASSUME_PIXMAP
;
345 surface
->use_pixmap
--;
351 /* xcb_get_image_t from a window is dangerous because it can
352 * produce errors if the window is unmapped or partially
353 * outside the screen. We could check for errors and
354 * retry, but to keep things simple, we just create a
358 pixmap
= xcb_generate_id (surface
->dpy
);
359 xcb_create_pixmap (surface
->dpy
,
363 extents
.width
, extents
.height
);
364 _cairo_xcb_surface_ensure_gc (surface
);
366 xcb_copy_area (surface
->dpy
, surface
->drawable
, pixmap
, surface
->gc
,
367 extents
.x
, extents
.y
, 0, 0, extents
.width
, extents
.height
);
369 imagerep
= xcb_get_image_reply(surface
->dpy
,
370 xcb_get_image(surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
372 extents
.x
, extents
.y
,
373 extents
.width
, extents
.height
,
375 xcb_free_pixmap (surface
->dpy
, pixmap
);
379 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
381 bpp
= _bits_per_pixel(surface
->dpy
, imagerep
->depth
);
382 bytes_per_line
= _bytes_per_line(surface
->dpy
, surface
->width
, bpp
);
384 data
= _cairo_malloc_ab (surface
->height
, bytes_per_line
);
387 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
390 memcpy (data
, xcb_get_image_data (imagerep
), bytes_per_line
* surface
->height
);
394 * Compute the pixel format masks from either an xcb_visualtype_t or
395 * a xcb_render_pctforminfo_t, failing we assume the drawable is an
396 * alpha-only pixmap as it could only have been created that way
397 * through the cairo_xlib_surface_create_for_bitmap function.
399 if (surface
->visual
) {
401 masks
.alpha_mask
= 0;
402 masks
.red_mask
= surface
->visual
->red_mask
;
403 masks
.green_mask
= surface
->visual
->green_mask
;
404 masks
.blue_mask
= surface
->visual
->blue_mask
;
405 } else if (surface
->xrender_format
.id
!= XCB_NONE
) {
407 masks
.red_mask
= (unsigned long)surface
->xrender_format
.direct
.red_mask
<< surface
->xrender_format
.direct
.red_shift
;
408 masks
.green_mask
= (unsigned long)surface
->xrender_format
.direct
.green_mask
<< surface
->xrender_format
.direct
.green_shift
;
409 masks
.blue_mask
= (unsigned long)surface
->xrender_format
.direct
.blue_mask
<< surface
->xrender_format
.direct
.blue_shift
;
410 masks
.alpha_mask
= (unsigned long)surface
->xrender_format
.direct
.alpha_mask
<< surface
->xrender_format
.direct
.alpha_shift
;
414 masks
.green_mask
= 0;
416 if (surface
->depth
< 32)
417 masks
.alpha_mask
= (1 << surface
->depth
) - 1;
419 masks
.alpha_mask
= 0xffffffff;
423 * Prefer to use a standard pixman format instead of the
424 * general masks case.
426 if (_CAIRO_MASK_FORMAT (&masks
, &format
)) {
427 image
= (cairo_image_surface_t
*)
428 cairo_image_surface_create_for_data (data
,
433 if (image
->base
.status
)
437 * XXX This can't work. We must convert the data to one of the
438 * supported pixman formats. Pixman needs another function
439 * which takes data in an arbitrary format and converts it
440 * to something supported by that library.
442 image
= (cairo_image_surface_t
*)
443 _cairo_image_surface_create_with_masks (data
,
448 if (image
->base
.status
)
452 /* Let the surface take ownership of the data */
453 _cairo_image_surface_assume_ownership_of_data (image
);
456 return CAIRO_STATUS_SUCCESS
;
460 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
464 _cairo_xcb_surface_ensure_src_picture (cairo_xcb_surface_t
*surface
)
466 if (!surface
->src_picture
) {
467 surface
->src_picture
= xcb_generate_id(surface
->dpy
);
468 xcb_render_create_picture (surface
->dpy
,
469 surface
->src_picture
,
471 surface
->xrender_format
.id
,
477 _cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t
*surface
)
479 if (surface
->have_clip_rects
)
480 xcb_render_set_picture_clip_rectangles (surface
->dpy
, surface
->dst_picture
,
482 surface
->num_clip_rects
,
483 surface
->clip_rects
);
487 _cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t
*surface
)
489 if (surface
->have_clip_rects
)
490 xcb_set_clip_rectangles(surface
->dpy
, XCB_CLIP_ORDERING_YX_SORTED
, surface
->gc
,
492 surface
->num_clip_rects
,
493 surface
->clip_rects
);
497 _cairo_xcb_surface_ensure_dst_picture (cairo_xcb_surface_t
*surface
)
499 if (!surface
->dst_picture
) {
500 surface
->dst_picture
= xcb_generate_id(surface
->dpy
);
501 xcb_render_create_picture (surface
->dpy
,
502 surface
->dst_picture
,
504 surface
->xrender_format
.id
,
506 _cairo_xcb_surface_set_picture_clip_rects (surface
);
512 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t
*surface
)
517 surface
->gc
= xcb_generate_id(surface
->dpy
);
518 xcb_create_gc (surface
->dpy
, surface
->gc
, surface
->drawable
, 0, 0);
519 _cairo_xcb_surface_set_gc_clip_rects(surface
);
522 static cairo_status_t
523 _draw_image_surface (cairo_xcb_surface_t
*surface
,
524 cairo_image_surface_t
*image
,
534 uint8_t *data
, left_pad
=0;
536 /* equivalent of XPutImage(..., src_x,src_y, dst_x,dst_y, width,height); */
537 /* XXX: assumes image and surface formats and depths are the same */
538 /* XXX: assumes depth is a multiple of 8 (not bitmap) */
540 /* fit src_{x,y,width,height} within image->{0,0,width,height} */
549 if (width
+ src_x
> image
->width
)
550 width
= image
->width
- src_x
;
551 if (height
+ src_y
> image
->height
)
552 height
= image
->height
- src_y
;
553 if (width
<= 0 || height
<= 0)
554 return CAIRO_STATUS_SUCCESS
;
556 bpp
= _bits_per_pixel(surface
->dpy
, image
->depth
);
557 /* XXX: could use bpl = image->stride? */
558 bpl
= _bytes_per_line(surface
->dpy
, image
->width
, bpp
);
560 if (src_x
== 0 && width
== image
->width
) {
561 /* can work in-place */
562 data_len
= height
* bpl
;
563 data
= image
->data
+ src_y
* bpl
;
565 /* must copy {src_x,src_y,width,height} into new data */
567 uint8_t *data_line
, *image_line
;
568 int data_bpl
= _bytes_per_line(surface
->dpy
, width
, bpp
);
569 data_len
= height
* data_bpl
;
570 data_line
= data
= malloc(data_len
);
572 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
574 image_line
= image
->data
+ src_y
* bpl
+ (src_x
* bpp
/ 8);
575 while (line
++ < height
) {
576 memcpy(data_line
, image_line
, data_bpl
);
577 data_line
+= data_bpl
;
581 _cairo_xcb_surface_ensure_gc (surface
);
582 xcb_put_image (surface
->dpy
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
583 surface
->drawable
, surface
->gc
,
586 left_pad
, image
->depth
,
589 if (data
< image
->data
|| data
>= image
->data
+ image
->height
* bpl
)
592 return CAIRO_STATUS_SUCCESS
;
595 static cairo_status_t
596 _cairo_xcb_surface_acquire_source_image (void *abstract_surface
,
597 cairo_image_surface_t
**image_out
,
600 cairo_xcb_surface_t
*surface
= abstract_surface
;
601 cairo_image_surface_t
*image
;
602 cairo_status_t status
;
604 status
= _get_image_surface (surface
, NULL
, &image
, NULL
);
611 return CAIRO_STATUS_SUCCESS
;
615 _cairo_xcb_surface_release_source_image (void *abstract_surface
,
616 cairo_image_surface_t
*image
,
619 cairo_surface_destroy (&image
->base
);
622 static cairo_status_t
623 _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
,
624 cairo_rectangle_int_t
*interest_rect
,
625 cairo_image_surface_t
**image_out
,
626 cairo_rectangle_int_t
*image_rect_out
,
629 cairo_xcb_surface_t
*surface
= abstract_surface
;
630 cairo_image_surface_t
*image
;
631 cairo_status_t status
;
633 status
= _get_image_surface (surface
, interest_rect
, &image
, image_rect_out
);
640 return CAIRO_STATUS_SUCCESS
;
644 _cairo_xcb_surface_release_dest_image (void *abstract_surface
,
645 cairo_rectangle_int_t
*interest_rect
,
646 cairo_image_surface_t
*image
,
647 cairo_rectangle_int_t
*image_rect
,
650 cairo_xcb_surface_t
*surface
= abstract_surface
;
653 _draw_image_surface (surface
, image
, 0, 0, image
->width
, image
->height
,
654 image_rect
->x
, image_rect
->y
);
656 cairo_surface_destroy (&image
->base
);
660 * Return whether two xcb surfaces share the same
661 * screen. Both core and Render drawing require this
662 * when using multiple drawables in an operation.
665 _cairo_xcb_surface_same_screen (cairo_xcb_surface_t
*dst
,
666 cairo_xcb_surface_t
*src
)
668 return dst
->dpy
== src
->dpy
&& dst
->screen
== src
->screen
;
671 static cairo_status_t
672 _cairo_xcb_surface_clone_similar (void *abstract_surface
,
673 cairo_surface_t
*src
,
680 cairo_surface_t
**clone_out
)
682 cairo_xcb_surface_t
*surface
= abstract_surface
;
683 cairo_xcb_surface_t
*clone
;
685 if (src
->backend
== surface
->base
.backend
) {
686 cairo_xcb_surface_t
*xcb_src
= (cairo_xcb_surface_t
*)src
;
688 if (_cairo_xcb_surface_same_screen(surface
, xcb_src
)) {
691 *clone_out
= cairo_surface_reference (src
);
693 return CAIRO_STATUS_SUCCESS
;
695 } else if (_cairo_surface_is_image (src
)) {
696 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*)src
;
697 cairo_content_t content
= _cairo_content_from_format (image_src
->format
);
698 cairo_status_t status
;
700 if (surface
->base
.status
)
701 return surface
->base
.status
;
703 clone
= (cairo_xcb_surface_t
*)
704 _cairo_xcb_surface_create_similar (surface
, content
, width
, height
);
706 return CAIRO_INT_STATUS_UNSUPPORTED
;
707 if (clone
->base
.status
)
708 return clone
->base
.status
;
710 status
= _draw_image_surface (clone
, image_src
,
715 cairo_surface_destroy (&clone
->base
);
719 *clone_offset_x
= src_x
;
720 *clone_offset_y
= src_y
;
721 *clone_out
= &clone
->base
;
723 return CAIRO_STATUS_SUCCESS
;
726 return CAIRO_INT_STATUS_UNSUPPORTED
;
729 static cairo_status_t
730 _cairo_xcb_surface_set_matrix (cairo_xcb_surface_t
*surface
,
731 cairo_matrix_t
*matrix
)
733 xcb_render_transform_t xtransform
;
735 if (!surface
->src_picture
)
736 return CAIRO_STATUS_SUCCESS
;
738 xtransform
.matrix11
= _cairo_fixed_16_16_from_double (matrix
->xx
);
739 xtransform
.matrix12
= _cairo_fixed_16_16_from_double (matrix
->xy
);
740 xtransform
.matrix13
= _cairo_fixed_16_16_from_double (matrix
->x0
);
742 xtransform
.matrix21
= _cairo_fixed_16_16_from_double (matrix
->yx
);
743 xtransform
.matrix22
= _cairo_fixed_16_16_from_double (matrix
->yy
);
744 xtransform
.matrix23
= _cairo_fixed_16_16_from_double (matrix
->y0
);
746 xtransform
.matrix31
= 0;
747 xtransform
.matrix32
= 0;
748 xtransform
.matrix33
= 1 << 16;
750 if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface
))
752 static const xcb_render_transform_t identity
= {
753 1 << 16, 0x00000, 0x00000,
754 0x00000, 1 << 16, 0x00000,
755 0x00000, 0x00000, 1 << 16
758 if (memcmp (&xtransform
, &identity
, sizeof (xcb_render_transform_t
)) == 0)
759 return CAIRO_STATUS_SUCCESS
;
761 return CAIRO_INT_STATUS_UNSUPPORTED
;
764 xcb_render_set_picture_transform (surface
->dpy
, surface
->src_picture
, xtransform
);
766 return CAIRO_STATUS_SUCCESS
;
769 static cairo_status_t
770 _cairo_xcb_surface_set_filter (cairo_xcb_surface_t
*surface
,
771 cairo_filter_t filter
)
773 const char *render_filter
;
775 if (!surface
->src_picture
)
776 return CAIRO_STATUS_SUCCESS
;
778 if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface
))
780 if (filter
== CAIRO_FILTER_FAST
|| filter
== CAIRO_FILTER_NEAREST
)
781 return CAIRO_STATUS_SUCCESS
;
783 return CAIRO_INT_STATUS_UNSUPPORTED
;
787 case CAIRO_FILTER_FAST
:
788 render_filter
= "fast";
790 case CAIRO_FILTER_GOOD
:
791 render_filter
= "good";
793 case CAIRO_FILTER_BEST
:
794 render_filter
= "best";
796 case CAIRO_FILTER_NEAREST
:
797 render_filter
= "nearest";
799 case CAIRO_FILTER_BILINEAR
:
800 render_filter
= "bilinear";
802 case CAIRO_FILTER_GAUSSIAN
:
804 render_filter
= "best";
808 xcb_render_set_picture_filter(surface
->dpy
, surface
->src_picture
,
809 strlen(render_filter
), render_filter
, 0, NULL
);
811 return CAIRO_STATUS_SUCCESS
;
814 static cairo_status_t
815 _cairo_xcb_surface_set_repeat (cairo_xcb_surface_t
*surface
, int repeat
)
817 uint32_t mask
= XCB_RENDER_CP_REPEAT
;
818 uint32_t pa
[] = { repeat
};
820 if (!surface
->src_picture
)
821 return CAIRO_STATUS_SUCCESS
;
823 xcb_render_change_picture (surface
->dpy
, surface
->src_picture
, mask
, pa
);
825 return CAIRO_STATUS_SUCCESS
;
828 static cairo_int_status_t
829 _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t
*surface
,
830 cairo_surface_attributes_t
*attributes
)
832 cairo_int_status_t status
;
834 _cairo_xcb_surface_ensure_src_picture (surface
);
836 status
= _cairo_xcb_surface_set_matrix (surface
, &attributes
->matrix
);
840 switch (attributes
->extend
) {
841 case CAIRO_EXTEND_NONE
:
842 _cairo_xcb_surface_set_repeat (surface
, 0);
844 case CAIRO_EXTEND_REPEAT
:
845 _cairo_xcb_surface_set_repeat (surface
, 1);
847 case CAIRO_EXTEND_REFLECT
:
848 case CAIRO_EXTEND_PAD
:
849 return CAIRO_INT_STATUS_UNSUPPORTED
;
852 status
= _cairo_xcb_surface_set_filter (surface
, attributes
->filter
);
856 return CAIRO_STATUS_SUCCESS
;
859 /* Checks whether we can can directly draw from src to dst with
860 * the core protocol: either with CopyArea or using src as a
864 _surfaces_compatible (cairo_xcb_surface_t
*dst
,
865 cairo_xcb_surface_t
*src
)
868 if (!_cairo_xcb_surface_same_screen (dst
, src
))
871 /* same depth (for core) */
872 if (src
->depth
!= dst
->depth
)
875 /* if Render is supported, match picture formats */
876 if (src
->xrender_format
.id
!= dst
->xrender_format
.id
)
878 else if (src
->xrender_format
.id
!= XCB_NONE
)
881 /* Without Render, match visuals instead */
882 if (src
->visual
== dst
->visual
)
889 _surface_has_alpha (cairo_xcb_surface_t
*surface
)
891 if (surface
->xrender_format
.id
!= XCB_NONE
) {
892 if (surface
->xrender_format
.type
== XCB_RENDER_PICT_TYPE_DIRECT
&&
893 surface
->xrender_format
.direct
.alpha_mask
!= 0)
899 /* In the no-render case, we never have alpha */
904 /* Returns true if the given operator and source-alpha combination
905 * requires alpha compositing to complete.
908 _operator_needs_alpha_composite (cairo_operator_t op
,
909 cairo_bool_t surface_has_alpha
)
911 if (op
== CAIRO_OPERATOR_SOURCE
||
912 (!surface_has_alpha
&&
913 (op
== CAIRO_OPERATOR_OVER
||
914 op
== CAIRO_OPERATOR_ATOP
||
915 op
== CAIRO_OPERATOR_IN
)))
921 /* There is a bug in most older X servers with compositing using a
922 * untransformed repeating source pattern when the source is in off-screen
923 * video memory, and another with repeated transformed images using a
924 * general transform matrix. When these bugs could be triggered, we need a
925 * fallback: in the common case where we have no transformation and the
926 * source and destination have the same format/visual, we can do the
927 * operation using the core protocol for the first bug, otherwise, we need
928 * a software fallback.
930 * We can also often optimize a compositing operation by calling XCopyArea
931 * for some common cases where there is no alpha compositing to be done.
932 * We figure that out here as well.
935 DO_RENDER
, /* use render */
936 DO_XCOPYAREA
, /* core protocol XCopyArea optimization/fallback */
937 DO_XTILE
, /* core protocol XSetTile optimization/fallback */
938 DO_UNSUPPORTED
/* software fallback */
939 } composite_operation_t
;
941 /* Initial check for the render bugs; we need to recheck for the
942 * offscreen-memory bug after we turn patterns into surfaces, since that
943 * may introduce a repeating pattern for gradient patterns. We don't need
944 * to check for the repeat+transform bug because gradient surfaces aren't
947 * All we do here is reject cases where we *know* are going to
948 * hit the bug and won't be able to use a core protocol fallback.
950 static composite_operation_t
951 _categorize_composite_operation (cairo_xcb_surface_t
*dst
,
953 cairo_pattern_t
*src_pattern
,
954 cairo_bool_t have_mask
)
958 if (!dst
->buggy_repeat
)
961 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
)
963 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*)src_pattern
;
965 if (_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
966 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
968 /* This is the case where we have the bug involving
969 * untransformed repeating source patterns with off-screen
970 * video memory; reject some cases where a core protocol
971 * fallback is impossible.
974 !(op
== CAIRO_OPERATOR_SOURCE
|| op
== CAIRO_OPERATOR_OVER
))
975 return DO_UNSUPPORTED
;
977 if (_cairo_surface_is_xcb (surface_pattern
->surface
)) {
978 cairo_xcb_surface_t
*src
= (cairo_xcb_surface_t
*)surface_pattern
->surface
;
980 if (op
== CAIRO_OPERATOR_OVER
&& _surface_has_alpha (src
))
981 return DO_UNSUPPORTED
;
983 /* If these are on the same screen but otherwise incompatible,
984 * make a copy as core drawing can't cross depths and doesn't
985 * work rightacross visuals of the same depth
987 if (_cairo_xcb_surface_same_screen (dst
, src
) &&
988 !_surfaces_compatible (dst
, src
))
989 return DO_UNSUPPORTED
;
993 /* Check for the other bug involving repeat patterns with general
995 if (!_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
996 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
997 return DO_UNSUPPORTED
;
1003 /* Recheck for composite-repeat once we've turned patterns into Xlib surfaces
1004 * If we end up returning DO_UNSUPPORTED here, we're throwing away work we
1005 * did to turn gradients into a pattern, but most of the time we can handle
1006 * that case with core protocol fallback.
1008 * Also check here if we can just use XCopyArea, instead of going through
1011 static composite_operation_t
1012 _recategorize_composite_operation (cairo_xcb_surface_t
*dst
,
1013 cairo_operator_t op
,
1014 cairo_xcb_surface_t
*src
,
1015 cairo_surface_attributes_t
*src_attr
,
1016 cairo_bool_t have_mask
)
1018 cairo_bool_t is_integer_translation
=
1019 _cairo_matrix_is_integer_translation (&src_attr
->matrix
, NULL
, NULL
);
1020 cairo_bool_t needs_alpha_composite
=
1021 _operator_needs_alpha_composite (op
, _surface_has_alpha (src
));
1024 is_integer_translation
&&
1025 src_attr
->extend
== CAIRO_EXTEND_NONE
&&
1026 !needs_alpha_composite
&&
1027 _surfaces_compatible(src
, dst
))
1029 return DO_XCOPYAREA
;
1031 #if XXX_BUGGY_REPEAT
1032 if (!dst
->buggy_repeat
)
1035 if (is_integer_translation
&&
1036 src_attr
->extend
== CAIRO_EXTEND_REPEAT
&&
1037 (src
->width
!= 1 || src
->height
!= 1))
1040 !needs_alpha_composite
&&
1041 _surfaces_compatible (dst
, src
))
1046 return DO_UNSUPPORTED
;
1053 _render_operator (cairo_operator_t op
)
1056 case CAIRO_OPERATOR_CLEAR
:
1057 return XCB_RENDER_PICT_OP_CLEAR
;
1058 case CAIRO_OPERATOR_SOURCE
:
1059 return XCB_RENDER_PICT_OP_SRC
;
1060 case CAIRO_OPERATOR_DEST
:
1061 return XCB_RENDER_PICT_OP_DST
;
1062 case CAIRO_OPERATOR_OVER
:
1063 return XCB_RENDER_PICT_OP_OVER
;
1064 case CAIRO_OPERATOR_DEST_OVER
:
1065 return XCB_RENDER_PICT_OP_OVER_REVERSE
;
1066 case CAIRO_OPERATOR_IN
:
1067 return XCB_RENDER_PICT_OP_IN
;
1068 case CAIRO_OPERATOR_DEST_IN
:
1069 return XCB_RENDER_PICT_OP_IN_REVERSE
;
1070 case CAIRO_OPERATOR_OUT
:
1071 return XCB_RENDER_PICT_OP_OUT
;
1072 case CAIRO_OPERATOR_DEST_OUT
:
1073 return XCB_RENDER_PICT_OP_OUT_REVERSE
;
1074 case CAIRO_OPERATOR_ATOP
:
1075 return XCB_RENDER_PICT_OP_ATOP
;
1076 case CAIRO_OPERATOR_DEST_ATOP
:
1077 return XCB_RENDER_PICT_OP_ATOP_REVERSE
;
1078 case CAIRO_OPERATOR_XOR
:
1079 return XCB_RENDER_PICT_OP_XOR
;
1080 case CAIRO_OPERATOR_ADD
:
1081 return XCB_RENDER_PICT_OP_ADD
;
1082 case CAIRO_OPERATOR_SATURATE
:
1083 return XCB_RENDER_PICT_OP_SATURATE
;
1085 return XCB_RENDER_PICT_OP_OVER
;
1089 static cairo_int_status_t
1090 _cairo_xcb_surface_composite (cairo_operator_t op
,
1091 cairo_pattern_t
*src_pattern
,
1092 cairo_pattern_t
*mask_pattern
,
1101 unsigned int height
)
1103 cairo_surface_attributes_t src_attr
, mask_attr
;
1104 cairo_xcb_surface_t
*dst
= abstract_dst
;
1105 cairo_xcb_surface_t
*src
;
1106 cairo_xcb_surface_t
*mask
;
1107 cairo_int_status_t status
;
1108 composite_operation_t operation
;
1110 cairo_bool_t is_integer_translation
;
1112 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst
))
1113 return CAIRO_INT_STATUS_UNSUPPORTED
;
1115 operation
= _categorize_composite_operation (dst
, op
, src_pattern
,
1116 mask_pattern
!= NULL
);
1117 if (operation
== DO_UNSUPPORTED
)
1118 return CAIRO_INT_STATUS_UNSUPPORTED
;
1120 status
= _cairo_pattern_acquire_surfaces (src_pattern
, mask_pattern
,
1125 (cairo_surface_t
**) &src
,
1126 (cairo_surface_t
**) &mask
,
1127 &src_attr
, &mask_attr
);
1131 operation
= _recategorize_composite_operation (dst
, op
, src
, &src_attr
,
1132 mask_pattern
!= NULL
);
1133 if (operation
== DO_UNSUPPORTED
) {
1134 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1138 status
= _cairo_xcb_surface_set_attributes (src
, &src_attr
);
1145 _cairo_xcb_surface_ensure_dst_picture (dst
);
1147 status
= _cairo_xcb_surface_set_attributes (mask
, &mask_attr
);
1151 xcb_render_composite (dst
->dpy
,
1152 _render_operator (op
),
1156 src_x
+ src_attr
.x_offset
,
1157 src_y
+ src_attr
.y_offset
,
1158 mask_x
+ mask_attr
.x_offset
,
1159 mask_y
+ mask_attr
.y_offset
,
1163 static xcb_render_picture_t maskpict
= { XCB_NONE
};
1165 xcb_render_composite (dst
->dpy
,
1166 _render_operator (op
),
1170 src_x
+ src_attr
.x_offset
,
1171 src_y
+ src_attr
.y_offset
,
1179 _cairo_xcb_surface_ensure_gc (dst
);
1180 xcb_copy_area (dst
->dpy
,
1184 src_x
+ src_attr
.x_offset
,
1185 src_y
+ src_attr
.y_offset
,
1191 /* This case is only used for bug fallbacks, though it is theoretically
1192 * applicable to the case where we don't have the RENDER extension as
1195 * We've checked that we have a repeating unscaled source in
1196 * _recategorize_composite_operation.
1199 _cairo_xcb_surface_ensure_gc (dst
);
1200 is_integer_translation
=
1201 _cairo_matrix_is_integer_translation (&src_attr
.matrix
, &itx
, &ity
);
1202 assert (is_integer_translation
== TRUE
);
1204 uint32_t mask
= XCB_GC_FILL_STYLE
| XCB_GC_TILE
1205 | XCB_GC_TILE_STIPPLE_ORIGIN_X
1206 | XCB_GC_TILE_STIPPLE_ORIGIN_Y
;
1207 uint32_t values
[] = {
1208 XCB_FILL_STYLE_TILED
, src
->drawable
,
1209 - (itx
+ src_attr
.x_offset
),
1210 - (ity
+ src_attr
.y_offset
)
1212 xcb_rectangle_t rect
= { dst_x
, dst_y
, width
, height
};
1214 xcb_change_gc( dst
->dpy
, dst
->gc
, mask
, values
);
1215 xcb_poly_fill_rectangle(dst
->dpy
, dst
->drawable
, dst
->gc
, 1, &rect
);
1219 case DO_UNSUPPORTED
:
1224 if (!_cairo_operator_bounded_by_source (op
))
1225 status
= _cairo_surface_composite_fixup_unbounded (&dst
->base
,
1226 &src_attr
, src
->width
, src
->height
,
1227 mask
? &mask_attr
: NULL
,
1228 mask
? mask
->width
: 0,
1229 mask
? mask
->height
: 0,
1232 dst_x
, dst_y
, width
, height
);
1236 _cairo_pattern_release_surface (mask_pattern
, &mask
->base
, &mask_attr
);
1238 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
1243 static cairo_int_status_t
1244 _cairo_xcb_surface_fill_rectangles (void *abstract_surface
,
1245 cairo_operator_t op
,
1246 const cairo_color_t
* color
,
1247 cairo_rectangle_int_t
*rects
,
1250 cairo_xcb_surface_t
*surface
= abstract_surface
;
1251 xcb_render_color_t render_color
;
1252 xcb_rectangle_t static_xrects
[16];
1253 xcb_rectangle_t
*xrects
= static_xrects
;
1256 if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface
))
1257 return CAIRO_INT_STATUS_UNSUPPORTED
;
1259 render_color
.red
= color
->red_short
;
1260 render_color
.green
= color
->green_short
;
1261 render_color
.blue
= color
->blue_short
;
1262 render_color
.alpha
= color
->alpha_short
;
1264 if (num_rects
> ARRAY_LENGTH(static_xrects
)) {
1265 xrects
= _cairo_malloc_ab (num_rects
, sizeof(xcb_rectangle_t
));
1267 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1270 for (i
= 0; i
< num_rects
; i
++) {
1271 xrects
[i
].x
= rects
[i
].x
;
1272 xrects
[i
].y
= rects
[i
].y
;
1273 xrects
[i
].width
= rects
[i
].width
;
1274 xrects
[i
].height
= rects
[i
].height
;
1277 _cairo_xcb_surface_ensure_dst_picture (surface
);
1278 xcb_render_fill_rectangles (surface
->dpy
,
1279 _render_operator (op
),
1280 surface
->dst_picture
,
1281 render_color
, num_rects
, xrects
);
1283 if (xrects
!= static_xrects
)
1286 return CAIRO_STATUS_SUCCESS
;
1289 /* Creates an A8 picture of size @width x @height, initialized with @color
1291 static xcb_render_picture_t
1292 _create_a8_picture (cairo_xcb_surface_t
*surface
,
1293 xcb_render_color_t
*color
,
1296 cairo_bool_t repeat
)
1298 uint32_t values
[] = { TRUE
};
1299 uint32_t mask
= repeat
? XCB_RENDER_CP_REPEAT
: 0;
1301 xcb_pixmap_t pixmap
= xcb_generate_id (surface
->dpy
);
1302 xcb_render_picture_t picture
= xcb_generate_id (surface
->dpy
);
1304 xcb_render_pictforminfo_t
*format
1305 = _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface
->dpy
, CAIRO_FORMAT_A8
);
1306 xcb_rectangle_t rect
= { 0, 0, width
, height
};
1308 xcb_create_pixmap (surface
->dpy
, 8, pixmap
, surface
->drawable
,
1309 width
<= 0 ? 1 : width
,
1310 height
<= 0 ? 1 : height
);
1311 xcb_render_create_picture (surface
->dpy
, picture
, pixmap
, format
->id
, mask
, values
);
1312 xcb_render_fill_rectangles (surface
->dpy
, XCB_RENDER_PICT_OP_SRC
, picture
, *color
, 1, &rect
);
1313 xcb_free_pixmap (surface
->dpy
, pixmap
);
1318 /* Creates a temporary mask for the trapezoids covering the area
1319 * [@dst_x, @dst_y, @width, @height] of the destination surface.
1321 static cairo_status_t
1322 _create_trapezoid_mask (cairo_xcb_surface_t
*dst
,
1323 cairo_trapezoid_t
*traps
,
1329 xcb_render_pictforminfo_t
*pict_format
,
1330 xcb_render_picture_t
*mask_picture_out
)
1332 xcb_render_color_t transparent
= { 0, 0, 0, 0 };
1333 xcb_render_color_t solid
= { 0xffff, 0xffff, 0xffff, 0xffff };
1334 xcb_render_picture_t mask_picture
, solid_picture
;
1335 xcb_render_trapezoid_t
*offset_traps
;
1338 /* This would be considerably simpler using XRenderAddTraps(), but since
1339 * we are only using this in the unbounded-operator case, we stick with
1340 * XRenderCompositeTrapezoids, which is available on older versions
1341 * of RENDER rather than conditionalizing. We should still hit an
1342 * optimization that avoids creating another intermediate surface on
1343 * the servers that have XRenderAddTraps().
1345 mask_picture
= _create_a8_picture (dst
, &transparent
, width
, height
, FALSE
);
1346 solid_picture
= _create_a8_picture (dst
, &solid
, width
, height
, TRUE
);
1348 offset_traps
= _cairo_malloc_ab (num_traps
, sizeof (xcb_render_trapezoid_t
));
1349 if (offset_traps
== NULL
)
1350 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1352 for (i
= 0; i
< num_traps
; i
++) {
1353 offset_traps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
) - 0x10000 * dst_y
;
1354 offset_traps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
) - 0x10000 * dst_y
;
1355 offset_traps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
) - 0x10000 * dst_x
;
1356 offset_traps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
) - 0x10000 * dst_y
;
1357 offset_traps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
) - 0x10000 * dst_x
;
1358 offset_traps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
) - 0x10000 * dst_y
;
1359 offset_traps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
) - 0x10000 * dst_x
;
1360 offset_traps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
) - 0x10000 * dst_y
;
1361 offset_traps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
) - 0x10000 * dst_x
;
1362 offset_traps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
) - 0x10000 * dst_y
;
1365 xcb_render_trapezoids (dst
->dpy
, XCB_RENDER_PICT_OP_ADD
,
1366 solid_picture
, mask_picture
,
1369 num_traps
, offset_traps
);
1371 xcb_render_free_picture (dst
->dpy
, solid_picture
);
1372 free (offset_traps
);
1374 *mask_picture_out
= mask_picture
;
1375 return CAIRO_STATUS_SUCCESS
;
1378 static cairo_int_status_t
1379 _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op
,
1380 cairo_pattern_t
*pattern
,
1382 cairo_antialias_t antialias
,
1388 unsigned int height
,
1389 cairo_trapezoid_t
*traps
,
1392 cairo_surface_attributes_t attributes
;
1393 cairo_xcb_surface_t
*dst
= abstract_dst
;
1394 cairo_xcb_surface_t
*src
;
1395 cairo_int_status_t status
;
1396 composite_operation_t operation
;
1397 int render_reference_x
, render_reference_y
;
1398 int render_src_x
, render_src_y
;
1400 xcb_render_pictforminfo_t
*render_format
;
1402 if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst
))
1403 return CAIRO_INT_STATUS_UNSUPPORTED
;
1405 operation
= _categorize_composite_operation (dst
, op
, pattern
, TRUE
);
1406 if (operation
== DO_UNSUPPORTED
)
1407 return CAIRO_INT_STATUS_UNSUPPORTED
;
1409 status
= _cairo_pattern_acquire_surface (pattern
, &dst
->base
,
1410 src_x
, src_y
, width
, height
,
1411 (cairo_surface_t
**) &src
,
1416 operation
= _recategorize_composite_operation (dst
, op
, src
, &attributes
, TRUE
);
1417 if (operation
== DO_UNSUPPORTED
) {
1418 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1422 switch (antialias
) {
1423 case CAIRO_ANTIALIAS_NONE
:
1424 cairo_format
= CAIRO_FORMAT_A1
;
1426 case CAIRO_ANTIALIAS_GRAY
:
1427 case CAIRO_ANTIALIAS_SUBPIXEL
:
1428 case CAIRO_ANTIALIAS_DEFAULT
:
1430 cairo_format
= CAIRO_FORMAT_A8
;
1433 render_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dst
->dpy
, cairo_format
);
1434 /* XXX: what to do if render_format is null? */
1436 if (traps
[0].left
.p1
.y
< traps
[0].left
.p2
.y
) {
1437 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.x
);
1438 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.y
);
1440 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.x
);
1441 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.y
);
1444 render_src_x
= src_x
+ render_reference_x
- dst_x
;
1445 render_src_y
= src_y
+ render_reference_y
- dst_y
;
1447 _cairo_xcb_surface_ensure_dst_picture (dst
);
1448 status
= _cairo_xcb_surface_set_attributes (src
, &attributes
);
1452 if (!_cairo_operator_bounded_by_mask (op
)) {
1453 /* xcb_render_composite+trapezoids() creates a mask only large enough for the
1454 * trapezoids themselves, but if the operator is unbounded, then we need
1455 * to actually composite all the way out to the bounds, so we create
1456 * the mask and composite ourselves. There actually would
1457 * be benefit to doing this in all cases, since RENDER implementations
1458 * will frequently create a too temporary big mask, ignoring destination
1459 * bounds and clip. (xcb_render_add_traps() could be used to make creating
1460 * the mask somewhat cheaper.)
1462 xcb_render_picture_t mask_picture
= 0; /* silence compiler */
1464 status
= _create_trapezoid_mask (dst
, traps
, num_traps
,
1465 dst_x
, dst_y
, width
, height
,
1471 xcb_render_composite (dst
->dpy
,
1472 _render_operator (op
),
1476 src_x
+ attributes
.x_offset
,
1477 src_y
+ attributes
.y_offset
,
1482 xcb_render_free_picture (dst
->dpy
, mask_picture
);
1484 status
= _cairo_surface_composite_shape_fixup_unbounded (&dst
->base
,
1485 &attributes
, src
->width
, src
->height
,
1489 dst_x
, dst_y
, width
, height
);
1492 xcb_render_trapezoid_t xtraps_stack
[16];
1493 xcb_render_trapezoid_t
*xtraps
= xtraps_stack
;
1496 if (num_traps
> ARRAY_LENGTH(xtraps_stack
)) {
1497 xtraps
= _cairo_malloc_ab (num_traps
, sizeof(xcb_render_trapezoid_t
));
1498 if (xtraps
== NULL
) {
1499 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1504 for (i
= 0; i
< num_traps
; i
++) {
1505 xtraps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
);
1506 xtraps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
);
1507 xtraps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
);
1508 xtraps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
);
1509 xtraps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
);
1510 xtraps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
);
1511 xtraps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
);
1512 xtraps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
);
1513 xtraps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
);
1514 xtraps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
);
1517 xcb_render_trapezoids (dst
->dpy
,
1518 _render_operator (op
),
1519 src
->src_picture
, dst
->dst_picture
,
1521 render_src_x
+ attributes
.x_offset
,
1522 render_src_y
+ attributes
.y_offset
,
1525 if (xtraps
!= xtraps_stack
)
1530 _cairo_pattern_release_surface (pattern
, &src
->base
, &attributes
);
1535 static cairo_int_status_t
1536 _cairo_xcb_surface_set_clip_region (void *abstract_surface
,
1537 cairo_region_t
*region
)
1539 cairo_xcb_surface_t
*surface
= abstract_surface
;
1541 if (surface
->clip_rects
) {
1542 free (surface
->clip_rects
);
1543 surface
->clip_rects
= NULL
;
1546 surface
->have_clip_rects
= FALSE
;
1547 surface
->num_clip_rects
= 0;
1549 if (region
== NULL
) {
1550 uint32_t none
[] = { XCB_NONE
};
1552 xcb_change_gc (surface
->dpy
, surface
->gc
, XCB_GC_CLIP_MASK
, none
);
1554 if (surface
->xrender_format
.id
!= XCB_NONE
&& surface
->dst_picture
)
1555 xcb_render_change_picture (surface
->dpy
, surface
->dst_picture
,
1556 XCB_RENDER_CP_CLIP_MASK
, none
);
1558 cairo_box_int_t
*boxes
;
1559 cairo_status_t status
;
1560 xcb_rectangle_t
*rects
= NULL
;
1563 status
= _cairo_region_get_boxes (region
, &n_boxes
, &boxes
);
1568 rects
= _cairo_malloc_ab (n_boxes
, sizeof(xcb_rectangle_t
));
1569 if (rects
== NULL
) {
1570 _cairo_region_boxes_fini (region
, boxes
);
1571 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1577 for (i
= 0; i
< n_boxes
; i
++) {
1578 rects
[i
].x
= boxes
[i
].p1
.x
;
1579 rects
[i
].y
= boxes
[i
].p1
.y
;
1580 rects
[i
].width
= boxes
[i
].p2
.x
- boxes
[i
].p1
.x
;
1581 rects
[i
].height
= boxes
[i
].p2
.y
- boxes
[i
].p1
.y
;
1584 _cairo_region_boxes_fini (region
, boxes
);
1586 surface
->have_clip_rects
= TRUE
;
1587 surface
->clip_rects
= rects
;
1588 surface
->num_clip_rects
= n_boxes
;
1591 _cairo_xcb_surface_set_gc_clip_rects (surface
);
1593 if (surface
->dst_picture
)
1594 _cairo_xcb_surface_set_picture_clip_rects (surface
);
1597 return CAIRO_STATUS_SUCCESS
;
1600 static cairo_int_status_t
1601 _cairo_xcb_surface_get_extents (void *abstract_surface
,
1602 cairo_rectangle_int_t
*rectangle
)
1604 cairo_xcb_surface_t
*surface
= abstract_surface
;
1609 rectangle
->width
= surface
->width
;
1610 rectangle
->height
= surface
->height
;
1612 return CAIRO_STATUS_SUCCESS
;
1615 /* XXX: _cairo_xcb_surface_get_font_options */
1618 _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
);
1621 _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
1622 cairo_scaled_font_t
*scaled_font
);
1624 static cairo_int_status_t
1625 _cairo_xcb_surface_show_glyphs (void *abstract_dst
,
1626 cairo_operator_t op
,
1627 cairo_pattern_t
*src_pattern
,
1628 cairo_glyph_t
*glyphs
,
1630 cairo_scaled_font_t
*scaled_font
,
1631 int *remaining_glyphs
);
1634 _cairo_xcb_surface_is_similar (void *surface_a
,
1636 cairo_content_t content
)
1638 cairo_xcb_surface_t
*a
= surface_a
;
1639 cairo_xcb_surface_t
*b
= surface_b
;
1640 xcb_render_pictforminfo_t
*xrender_format
;
1642 /* XXX: disable caching by the solid pattern cache until we implement
1643 * display notification to avoid issuing xcb calls from the wrong thread
1644 * or accessing the surface after the Display has been closed.
1648 if (! _cairo_xcb_surface_same_screen (a
, b
))
1651 /* now check that the target is a similar format */
1652 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (b
->dpy
,
1653 _cairo_format_from_content (content
));
1655 return a
->xrender_format
.id
== xrender_format
->id
;
1658 static cairo_status_t
1659 _cairo_xcb_surface_reset (void *abstract_surface
)
1661 cairo_xcb_surface_t
*surface
= abstract_surface
;
1662 cairo_status_t status
;
1664 status
= _cairo_xcb_surface_set_clip_region (surface
, NULL
);
1668 return CAIRO_STATUS_SUCCESS
;
1672 /* XXX: move this to the bottom of the file, XCB and Xlib */
1674 static const cairo_surface_backend_t cairo_xcb_surface_backend
= {
1675 CAIRO_SURFACE_TYPE_XCB
,
1676 _cairo_xcb_surface_create_similar
,
1677 _cairo_xcb_surface_finish
,
1678 _cairo_xcb_surface_acquire_source_image
,
1679 _cairo_xcb_surface_release_source_image
,
1680 _cairo_xcb_surface_acquire_dest_image
,
1681 _cairo_xcb_surface_release_dest_image
,
1682 _cairo_xcb_surface_clone_similar
,
1683 _cairo_xcb_surface_composite
,
1684 _cairo_xcb_surface_fill_rectangles
,
1685 _cairo_xcb_surface_composite_trapezoids
,
1686 NULL
, /* copy_page */
1687 NULL
, /* show_page */
1688 _cairo_xcb_surface_set_clip_region
,
1689 NULL
, /* intersect_clip_path */
1690 _cairo_xcb_surface_get_extents
,
1691 NULL
, /* old_show_glyphs */
1692 NULL
, /* get_font_options */
1694 NULL
, /* mark_dirty_rectangle */
1695 _cairo_xcb_surface_scaled_font_fini
,
1696 _cairo_xcb_surface_scaled_glyph_fini
,
1702 _cairo_xcb_surface_show_glyphs
,
1703 NULL
, /* snapshot */
1705 _cairo_xcb_surface_is_similar
,
1707 _cairo_xcb_surface_reset
1711 * _cairo_surface_is_xcb:
1712 * @surface: a #cairo_surface_t
1714 * Checks if a surface is a #cairo_xcb_surface_t
1716 * Return value: True if the surface is an xcb surface
1719 _cairo_surface_is_xcb (cairo_surface_t
*surface
)
1721 return surface
->backend
== &cairo_xcb_surface_backend
;
1724 static cairo_surface_t
*
1725 _cairo_xcb_surface_create_internal (xcb_connection_t
*dpy
,
1726 xcb_drawable_t drawable
,
1727 xcb_screen_t
*screen
,
1728 xcb_visualtype_t
*visual
,
1729 xcb_render_pictforminfo_t
*xrender_format
,
1734 cairo_xcb_surface_t
*surface
;
1735 const xcb_render_query_version_reply_t
*r
;
1737 surface
= malloc (sizeof (cairo_xcb_surface_t
));
1738 if (surface
== NULL
)
1739 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1741 if (xrender_format
) {
1742 depth
= xrender_format
->depth
;
1743 } else if (visual
) {
1744 xcb_depth_iterator_t depths
;
1745 xcb_visualtype_iterator_t visuals
;
1747 /* This is ugly, but we have to walk over all visuals
1748 * for the screen to find the depth.
1750 depths
= xcb_screen_allowed_depths_iterator(screen
);
1751 for(; depths
.rem
; xcb_depth_next(&depths
))
1753 visuals
= xcb_depth_visuals_iterator(depths
.data
);
1754 for(; visuals
.rem
; xcb_visualtype_next(&visuals
))
1756 if(visuals
.data
->visual_id
== visual
->visual_id
)
1758 depth
= depths
.data
->depth
;
1767 r
= xcb_render_util_query_version(dpy
);
1769 surface
->render_major
= r
->major_version
;
1770 surface
->render_minor
= r
->minor_version
;
1772 surface
->render_major
= -1;
1773 surface
->render_minor
= -1;
1776 if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface
)) {
1777 if (!xrender_format
) {
1779 const xcb_render_query_pict_formats_reply_t
*formats
;
1780 xcb_render_pictvisual_t
*pict_visual
;
1781 formats
= xcb_render_util_query_formats (dpy
);
1782 pict_visual
= xcb_render_util_find_visual_format (formats
, visual
->visual_id
);
1784 xcb_render_pictforminfo_t
template;
1785 template.id
= pict_visual
->format
;
1786 xrender_format
= xcb_render_util_find_format (formats
, XCB_PICT_FORMAT_ID
, &template, 0);
1788 } else if (depth
== 1) {
1789 xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy
, CAIRO_FORMAT_A1
);
1793 xrender_format
= NULL
;
1796 _cairo_surface_init (&surface
->base
, &cairo_xcb_surface_backend
,
1797 _xcb_render_format_to_content (xrender_format
));
1801 surface
->gc
= XCB_NONE
;
1802 surface
->drawable
= drawable
;
1803 surface
->screen
= screen
;
1804 surface
->owns_pixmap
= FALSE
;
1805 surface
->use_pixmap
= 0;
1806 surface
->width
= width
;
1807 surface
->height
= height
;
1809 /* XXX: set buggy_repeat based on ServerVendor and VendorRelease */
1811 surface
->dst_picture
= XCB_NONE
;
1812 surface
->src_picture
= XCB_NONE
;
1814 surface
->visual
= visual
;
1815 surface
->xrender_format
.id
= XCB_NONE
;
1816 if (xrender_format
) surface
->xrender_format
= *xrender_format
;
1817 surface
->depth
= depth
;
1819 surface
->have_clip_rects
= FALSE
;
1820 surface
->clip_rects
= NULL
;
1821 surface
->num_clip_rects
= 0;
1823 return (cairo_surface_t
*) surface
;
1826 static xcb_screen_t
*
1827 _cairo_xcb_screen_from_visual (xcb_connection_t
*c
, xcb_visualtype_t
*visual
)
1829 xcb_depth_iterator_t d
;
1830 xcb_screen_iterator_t s
= xcb_setup_roots_iterator(xcb_get_setup(c
));
1831 for (; s
.rem
; xcb_screen_next(&s
))
1833 if (s
.data
->root_visual
== visual
->visual_id
)
1836 d
= xcb_screen_allowed_depths_iterator(s
.data
);
1837 for (; d
.rem
; xcb_depth_next(&d
))
1839 xcb_visualtype_iterator_t v
= xcb_depth_visuals_iterator(d
.data
);
1840 for (; v
.rem
; xcb_visualtype_next(&v
))
1842 if (v
.data
->visual_id
== visual
->visual_id
)
1851 * cairo_xcb_surface_create:
1852 * @c: an XCB connection
1853 * @drawable: an XCB drawable
1854 * @visual: the visual to use for drawing to @drawable. The depth
1855 * of the visual must match the depth of the drawable.
1856 * Currently, only TrueColor visuals are fully supported.
1857 * @width: the current width of @drawable.
1858 * @height: the current height of @drawable.
1860 * Creates an XCB surface that draws to the given drawable.
1861 * The way that colors are represented in the drawable is specified
1862 * by the provided visual.
1864 * Note: If @drawable is a window, then the function
1865 * cairo_xcb_surface_set_size() must be called whenever the size of the
1868 * Return value: the newly created surface
1871 cairo_xcb_surface_create (xcb_connection_t
*c
,
1872 xcb_drawable_t drawable
,
1873 xcb_visualtype_t
*visual
,
1877 xcb_screen_t
*screen
= _cairo_xcb_screen_from_visual (c
, visual
);
1880 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
1882 return _cairo_xcb_surface_create_internal (c
, drawable
, screen
,
1888 * cairo_xcb_surface_create_for_bitmap:
1889 * @c: an XCB connection
1890 * @bitmap: an XCB Pixmap (a depth-1 pixmap)
1891 * @screen: an XCB Screen
1892 * @width: the current width of @bitmap
1893 * @height: the current height of @bitmap
1895 * Creates an XCB surface that draws to the given bitmap.
1896 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1898 * Return value: the newly created surface
1901 cairo_xcb_surface_create_for_bitmap (xcb_connection_t
*c
,
1902 xcb_pixmap_t bitmap
,
1903 xcb_screen_t
*screen
,
1907 return _cairo_xcb_surface_create_internal (c
, bitmap
, screen
,
1913 * cairo_xcb_surface_create_with_xrender_format:
1914 * @c: an XCB connection
1915 * @drawable: an XCB drawable
1916 * @screen: the XCB screen associated with @drawable
1917 * @format: the picture format to use for drawing to @drawable. The
1918 * depth of @format mush match the depth of the drawable.
1919 * @width: the current width of @drawable
1920 * @height: the current height of @drawable
1922 * Creates an XCB surface that draws to the given drawable.
1923 * The way that colors are represented in the drawable is specified
1924 * by the provided picture format.
1926 * Note: If @drawable is a Window, then the function
1927 * cairo_xcb_surface_set_size() must be called whenever the size of the
1930 * Return value: the newly created surface.
1933 cairo_xcb_surface_create_with_xrender_format (xcb_connection_t
*c
,
1934 xcb_drawable_t drawable
,
1935 xcb_screen_t
*screen
,
1936 xcb_render_pictforminfo_t
*format
,
1940 return _cairo_xcb_surface_create_internal (c
, drawable
, screen
,
1944 slim_hidden_def (cairo_xcb_surface_create_with_xrender_format
);
1947 * cairo_xcb_surface_set_size:
1948 * @surface: a #cairo_surface_t for the XCB backend
1949 * @width: the new width of the surface
1950 * @height: the new height of the surface
1952 * Informs cairo of the new size of the XCB drawable underlying the
1953 * surface. For a surface created for a window (rather than a pixmap),
1954 * this function must be called each time the size of the window
1955 * changes. (For a subwindow, you are normally resizing the window
1956 * yourself, but for a toplevel window, it is necessary to listen for
1957 * ConfigureNotify events.)
1959 * A pixmap can never change size, so it is never necessary to call
1960 * this function on a surface created for a pixmap.
1963 cairo_xcb_surface_set_size (cairo_surface_t
*abstract_surface
,
1967 cairo_xcb_surface_t
*surface
= (cairo_xcb_surface_t
*) abstract_surface
;
1968 cairo_status_t status_ignored
;
1970 if (! _cairo_surface_is_xcb (abstract_surface
)) {
1971 status_ignored
= _cairo_surface_set_error (abstract_surface
,
1972 CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
1976 surface
->width
= width
;
1977 surface
->height
= height
;
1981 * Glyph rendering support
1984 typedef struct _cairo_xcb_surface_font_private
{
1985 xcb_connection_t
*dpy
;
1986 xcb_render_glyphset_t glyphset
;
1987 cairo_format_t format
;
1988 xcb_render_pictforminfo_t
*xrender_format
;
1989 } cairo_xcb_surface_font_private_t
;
1991 static cairo_status_t
1992 _cairo_xcb_surface_font_init (xcb_connection_t
*dpy
,
1993 cairo_scaled_font_t
*scaled_font
,
1994 cairo_format_t format
)
1996 cairo_xcb_surface_font_private_t
*font_private
;
1998 font_private
= malloc (sizeof (cairo_xcb_surface_font_private_t
));
2000 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2002 font_private
->dpy
= dpy
;
2003 font_private
->format
= format
;
2004 font_private
->xrender_format
= _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy
, format
);
2005 font_private
->glyphset
= xcb_generate_id(dpy
);
2006 xcb_render_create_glyph_set (dpy
, font_private
->glyphset
, font_private
->xrender_format
->id
);
2008 scaled_font
->surface_private
= font_private
;
2009 scaled_font
->surface_backend
= &cairo_xcb_surface_backend
;
2010 return CAIRO_STATUS_SUCCESS
;
2014 _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
2016 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2019 xcb_render_free_glyph_set (font_private
->dpy
, font_private
->glyphset
);
2020 free (font_private
);
2025 _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
2026 cairo_scaled_font_t
*scaled_font
)
2028 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2030 if (font_private
!= NULL
&& scaled_glyph
->surface_private
!= NULL
) {
2031 xcb_render_glyph_t glyph_index
= _cairo_scaled_glyph_index(scaled_glyph
);
2032 xcb_render_free_glyphs (font_private
->dpy
,
2033 font_private
->glyphset
,
2039 _native_byte_order_lsb (void)
2043 return *((char *) &x
) == 1;
2046 static cairo_status_t
2047 _cairo_xcb_surface_add_glyph (xcb_connection_t
*dpy
,
2048 cairo_scaled_font_t
*scaled_font
,
2049 cairo_scaled_glyph_t
*scaled_glyph
)
2051 xcb_render_glyphinfo_t glyph_info
;
2052 xcb_render_glyph_t glyph_index
;
2053 unsigned char *data
;
2054 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
2055 cairo_xcb_surface_font_private_t
*font_private
;
2056 cairo_image_surface_t
*glyph_surface
= scaled_glyph
->surface
;
2058 if (scaled_font
->surface_private
== NULL
) {
2059 status
= _cairo_xcb_surface_font_init (dpy
, scaled_font
,
2060 glyph_surface
->format
);
2064 font_private
= scaled_font
->surface_private
;
2066 /* If the glyph format does not match the font format, then we
2067 * create a temporary surface for the glyph image with the font's
2070 if (glyph_surface
->format
!= font_private
->format
) {
2072 cairo_surface_t
*tmp_surface
;
2073 double x_offset
, y_offset
;
2075 tmp_surface
= cairo_image_surface_create (font_private
->format
,
2076 glyph_surface
->width
,
2077 glyph_surface
->height
);
2078 cr
= cairo_create (tmp_surface
);
2079 cairo_surface_get_device_offset (&glyph_surface
->base
, &x_offset
, &y_offset
);
2080 cairo_set_source_surface (cr
, &glyph_surface
->base
, x_offset
, y_offset
);
2081 cairo_set_operator (cr
, CAIRO_OPERATOR_SOURCE
);
2084 status
= cairo_status (cr
);
2088 tmp_surface
->device_transform
= glyph_surface
->base
.device_transform
;
2089 tmp_surface
->device_transform_inverse
= glyph_surface
->base
.device_transform_inverse
;
2091 glyph_surface
= (cairo_image_surface_t
*) tmp_surface
;
2097 /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
2098 glyph_info
.x
= _cairo_lround (glyph_surface
->base
.device_transform
.x0
);
2099 glyph_info
.y
= _cairo_lround (glyph_surface
->base
.device_transform
.y0
);
2100 glyph_info
.width
= glyph_surface
->width
;
2101 glyph_info
.height
= glyph_surface
->height
;
2102 glyph_info
.x_off
= 0;
2103 glyph_info
.y_off
= 0;
2105 data
= glyph_surface
->data
;
2107 /* flip formats around */
2108 switch (scaled_glyph
->surface
->format
) {
2109 case CAIRO_FORMAT_A1
:
2110 /* local bitmaps are always stored with bit == byte */
2111 if (_native_byte_order_lsb() != (xcb_get_setup(dpy
)->bitmap_format_bit_order
== XCB_IMAGE_ORDER_LSB_FIRST
)) {
2112 int c
= glyph_surface
->stride
* glyph_surface
->height
;
2114 unsigned char *new, *n
;
2118 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2126 b
= ((b
<< 1) & 0xaa) | ((b
>> 1) & 0x55);
2127 b
= ((b
<< 2) & 0xcc) | ((b
>> 2) & 0x33);
2128 b
= ((b
<< 4) & 0xf0) | ((b
>> 4) & 0x0f);
2134 case CAIRO_FORMAT_A8
:
2136 case CAIRO_FORMAT_ARGB32
:
2137 if (_native_byte_order_lsb() != (xcb_get_setup(dpy
)->image_byte_order
== XCB_IMAGE_ORDER_LSB_FIRST
)) {
2138 unsigned int c
= glyph_surface
->stride
* glyph_surface
->height
;
2140 unsigned char *new, *n
;
2144 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2162 case CAIRO_FORMAT_RGB24
:
2167 /* XXX assume X server wants pixman padding. Xft assumes this as well */
2169 glyph_index
= _cairo_scaled_glyph_index (scaled_glyph
);
2171 xcb_render_add_glyphs (dpy
, font_private
->glyphset
,
2172 1, &glyph_index
, &glyph_info
,
2173 glyph_surface
->stride
* glyph_surface
->height
,
2176 if (data
!= glyph_surface
->data
)
2180 if (glyph_surface
!= scaled_glyph
->surface
)
2181 cairo_surface_destroy (&glyph_surface
->base
);
2186 #define N_STACK_BUF 1024
2188 static cairo_status_t
2189 _cairo_xcb_surface_show_glyphs_8 (cairo_xcb_surface_t
*dst
,
2190 cairo_operator_t op
,
2191 cairo_xcb_surface_t
*src
,
2192 int src_x_offset
, int src_y_offset
,
2193 const cairo_glyph_t
*glyphs
,
2195 cairo_scaled_font_t
*scaled_font
)
2197 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2198 xcb_render_util_composite_text_stream_t
*stream
;
2201 int lastX
= 0, lastY
= 0;
2204 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2206 for (i
= 0; i
< num_glyphs
; ++i
) {
2207 thisX
= _cairo_lround (glyphs
[i
].x
);
2208 thisY
= _cairo_lround (glyphs
[i
].y
);
2209 glyph
= glyphs
[i
].index
;
2210 xcb_render_util_glyphs_8 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2215 xcb_render_util_composite_text (dst
->dpy
,
2216 _render_operator (op
),
2219 font_private
->xrender_format
->id
,
2220 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2221 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2224 xcb_render_util_composite_text_free (stream
);
2226 return CAIRO_STATUS_SUCCESS
;
2229 static cairo_status_t
2230 _cairo_xcb_surface_show_glyphs_16 (cairo_xcb_surface_t
*dst
,
2231 cairo_operator_t op
,
2232 cairo_xcb_surface_t
*src
,
2233 int src_x_offset
, int src_y_offset
,
2234 const cairo_glyph_t
*glyphs
,
2236 cairo_scaled_font_t
*scaled_font
)
2238 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2239 xcb_render_util_composite_text_stream_t
*stream
;
2242 int lastX
= 0, lastY
= 0;
2245 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2247 for (i
= 0; i
< num_glyphs
; ++i
) {
2248 thisX
= _cairo_lround (glyphs
[i
].x
);
2249 thisY
= _cairo_lround (glyphs
[i
].y
);
2250 glyph
= glyphs
[i
].index
;
2251 xcb_render_util_glyphs_16 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2256 xcb_render_util_composite_text (dst
->dpy
,
2257 _render_operator (op
),
2260 font_private
->xrender_format
->id
,
2261 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2262 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2265 xcb_render_util_composite_text_free (stream
);
2267 return CAIRO_STATUS_SUCCESS
;
2270 static cairo_status_t
2271 _cairo_xcb_surface_show_glyphs_32 (cairo_xcb_surface_t
*dst
,
2272 cairo_operator_t op
,
2273 cairo_xcb_surface_t
*src
,
2274 int src_x_offset
, int src_y_offset
,
2275 const cairo_glyph_t
*glyphs
,
2277 cairo_scaled_font_t
*scaled_font
)
2279 cairo_xcb_surface_font_private_t
*font_private
= scaled_font
->surface_private
;
2280 xcb_render_util_composite_text_stream_t
*stream
;
2283 int lastX
= 0, lastY
= 0;
2286 stream
= xcb_render_util_composite_text_stream (font_private
->glyphset
, num_glyphs
, 0);
2288 for (i
= 0; i
< num_glyphs
; ++i
) {
2289 thisX
= _cairo_lround (glyphs
[i
].x
);
2290 thisY
= _cairo_lround (glyphs
[i
].y
);
2291 glyph
= glyphs
[i
].index
;
2292 xcb_render_util_glyphs_32 (stream
, thisX
- lastX
, thisY
- lastY
, 1, &glyph
);
2297 xcb_render_util_composite_text (dst
->dpy
,
2298 _render_operator (op
),
2301 font_private
->xrender_format
->id
,
2302 src_x_offset
+ _cairo_lround (glyphs
[0].x
),
2303 src_y_offset
+ _cairo_lround (glyphs
[0].y
),
2306 xcb_render_util_composite_text_free (stream
);
2308 return CAIRO_STATUS_SUCCESS
;
2311 typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t
)
2312 (cairo_xcb_surface_t
*, cairo_operator_t
, cairo_xcb_surface_t
*, int, int,
2313 const cairo_glyph_t
*, int, cairo_scaled_font_t
*);
2316 _cairo_xcb_surface_owns_font (cairo_xcb_surface_t
*dst
,
2317 cairo_scaled_font_t
*scaled_font
)
2319 cairo_xcb_surface_font_private_t
*font_private
;
2321 font_private
= scaled_font
->surface_private
;
2322 if ((scaled_font
->surface_backend
!= NULL
&&
2323 scaled_font
->surface_backend
!= &cairo_xcb_surface_backend
) ||
2324 (font_private
!= NULL
&& font_private
->dpy
!= dst
->dpy
))
2334 static cairo_status_t
2335 _cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t
*dst
,
2336 cairo_glyph_t
*glyphs
,
2338 cairo_scaled_font_t
*scaled_font
,
2339 cairo_operator_t op
,
2340 cairo_xcb_surface_t
*src
,
2341 cairo_surface_attributes_t
*attributes
,
2342 int *remaining_glyphs
)
2344 cairo_scaled_glyph_t
*scaled_glyph
;
2346 unsigned long max_index
= 0;
2347 cairo_status_t status
;
2348 cairo_glyph_t
*output_glyphs
;
2349 const cairo_glyph_t
*glyphs_chunk
;
2350 int glyphs_remaining
, chunk_size
, max_chunk_size
;
2351 cairo_xcb_surface_show_glyphs_func_t show_glyphs_func
;
2353 /* We make a copy of the glyphs so that we can elide any size-zero
2354 * glyphs to workaround an X server bug, (present in at least Xorg
2355 * 7.1 without EXA). */
2356 output_glyphs
= _cairo_malloc_ab (num_glyphs
, sizeof (cairo_glyph_t
));
2357 if (output_glyphs
== NULL
)
2358 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2360 for (i
= 0, o
= 0; i
< num_glyphs
; i
++) {
2361 if (glyphs
[i
].index
> max_index
)
2362 max_index
= glyphs
[i
].index
;
2363 status
= _cairo_scaled_glyph_lookup (scaled_font
,
2365 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
2368 free (output_glyphs
);
2372 /* Don't put any size-zero glyphs into output_glyphs to avoid
2373 * an X server bug which stops rendering glyphs after the
2374 * first size-zero glyph. */
2375 if (scaled_glyph
->surface
->width
&& scaled_glyph
->surface
->height
) {
2376 output_glyphs
[o
++] = glyphs
[i
];
2377 if (scaled_glyph
->surface_private
== NULL
) {
2378 _cairo_xcb_surface_add_glyph (dst
->dpy
, scaled_font
, scaled_glyph
);
2379 scaled_glyph
->surface_private
= (void *) 1;
2385 _cairo_xcb_surface_ensure_dst_picture (dst
);
2387 max_chunk_size
= xcb_get_maximum_request_length (dst
->dpy
);
2388 if (max_index
< 256) {
2389 /* XXX: these are all the same size! (28) */
2390 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_8_request_t
);
2391 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_8
;
2392 } else if (max_index
< 65536) {
2393 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_16_request_t
);
2394 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_16
;
2396 max_chunk_size
-= sizeof(xcb_render_composite_glyphs_32_request_t
);
2397 show_glyphs_func
= _cairo_xcb_surface_show_glyphs_32
;
2399 /* XXX: I think this is wrong; this is only the header size (2 longs) */
2400 /* but should also include the glyph (1 long) */
2401 /* max_chunk_size /= sz_xGlyphElt; */
2402 max_chunk_size
/= 3*sizeof(uint32_t);
2404 for (glyphs_remaining
= num_glyphs
, glyphs_chunk
= output_glyphs
;
2406 glyphs_remaining
-= chunk_size
, glyphs_chunk
+= chunk_size
)
2408 chunk_size
= MIN (glyphs_remaining
, max_chunk_size
);
2410 status
= show_glyphs_func (dst
, op
, src
,
2411 attributes
->x_offset
, attributes
->y_offset
,
2412 glyphs_chunk
, chunk_size
, scaled_font
);
2414 free (output_glyphs
);
2419 return CAIRO_STATUS_SUCCESS
;
2422 static cairo_int_status_t
2423 _cairo_xcb_surface_show_glyphs (void *abstract_dst
,
2424 cairo_operator_t op
,
2425 cairo_pattern_t
*src_pattern
,
2426 cairo_glyph_t
*glyphs
,
2428 cairo_scaled_font_t
*scaled_font
,
2429 int *remaining_glyphs
)
2431 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
2432 cairo_xcb_surface_t
*dst
= abstract_dst
;
2434 composite_operation_t operation
;
2435 cairo_surface_attributes_t attributes
;
2436 cairo_xcb_surface_t
*src
= NULL
;
2438 cairo_solid_pattern_t solid_pattern
;
2440 if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst
) || dst
->xrender_format
.id
== XCB_NONE
)
2441 return CAIRO_INT_STATUS_UNSUPPORTED
;
2443 /* Just let unbounded operators go through the fallback code
2444 * instead of trying to do the fixups here */
2445 if (!_cairo_operator_bounded_by_mask (op
))
2446 return CAIRO_INT_STATUS_UNSUPPORTED
;
2448 /* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs --
2449 * the solid source seems to be multiplied by the glyph mask, and
2450 * then the entire thing is copied to the destination surface,
2451 * including the fully transparent "background" of the rectangular
2453 if (op
== CAIRO_OPERATOR_SOURCE
&&
2454 !CAIRO_SURFACE_RENDER_AT_LEAST(dst
, 0, 11))
2455 return CAIRO_INT_STATUS_UNSUPPORTED
;
2457 /* We can only use our code if we either have no clip or
2458 * have a real native clip region set. If we're using
2459 * fallback clip masking, we have to go through the full
2462 if (dst
->base
.clip
&&
2463 (dst
->base
.clip
->mode
!= CAIRO_CLIP_MODE_REGION
||
2464 dst
->base
.clip
->surface
!= NULL
))
2465 return CAIRO_INT_STATUS_UNSUPPORTED
;
2467 operation
= _categorize_composite_operation (dst
, op
, src_pattern
, TRUE
);
2468 if (operation
== DO_UNSUPPORTED
)
2469 return CAIRO_INT_STATUS_UNSUPPORTED
;
2471 if (! _cairo_xcb_surface_owns_font (dst
, scaled_font
))
2472 return CAIRO_INT_STATUS_UNSUPPORTED
;
2474 /* After passing all those tests, we're now committed to rendering
2475 * these glyphs or to fail trying. We first upload any glyphs to
2476 * the X server that it doesn't have already, then we draw
2477 * them. We tie into the scaled_font's glyph cache and remove
2478 * glyphs from the X server when they are ejected from the
2479 * scaled_font cache.
2482 /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
2483 * the mask (the glyphs). This code below was executed as a side effect
2484 * of going through the _clip_and_composite fallback code for old_show_glyphs,
2485 * so PictOpClear was never used with CompositeText before.
2487 if (op
== CAIRO_OPERATOR_CLEAR
) {
2488 _cairo_pattern_init_solid (&solid_pattern
, CAIRO_COLOR_WHITE
,
2489 CAIRO_CONTENT_COLOR
);
2490 src_pattern
= &solid_pattern
.base
;
2491 op
= CAIRO_OPERATOR_DEST_OUT
;
2494 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
) {
2495 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
2497 (cairo_surface_t
**) &src
,
2500 cairo_rectangle_int_t glyph_extents
;
2502 status
= _cairo_scaled_font_glyph_device_extents (scaled_font
,
2509 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
2510 glyph_extents
.x
, glyph_extents
.y
,
2511 glyph_extents
.width
, glyph_extents
.height
,
2512 (cairo_surface_t
**) &src
,
2519 operation
= _recategorize_composite_operation (dst
, op
, src
, &attributes
, TRUE
);
2520 if (operation
== DO_UNSUPPORTED
) {
2521 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2525 status
= _cairo_xcb_surface_set_attributes (src
, &attributes
);
2529 /* Send all unsent glyphs to the server, and count the max of the glyph indices */
2530 _cairo_scaled_font_freeze_cache (scaled_font
);
2532 if (_cairo_xcb_surface_owns_font (dst
, scaled_font
))
2533 status
= _cairo_xcb_surface_emit_glyphs (dst
,
2541 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2542 _cairo_scaled_font_thaw_cache (scaled_font
);
2546 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &attributes
);
2547 if (src_pattern
== &solid_pattern
.base
)
2548 _cairo_pattern_fini (&solid_pattern
.base
);