1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Intel Corporation
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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.
29 * Chris Wilson <chris@chris-wilson.co.uk>
34 #include "cairo-xcb-private.h"
36 #include <xcb/xcbext.h>
39 _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t
*connection
,
41 xcb_drawable_t drawable
,
45 xcb_pixmap_t pixmap
= _cairo_xcb_connection_get_xid (connection
);
49 xcb_create_pixmap (connection
->xcb_connection
,
50 depth
, pixmap
, drawable
,
56 _cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t
*connection
,
59 xcb_free_pixmap (connection
->xcb_connection
, pixmap
);
60 _cairo_xcb_connection_put_xid (connection
, pixmap
);
64 _cairo_xcb_connection_create_gc (cairo_xcb_connection_t
*connection
,
65 xcb_drawable_t drawable
,
69 xcb_gcontext_t gc
= _cairo_xcb_connection_get_xid (connection
);
70 xcb_create_gc (connection
->xcb_connection
, gc
, drawable
,
76 _cairo_xcb_connection_free_gc (cairo_xcb_connection_t
*connection
,
79 xcb_free_gc (connection
->xcb_connection
, gc
);
80 _cairo_xcb_connection_put_xid (connection
, gc
);
84 _cairo_xcb_connection_change_gc (cairo_xcb_connection_t
*connection
,
89 xcb_change_gc (connection
->xcb_connection
, gc
,
94 _cairo_xcb_connection_copy_area (cairo_xcb_connection_t
*connection
,
105 xcb_copy_area (connection
->xcb_connection
, src
, dst
, gc
,
106 src_x
, src_y
, dst_x
, dst_y
, width
, height
);
110 _cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t
*connection
,
113 uint32_t num_rectangles
,
114 xcb_rectangle_t
*rectangles
)
116 xcb_poly_fill_rectangle (connection
->xcb_connection
, dst
, gc
,
117 num_rectangles
, rectangles
);
121 _cairo_xcb_connection_put_image (cairo_xcb_connection_t
*connection
,
132 const uint32_t req_size
= 18;
133 uint32_t length
= height
* stride
;
134 uint32_t len
= (req_size
+ length
) >> 2;
136 if (len
< connection
->maximum_request_length
) {
137 xcb_put_image (connection
->xcb_connection
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
138 dst
, gc
, width
, height
, dst_x
, dst_y
, 0, depth
,
141 int rows
= (connection
->maximum_request_length
- req_size
- 4) / stride
;
147 length
= rows
* stride
;
149 xcb_put_image (connection
->xcb_connection
, XCB_IMAGE_FORMAT_Z_PIXMAP
,
150 dst
, gc
, width
, rows
, dst_x
, dst_y
, 0, depth
, length
, data
);
154 data
= (char *) data
+ length
;
163 _cairo_xcb_connection_do_put_subimage (cairo_xcb_connection_t
*connection
,
177 xcb_protocol_request_t xcb_req
= {
180 XCB_PUT_IMAGE
/* opcode */,
181 1 /* isvoid (doesn't cause a reply) */
183 xcb_put_image_request_t req
;
184 struct iovec vec_stack
[CAIRO_STACK_ARRAY_LENGTH (struct iovec
)];
185 struct iovec
*vec
= vec_stack
;
187 uint8_t *data
= _data
;
189 /* Two extra entries are needed for xcb, two for us */
190 int entries_needed
= height
+ 2 + 2;
192 req
.format
= XCB_IMAGE_FORMAT_Z_PIXMAP
;
204 if (entries_needed
> ARRAY_LENGTH (vec_stack
)) {
205 vec
= _cairo_malloc_ab (entries_needed
, sizeof (struct iovec
));
206 if (unlikely (vec
== NULL
)) {
207 /* XXX loop over ARRAY_LENGTH (vec_stack) */
212 data
+= src_y
* stride
+ src_x
* cpp
;
213 /* vec[1] will be used in XCB if it has to use BigRequests or insert a sync,
214 * vec[0] is used if the internal queue needs to be flushed. */
215 vec
[2].iov_base
= (char *) &req
;
216 vec
[2].iov_len
= sizeof (req
);
218 /* Now comes the actual data */
220 vec
[n
].iov_base
= data
;
221 vec
[n
].iov_len
= cpp
* width
;
227 /* And again some padding */
229 vec
[n
].iov_len
= -len
& 3;
232 /* For efficiency reasons, this functions writes the request "directly" to
233 * the xcb connection to avoid having to copy the data around. */
234 assert (n
== entries_needed
);
235 xcb_req
.count
= n
- 2;
236 xcb_send_request (connection
->xcb_connection
, 0, &vec
[2], &xcb_req
);
238 if (vec
!= vec_stack
)
243 _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t
*connection
,
257 const uint32_t req_size
= sizeof(xcb_put_image_request_t
);
258 uint32_t length
= height
* cpp
* width
;
259 uint32_t len
= (req_size
+ length
) >> 2;
261 if (len
< connection
->maximum_request_length
) {
262 _cairo_xcb_connection_do_put_subimage (connection
, dst
, gc
, src_x
, src_y
,
263 width
, height
, cpp
, stride
, dst_x
, dst_y
, depth
, _data
);
265 int rows
= (connection
->maximum_request_length
- req_size
- 4) / (cpp
* width
);
271 _cairo_xcb_connection_do_put_subimage (connection
, dst
, gc
, src_x
, src_y
,
272 width
, rows
, cpp
, stride
, dst_x
, dst_y
, depth
, _data
);
276 _data
= (char *) _data
+ stride
* rows
;
284 xcb_get_image_reply_t
*
285 _cairo_xcb_connection_get_image (cairo_xcb_connection_t
*connection
,
292 return xcb_get_image_reply (connection
->xcb_connection
,
293 xcb_get_image (connection
->xcb_connection
,
294 XCB_IMAGE_FORMAT_Z_PIXMAP
,