[PATCH] XCB: Stop taking the xcb socket

Uli Schlachter psychon at znc.in
Sat Dec 4 07:36:28 PST 2010


This makes the xcb backend use the auto-generated xcb API instead of
hand-writing each request. This should also improve parallelism with non-cairo
threads that use the same xcb connection.

Big thanks to Andrea Canciani for taking a look at this and finding lots of good
improvements (especially finding xcb_send_request was great).

cairo-perf-trace and cairo-perf-diff-files between master
(6732dbf2992891be4b1f08b14a5c449fd08b637c) and this change:

 $ ./cairo-perf-diff-files ../master_perf ../xcb_no_socket_perf
old: master_perf
new: xcb_no_socket_perf
Speedups
========
  xcb-rgba                  evolution-0    23558.86 (23558.86 0.00%) -> 19338.78 (19338.78 0.00%):  1.22x speedup
▎
  xcb-rgba          poppler-bug-12266-0     98.43 (98.43 0.00%) ->  82.36 (82.36 0.00%):  1.20x speedup
▎
  xcb-rgba         gnome-terminal-vim-0    5518.08 (5518.08 0.00%) -> 4905.92 (4905.92 0.00%):  1.12x speedup
▏
  xcb-rgba    gnome-terminal-20090601-0    45648.46 (45648.46 0.00%) -> 41231.25 (41231.25 0.00%):  1.11x speedup
▏
  xcb-rgba         evolution-20090607-0    71643.69 (71643.69 0.00%) -> 66314.95 (66314.95 0.00%):  1.08x speedup
▏
  xcb-rgba                    poppler-0    3501.69 (3501.69 0.00%) -> 3322.26 (3322.26 0.00%):  1.05x speedup

Slowdowns
=========
  xcb-rgba       gnome-system-monitor-0    7500.01 (7500.01 0.00%) -> 7923.70 (7923.70 0.00%):  1.06x slowdown

  xcb-rgba        swfdec-youtube-full-0    26409.89 (26409.89 0.00%) -> 28430.76 (28430.76 0.00%):  1.08x slowdown
▏
  xcb-rgba gnome-system-monitor-20090821-0    34801.61 (34801.61 0.00%) -> 37891.14 (37891.14 0.00%):  1.09x slowdown

Signed-off-by: Uli Schlachter <psychon at znc.in>
---
 src/cairo-xcb-connection-core.c   |  336 ++++--------------
 src/cairo-xcb-connection-render.c |  716 +++----------------------------------
 src/cairo-xcb-connection-shm.c    |  105 +-----
 src/cairo-xcb-connection.c        |   41 ---
 src/cairo-xcb-private.h           |   22 +-
 src/cairo-xcb-shm.c               |    3 +-
 src/cairo-xcb-surface-core.c      |   16 +-
 src/cairo-xcb-surface-render.c    |   28 +--
 src/cairo-xcb-surface.c           |   30 +--
 9 files changed, 125 insertions(+), 1172 deletions(-)

diff --git a/src/cairo-xcb-connection-core.c b/src/cairo-xcb-connection-core.c
index 5b16c19..089cc4e 100644
--- a/src/cairo-xcb-connection-core.c
+++ b/src/cairo-xcb-connection-core.c
@@ -42,53 +42,18 @@ _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection,
 				     uint16_t width,
 				     uint16_t height)
 {
-    struct {
-	uint8_t req;
-	uint8_t depth;
-	uint16_t len;
-	uint32_t pixmap;
-	uint32_t drawable;
-	uint16_t width, height;
-    } req;
-    struct iovec vec[1];
-
-    req.req = 53;
-    req.depth = depth;
-    req.len = sizeof (req) >> 2;
-
-    req.pixmap = _cairo_xcb_connection_get_xid (connection);
-    req.drawable = drawable;
-    req.width = width;
-    req.height = height;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
-
-    return req.pixmap;
+    xcb_pixmap_t pixmap = _cairo_xcb_connection_get_xid (connection);
+    xcb_create_pixmap (connection->xcb_connection,
+		       depth, pixmap, drawable,
+		       width, height);
+    return pixmap;
 }
 
 void
 _cairo_xcb_connection_free_pixmap (cairo_xcb_connection_t *connection,
 				   xcb_pixmap_t pixmap)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t pixmap;
-    } req;
-    struct iovec vec[1];
-
-    req.req = 54;
-    req.len = sizeof (req) >> 2;
-    req.pixmap = pixmap;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_free_pixmap (connection->xcb_connection, pixmap);
     _cairo_xcb_connection_put_xid (connection, pixmap);
 }
 
@@ -98,53 +63,17 @@ _cairo_xcb_connection_create_gc (cairo_xcb_connection_t *connection,
 				 uint32_t value_mask,
 				 uint32_t *values)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t gc;
-	uint32_t drawable;
-	uint32_t mask;
-    } req;
-    struct iovec vec[2];
-    int len = _cairo_popcount (value_mask) * 4;
-
-    req.req = 55;
-    req.len = (sizeof (req) + len) >> 2;
-    req.gc = _cairo_xcb_connection_get_xid (connection);
-    req.drawable = drawable;
-    req.mask = value_mask;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = values;
-    vec[1].iov_len = len;
-
-    _cairo_xcb_connection_write (connection, vec, 2);
-
-    return req.gc;
+    xcb_gcontext_t gc = _cairo_xcb_connection_get_xid (connection);
+    xcb_create_gc (connection->xcb_connection, gc, drawable,
+		   value_mask, values);
+    return gc;
 }
 
 void
 _cairo_xcb_connection_free_gc (cairo_xcb_connection_t *connection,
 			       xcb_gcontext_t gc)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t gc;
-    } req;
-    struct iovec vec[1];
-
-    req.req = 60;
-    req.len = sizeof (req) >> 2;
-    req.gc = gc;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_free_gc (connection->xcb_connection, gc);
     _cairo_xcb_connection_put_xid (connection, gc);
 }
 
@@ -154,27 +83,8 @@ _cairo_xcb_connection_change_gc (cairo_xcb_connection_t *connection,
 				 uint32_t value_mask,
 				 uint32_t *values)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t gc;
-	uint32_t mask;
-    } req;
-    struct iovec vec[2];
-    int len = _cairo_popcount (value_mask) * 4;
-
-    req.req = 56;
-    req.len = (sizeof (req) + len) >> 2;
-    req.gc = gc;
-    req.mask = value_mask;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = values;
-    vec[1].iov_len = len;
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_change_gc (connection->xcb_connection, gc,
+		   value_mask, values);
 }
 
 void
@@ -189,38 +99,8 @@ _cairo_xcb_connection_copy_area (cairo_xcb_connection_t *connection,
 				 uint16_t width,
 				 uint16_t height)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t src;
-	uint32_t dst;
-	uint32_t gc;
-	int16_t src_x;
-	int16_t src_y;
-	int16_t dst_x;
-	int16_t dst_y;
-	uint16_t width;
-	uint16_t height;
-    } req;
-    struct iovec vec[1];
-
-    req.req = 62;
-    req.len = sizeof (req) >> 2;
-    req.src = src;
-    req.dst = dst;
-    req.gc = gc;
-    req.src_x = src_x;
-    req.src_y = src_y;
-    req.dst_x = dst_x;
-    req.dst_y = dst_y;
-    req.width = width;
-    req.height = height;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_copy_area (connection->xcb_connection, src, dst, gc,
+		   src_x, src_y, dst_x, dst_y, width, height);
 }
 
 void
@@ -230,26 +110,8 @@ _cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t *connection,
 					   uint32_t num_rectangles,
 					   xcb_rectangle_t *rectangles)
 {
-    struct {
-	uint8_t req;
-	uint8_t pad;
-	uint16_t len;
-	uint32_t dst;
-	uint32_t gc;
-    } req;
-    struct iovec vec[2];
-
-    req.req = 70;
-    req.len = (sizeof (req) + num_rectangles * sizeof (xcb_rectangle_t)) >> 2;
-    req.dst = dst;
-    req.gc = gc;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = rectangles;
-    vec[1].iov_len = num_rectangles * sizeof (xcb_rectangle_t);
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_poly_fill_rectangle (connection->xcb_connection, dst, gc,
+			     num_rectangles, rectangles);
 }
 
 void
@@ -264,86 +126,28 @@ _cairo_xcb_connection_put_image (cairo_xcb_connection_t *connection,
 				 uint32_t stride,
 				 void *data)
 {
-    struct {
-	uint8_t req;
-	uint8_t format;
-	uint16_t len;
-	uint32_t dst;
-	uint32_t gc;
-	uint16_t width;
-	uint16_t height;
-	int16_t dst_x;
-	int16_t dst_y;
-	uint8_t left;
-	uint8_t depth;
-	uint16_t pad;
-    } req;
-    struct iovec vec[3];
-    uint32_t prefix[2];
+    const uint32_t req_size = 18;
     uint32_t length = height * stride;
-    uint32_t len = (sizeof (req) + length) >> 2;
-
-    req.req = 72;
-    req.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
-    req.len = 0;
-    req.dst = dst;
-    req.gc = gc;
-    req.width = width;
-    req.height = height;
-    req.dst_x = dst_x;
-    req.dst_y = dst_y;
-    req.left = 0;
-    req.depth = depth;
-
-    if (len < connection->root->maximum_request_length) {
-	req.len = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-	vec[1].iov_base = data;
-	vec[1].iov_len = length;
-
-	_cairo_xcb_connection_write (connection, vec, 2);
-    } else if (len < connection->maximum_request_length) {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-	vec[2].iov_base = data;
-	vec[2].iov_len = length;
+    uint32_t len = (req_size + length) >> 2;
 
-	_cairo_xcb_connection_write (connection, vec, 3);
+    if (len < connection->maximum_request_length) {
+	xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
+		       dst, gc, width, height, dst_x, dst_y, 0, depth,
+		       length, data);
     } else {
-	int rows;
-
-	rows = (connection->maximum_request_length - sizeof (req) - 4) / stride;
+	int rows = (connection->maximum_request_length - req_size - 4) / stride;
 	if (rows > 0) {
 	    do {
 		if (rows > height)
 		    rows = height;
 
 		length = rows * stride;
-		len = (sizeof (req) + 4 + length) >> 2;
-
-		req.height = rows;
-
-		prefix[0] = *(uint32_t *) &req;
-		prefix[1] = len;
-
-		vec[0].iov_base = prefix;
-		vec[0].iov_len = sizeof (prefix);
-		vec[1].iov_base = (uint32_t *) &req + 1;
-		vec[1].iov_len = sizeof (req) - 4;
-		vec[2].iov_base = data;
-		vec[2].iov_len = length;
 
-		/* note may modify vec */
-		_cairo_xcb_connection_write (connection, vec, 3);
+		xcb_put_image (connection->xcb_connection, XCB_IMAGE_FORMAT_Z_PIXMAP,
+			       dst, gc, width, rows, dst_x, dst_y, 0, depth, length, data);
 
 		height -= rows;
-		req.dst_y += rows;
+		dst_y += rows;
 		data = (char *) data + length;
 	    } while (height);
 	} else {
@@ -367,41 +171,35 @@ _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
 				    uint8_t depth,
 				    void *_data)
 {
-    struct {
-	uint8_t req;
-	uint8_t format;
-	uint16_t len;
-	uint32_t dst;
-	uint32_t gc;
-	uint16_t width;
-	uint16_t height;
-	int16_t dst_x;
-	int16_t dst_y;
-	uint8_t left;
-	uint8_t depth;
-	uint16_t pad;
-    } req;
+    xcb_protocol_request_t xcb_req = {
+	0 /* count */,
+	0 /* ext */,
+	XCB_PUT_IMAGE /* opcode */,
+	1 /* isvoid (doesn't cause a reply) */
+    };
+    xcb_put_image_request_t req;
     struct iovec vec_stack[CAIRO_STACK_ARRAY_LENGTH (struct iovec)];
     struct iovec *vec = vec_stack;
-    uint32_t prefix[2];
-    uint32_t len = (sizeof (req) + cpp*width*height) >> 2;
+    uint32_t len = 0;
     uint8_t *data = _data;
-    int n;
+    int n = 3;
+    /* Two extra entries are needed for xcb, two for us */
+    int entries_needed = height + 2 + 2;
 
-    req.req = 72;
     req.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
-    req.len = 0;
-    req.dst = dst;
+    req.drawable = dst;
     req.gc = gc;
     req.width = width;
     req.height = height;
     req.dst_x = dst_x;
     req.dst_y = dst_y;
-    req.left = 0;
+    req.left_pad = 0;
     req.depth = depth;
+    req.pad0[0] = 0;
+    req.pad0[1] = 0;
 
-    if (height + 2 > ARRAY_LENGTH (vec_stack)) {
-	vec = _cairo_malloc_ab (height+2, sizeof (struct iovec));
+    if (entries_needed > ARRAY_LENGTH (vec_stack)) {
+	vec = _cairo_malloc_ab (entries_needed, sizeof (struct iovec));
 	if (unlikely (vec == NULL)) {
 	    /* XXX loop over ARRAY_LENGTH (vec_stack) */
 	    return;
@@ -409,34 +207,30 @@ _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
     }
 
     data += src_y * stride + src_x * cpp;
-    if (len < connection->root->maximum_request_length) {
-	req.len = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	n = 1;
-    } else if (len < connection->maximum_request_length) {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	n = 2;
-    } else {
-	ASSERT_NOT_REACHED;
-    }
+    /* vec[1] will be used in XCB if it has to use BigRequests or insert a sync,
+     * vec[0] is used if the internal queue needs to be flushed. */
+    vec[2].iov_base = (char *) &req;
+    vec[2].iov_len = sizeof (req);
 
+    /* Now comes the actual data */
     while (height--) {
 	vec[n].iov_base = data;
 	vec[n].iov_len = cpp * width;
+	len += cpp * width;
 	data += stride;
 	n++;
     }
 
-    _cairo_xcb_connection_write (connection, vec, n);
+    /* And again some padding */
+    vec[n].iov_base = 0;
+    vec[n].iov_len = -len & 3;
+    n++;
+
+    /* For efficiency reasons, this functions writes the request "directly" to
+     * the xcb connection to avoid having to copy the data around. */
+    assert (n == entries_needed);
+    xcb_req.count = n - 2;
+    xcb_send_request (connection->xcb_connection, 0, &vec[2], &xcb_req);
 
     if (vec != vec_stack)
 	free (vec);
@@ -452,7 +246,6 @@ _cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
 				 xcb_get_image_reply_t **reply)
 {
     xcb_generic_error_t *error;
-    cairo_status_t status;
 
     *reply = xcb_get_image_reply (connection->xcb_connection,
 				  xcb_get_image (connection->xcb_connection,
@@ -471,12 +264,5 @@ _cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
 	*reply = NULL;
     }
 
-    status = _cairo_xcb_connection_take_socket (connection);
-    if (unlikely (status)) {
-	if (*reply)
-	    free (*reply);
-	*reply = NULL;
-    }
-
-    return status;
+    return CAIRO_STATUS_SUCCESS;
 }
diff --git a/src/cairo-xcb-connection-render.c b/src/cairo-xcb-connection-render.c
index 63eb59d..b44e363 100644
--- a/src/cairo-xcb-connection-render.c
+++ b/src/cairo-xcb-connection-render.c
@@ -35,9 +35,6 @@
 
 #include <xcb/xcbext.h>
 
-#define X_RenderSpans 99
-#define XLIB_COORD_MAX 32767
-
 void
 _cairo_xcb_connection_render_create_picture (cairo_xcb_connection_t  *connection,
 					     xcb_render_picture_t     picture,
@@ -46,34 +43,8 @@ _cairo_xcb_connection_render_create_picture (cairo_xcb_connection_t  *connection
 					     uint32_t                 value_mask,
 					     uint32_t	             *value_list)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	uint32_t drawable;
-	uint32_t format;
-	uint32_t mask;
-    } req;
-    struct iovec vec[2];
-    int len = _cairo_popcount (value_mask) * 4;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 20);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 4;
-    req.length = (sizeof (req) + len) >> 2;
-    req.picture = picture;
-    req.drawable = drawable;
-    req.format = format;
-    req.mask = value_mask;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = value_list;
-    vec[1].iov_len = len;
-
-    _cairo_xcb_connection_write (connection, vec, 1 + (len != 0));
+    xcb_render_create_picture (connection->xcb_connection, picture, drawable,
+			       format, value_mask, value_list);
 }
 
 void
@@ -82,30 +53,8 @@ _cairo_xcb_connection_render_change_picture (cairo_xcb_connection_t     *connect
 					     uint32_t              value_mask,
 					     uint32_t             *value_list)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	uint32_t mask;
-    } req;
-    struct iovec vec[2];
-    int len = _cairo_popcount (value_mask) * 4;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 12);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 5;
-    req.length = (sizeof (req) + len) >> 2;
-    req.picture = picture;
-    req.mask = value_mask;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = value_list;
-    vec[1].iov_len = len;
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_render_change_picture (connection->xcb_connection, picture,
+			       value_mask, value_list);
 }
 
 void
@@ -116,58 +65,16 @@ _cairo_xcb_connection_render_set_picture_clip_rectangles (cairo_xcb_connection_t
 							  uint32_t               rectangles_len,
 							  xcb_rectangle_t *rectangles)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	uint16_t x;
-	uint16_t y;
-    } req;
-    struct iovec vec[2];
-    int len = sizeof (xcb_rectangle_t) * rectangles_len;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 12);
-    assert ((len + sizeof (req)) >> 2 < connection->root->maximum_request_length);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 6;
-    req.length = (sizeof (req) + len) >> 2;
-    req.picture = picture;
-    req.x = clip_x_origin;
-    req.y = clip_y_origin;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = rectangles;
-    vec[1].iov_len = len;
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_render_set_picture_clip_rectangles (connection->xcb_connection, picture,
+					    clip_x_origin, clip_y_origin,
+					    rectangles_len, rectangles);
 }
 
 void
 _cairo_xcb_connection_render_free_picture (cairo_xcb_connection_t *connection,
 					   xcb_render_picture_t  picture)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 8);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 7;
-    req.length = sizeof (req) >> 2;
-    req.picture = picture;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_render_free_picture (connection->xcb_connection, picture);
     _cairo_xcb_connection_put_xid (connection, picture);
 }
 
@@ -186,49 +93,8 @@ _cairo_xcb_connection_render_composite (cairo_xcb_connection_t     *connection,
 					uint16_t              width,
 					uint16_t              height)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t src;
-	uint32_t mask;
-	uint32_t dst;
-	int16_t src_x;
-	int16_t src_y;
-	int16_t mask_x;
-	int16_t mask_y;
-	int16_t dst_x;
-	int16_t dst_y;
-	uint16_t width;
-	uint16_t height;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 36);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 8;
-    req.length = sizeof (req) >> 2;
-    req.op = op;
-    req.src = src;
-    req.mask = mask;
-    req.dst = dst;
-    req.src_x = src_x;
-    req.src_y = src_y;
-    req.mask_x = mask_x;
-    req.mask_y = mask_y;
-    req.dst_x = dst_x;
-    req.dst_y = dst_y;
-    req.width = width;
-    req.height = height;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_render_composite (connection->xcb_connection, op, src, mask, dst,
+			  src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
 }
 
 void
@@ -242,56 +108,8 @@ _cairo_xcb_connection_render_trapezoids (cairo_xcb_connection_t *connection,
 					 uint32_t                      traps_len,
 					 xcb_render_trapezoid_t *traps)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t src;
-	uint32_t dst;
-	uint32_t mask_format;
-	int16_t src_x;
-	int16_t src_y;
-    } req;
-    struct iovec vec[3];
-    uint32_t prefix[2];
-    uint32_t len = (sizeof (req) + traps_len * sizeof (xcb_render_trapezoid_t)) >> 2;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 24);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 10;
-    req.length = 0;
-    req.op = op;
-    req.src = src;
-    req.dst = dst;
-    req.mask_format = mask_format;
-    req.src_x = src_x;
-    req.src_y = src_y;
-
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-	vec[1].iov_base = traps;
-	vec[1].iov_len = traps_len * sizeof (xcb_render_trapezoid_t);
-
-	_cairo_xcb_connection_write (connection, vec, 2);
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-	vec[2].iov_base = traps;
-	vec[2].iov_len = traps_len * sizeof (xcb_render_trapezoid_t);
-
-	_cairo_xcb_connection_write (connection, vec, 3);
-    }
+    xcb_render_trapezoids (connection->xcb_connection, op, src, dst,
+			   mask_format, src_x, src_y, traps_len, traps);
 }
 
 void
@@ -305,6 +123,10 @@ _cairo_xcb_connection_render_spans (cairo_xcb_connection_t *connection,
 				    uint32_t num_spans,
 				    uint16_t *spans)
 {
+    ASSERT_NOT_REACHED;
+#if 0
+#define X_RenderSpans 99
+
     struct {
 	uint8_t major;
 	uint8_t minor;
@@ -360,6 +182,7 @@ _cairo_xcb_connection_render_spans (cairo_xcb_connection_t *connection,
 
 	_cairo_xcb_connection_write (connection, vec, 3);
     }
+#endif
 }
 
 void
@@ -367,52 +190,14 @@ _cairo_xcb_connection_render_create_glyph_set (cairo_xcb_connection_t	*connectio
 					       xcb_render_glyphset_t	 id,
 					       xcb_render_pictformat_t  format)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t gsid;
-	uint32_t format;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 12);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 17;
-    req.length = sizeof (req) >> 2;
-    req.gsid = id;
-    req.format = format;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_render_create_glyph_set (connection->xcb_connection, id, format);
 }
 
 void
 _cairo_xcb_connection_render_free_glyph_set (cairo_xcb_connection_t      *connection,
 					     xcb_render_glyphset_t  glyphset)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t gsid;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 8);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 19;
-    req.length = sizeof (req) >> 2;
-    req.gsid = glyphset;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_render_free_glyph_set (connection->xcb_connection, glyphset);
     _cairo_xcb_connection_put_xid (connection, glyphset);
 }
 
@@ -425,57 +210,8 @@ _cairo_xcb_connection_render_add_glyphs (cairo_xcb_connection_t             *con
 					 uint32_t                      data_len,
 					 uint8_t                *data)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t gsid;
-	uint32_t num_glyphs;
-    } req;
-    struct iovec vec[5];
-    uint32_t prefix[2];
-    uint32_t len = (sizeof (req) + num_glyphs * (sizeof (uint32_t) + sizeof (xcb_render_glyphinfo_t)) + data_len) >> 2;
-    int cnt;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 12);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 20;
-    req.length = 0;
-    req.gsid = glyphset;
-    req.num_glyphs = num_glyphs;
-
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	cnt = 1;
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	cnt = 2;
-    }
-
-    vec[cnt].iov_base = glyphs_id;
-    vec[cnt].iov_len = num_glyphs * sizeof (uint32_t);
-    cnt++;
-
-    vec[cnt].iov_base = glyphs;
-    vec[cnt].iov_len = num_glyphs * sizeof (xcb_render_glyphinfo_t);
-    cnt++;
-
-    vec[cnt].iov_base = data;
-    vec[cnt].iov_len = data_len;
-    cnt++;
-
-    _cairo_xcb_connection_write (connection, vec, cnt);
+    xcb_render_add_glyphs (connection->xcb_connection, glyphset, num_glyphs,
+				   glyphs_id, glyphs, data_len, data);
 }
 
 void
@@ -484,28 +220,7 @@ _cairo_xcb_connection_render_free_glyphs (cairo_xcb_connection_t         *connec
 					  uint32_t                  num_glyphs,
 					  xcb_render_glyph_t *glyphs)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t gsid;
-    } req;
-    struct iovec vec[2];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 8);
-    assert ( (sizeof (req) + num_glyphs * sizeof (uint32_t)) >> 2 < connection->root->maximum_request_length);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 22;
-    req.length = (sizeof (req) + num_glyphs * sizeof (uint32_t)) >> 2;
-    req.gsid = glyphset;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = glyphs;
-    vec[1].iov_len = num_glyphs * sizeof (uint32_t);
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_render_free_glyphs (connection->xcb_connection, glyphset, num_glyphs, glyphs);
 }
 
 void
@@ -520,61 +235,8 @@ _cairo_xcb_connection_render_composite_glyphs_8 (cairo_xcb_connection_t        *
 						 uint32_t                 glyphcmds_len,
 						 uint8_t           *glyphcmds)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t src;
-	uint32_t dst;
-	uint32_t mask_format;
-	uint32_t glyphset;
-	int16_t src_x;
-	int16_t src_y;
-    } req;
-    struct iovec vec[3];
-    uint32_t prefix[2];
-    int len;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 28);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 23;
-    req.length = 0;
-    req.op = op;
-    req.src = src;
-    req.dst = dst;
-    req.mask_format = mask_format;
-    req.glyphset = glyphset;
-    req.src_x = src_x;
-    req.src_y = src_y;
-
-    len = (sizeof (req) + glyphcmds_len) >> 2;
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	len = 1;
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	len = 2;
-    }
-
-    vec[len].iov_base = glyphcmds;
-    vec[len].iov_len = glyphcmds_len;
-    len++;
-
-    _cairo_xcb_connection_write (connection, vec, len);
+    xcb_render_composite_glyphs_8 (connection->xcb_connection, op, src, dst, mask_format,
+				   glyphset, src_x, src_y, glyphcmds_len, glyphcmds);
 }
 
 void
@@ -589,61 +251,8 @@ _cairo_xcb_connection_render_composite_glyphs_16 (cairo_xcb_connection_t
 						  uint32_t                 glyphcmds_len,
 						  uint8_t           *glyphcmds)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t src;
-	uint32_t dst;
-	uint32_t mask_format;
-	uint32_t glyphset;
-	int16_t src_x;
-	int16_t src_y;
-    } req;
-    struct iovec vec[3];
-    uint32_t prefix[2];
-    int len;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 28);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 24;
-    req.length = 0;
-    req.op = op;
-    req.src = src;
-    req.dst = dst;
-    req.mask_format = mask_format;
-    req.glyphset = glyphset;
-    req.src_x = src_x;
-    req.src_y = src_y;
-
-    len = (sizeof (req) + glyphcmds_len) >> 2;
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	len = 1;
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	len = 2;
-    }
-
-    vec[len].iov_base = glyphcmds;
-    vec[len].iov_len = glyphcmds_len;
-    len++;
-
-    _cairo_xcb_connection_write (connection, vec, len);
+    xcb_render_composite_glyphs_16 (connection->xcb_connection, op, src, dst, mask_format,
+				    glyphset, src_x, src_y, glyphcmds_len, glyphcmds);
 }
 
 void
@@ -658,61 +267,8 @@ _cairo_xcb_connection_render_composite_glyphs_32 (cairo_xcb_connection_t
 						  uint32_t                 glyphcmds_len,
 						  uint8_t           *glyphcmds)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t src;
-	uint32_t dst;
-	uint32_t mask_format;
-	uint32_t glyphset;
-	int16_t src_x;
-	int16_t src_y;
-    } req;
-    struct iovec vec[2];
-    uint32_t prefix[2];
-    int len;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 28);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 25;
-    req.length = 0;
-    req.op = op;
-    req.src = src;
-    req.dst = dst;
-    req.mask_format = mask_format;
-    req.glyphset = glyphset;
-    req.src_x = src_x;
-    req.src_y = src_y;
-
-    len = (sizeof (req) + glyphcmds_len) >> 2;
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	len = 1;
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	len = 2;
-    }
-
-    vec[len].iov_base = glyphcmds;
-    vec[len].iov_len = glyphcmds_len;
-    len++;
-
-    _cairo_xcb_connection_write (connection, vec, len);
+    xcb_render_composite_glyphs_32 (connection->xcb_connection, op, src, dst, mask_format,
+				    glyphset, src_x, src_y, glyphcmds_len, glyphcmds);
 }
 
 void
@@ -723,52 +279,8 @@ _cairo_xcb_connection_render_fill_rectangles (cairo_xcb_connection_t      *conne
 					      uint32_t               num_rects,
 					      xcb_rectangle_t *rects)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint8_t op;
-	uint8_t pad1;
-	uint16_t pad2;
-	uint32_t dst;
-	xcb_render_color_t     color;
-    } req;
-    struct iovec vec[3];
-    uint32_t prefix[2];
-    uint32_t len;
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 20);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 26;
-    req.op = op;
-    req.dst = dst;
-    req.color = color;
-
-    len = (sizeof (req) + num_rects * sizeof (xcb_rectangle_t)) >> 2;
-    if (len < connection->root->maximum_request_length) {
-	req.length = len;
-
-	vec[0].iov_base = &req;
-	vec[0].iov_len = sizeof (req);
-
-	len = 1;
-    } else {
-	prefix[0] = *(uint32_t *) &req;
-	prefix[1] = len + 1;
-	vec[0].iov_base = prefix;
-	vec[0].iov_len = sizeof (prefix);
-	vec[1].iov_base = (uint32_t *) &req + 1;
-	vec[1].iov_len = sizeof (req) - 4;
-
-	len = 2;
-    }
-
-    vec[len].iov_base = rects;
-    vec[len].iov_len = num_rects * sizeof (xcb_rectangle_t);
-    len++;
-
-    _cairo_xcb_connection_write (connection, vec, len);
+    xcb_render_fill_rectangles (connection->xcb_connection, op, dst, color,
+				num_rects, rects);
 }
 
 void
@@ -776,25 +288,7 @@ _cairo_xcb_connection_render_set_picture_transform (cairo_xcb_connection_t
 						    xcb_render_picture_t    picture,
 						    xcb_render_transform_t  *transform)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-    } req;
-    struct iovec vec[2];
-
-    req.major = connection->render->major_opcode;
-    req.minor = 28;
-    req.length = (sizeof (req) + sizeof (xcb_render_transform_t)) >> 2;
-    req.picture = picture;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = transform;
-    vec[1].iov_len = sizeof (xcb_render_transform_t);
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_render_set_picture_transform (connection->xcb_connection, picture, *transform);
 }
 
 void
@@ -803,30 +297,8 @@ _cairo_xcb_connection_render_set_picture_filter (cairo_xcb_connection_t
 						 uint16_t                  filter_len,
 						 char               *filter)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	uint16_t nbytes;
-	uint16_t pad;
-    } req;
-    struct iovec vec[2];
-
-    req.nbytes = filter_len;
-    filter_len = (filter_len + 3) & ~3;
-
-    req.major = connection->render->major_opcode;
-    req.minor = 30;
-    req.length = (sizeof (req) + filter_len) >> 2;
-    req.picture = picture;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = filter;
-    vec[1].iov_len = filter_len;
-
-    _cairo_xcb_connection_write (connection, vec, 2);
+    xcb_render_set_picture_filter (connection->xcb_connection, picture,
+				   filter_len, filter, 0, NULL);
 }
 
 void
@@ -834,27 +306,7 @@ _cairo_xcb_connection_render_create_solid_fill (cairo_xcb_connection_t     *conn
 						xcb_render_picture_t  picture,
 						xcb_render_color_t    color)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	xcb_render_color_t color;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 16);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 33;
-    req.length = sizeof (req) >> 2;
-    req.picture = picture;
-    req.color = color;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_render_create_solid_fill (connection->xcb_connection, picture, color);
 }
 
 void
@@ -866,35 +318,8 @@ _cairo_xcb_connection_render_create_linear_gradient (cairo_xcb_connection_t
 						     xcb_render_fixed_t *stops,
 						     xcb_render_color_t *colors)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	xcb_render_pointfix_t p1, p2;
-	uint32_t num_stops;
-    } req;
-    struct iovec vec[3];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 28);
-    assert((sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2 < connection->root->maximum_request_length);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 34;
-    req.length = (sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2;
-    req.picture = picture;
-    req.p1 = p1;
-    req.p2 = p2;
-    req.num_stops = num_stops;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = stops;
-    vec[1].iov_len = num_stops * sizeof (xcb_render_fixed_t);
-    vec[2].iov_base = colors;
-    vec[2].iov_len = num_stops * sizeof (xcb_render_color_t);
-
-    _cairo_xcb_connection_write (connection, vec, 3);
+    xcb_render_create_linear_gradient (connection->xcb_connection, picture,
+				       p1, p2, num_stops, stops, colors);
 }
 
 void
@@ -908,40 +333,9 @@ _cairo_xcb_connection_render_create_radial_gradient (cairo_xcb_connection_t
 						     xcb_render_fixed_t *stops,
 						     xcb_render_color_t *colors)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	xcb_render_pointfix_t     inner;
-	xcb_render_pointfix_t     outer;
-	xcb_render_fixed_t        inner_radius;
-	xcb_render_fixed_t        outer_radius;
-	uint32_t num_stops;
-    } req;
-    struct iovec vec[3];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 36);
-    assert((sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2 < connection->root->maximum_request_length);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 35;
-    req.length = (sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2;
-    req.picture = picture;
-    req.inner = inner;
-    req.outer = outer;
-    req.inner_radius = inner_radius;
-    req.outer_radius = outer_radius;
-    req.num_stops = num_stops;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = stops;
-    vec[1].iov_len = num_stops * sizeof (xcb_render_fixed_t);
-    vec[2].iov_base = colors;
-    vec[2].iov_len = num_stops * sizeof (xcb_render_color_t);
-
-    _cairo_xcb_connection_write (connection, vec, 3);
+    xcb_render_create_radial_gradient (connection->xcb_connection, picture,
+				       inner, outer, inner_radius, outer_radius,
+				       num_stops, stops, colors);
 }
 
 void
@@ -953,34 +347,6 @@ _cairo_xcb_connection_render_create_conical_gradient (cairo_xcb_connection_t
 						      xcb_render_fixed_t *stops,
 						      xcb_render_color_t *colors)
 {
-    struct {
-	uint8_t major;
-	uint8_t minor;
-	uint16_t length;
-	uint32_t picture;
-	xcb_render_pointfix_t     center;
-	xcb_render_fixed_t        angle;
-	uint32_t num_stops;
-    } req;
-    struct iovec vec[3];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 24);
-    assert((sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2 < connection->root->maximum_request_length);
-
-    req.major = connection->render->major_opcode;
-    req.minor = 36;
-    req.length = (sizeof (req)  + num_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t))) >> 2;
-    req.picture = picture;
-    req.center = center;
-    req.angle = angle;
-    req.num_stops = num_stops;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-    vec[1].iov_base = stops;
-    vec[1].iov_len = num_stops * sizeof (xcb_render_fixed_t);
-    vec[2].iov_base = colors;
-    vec[2].iov_len = num_stops * sizeof (xcb_render_color_t);
-
-    _cairo_xcb_connection_write (connection, vec, 3);
+    xcb_render_create_conical_gradient (connection->xcb_connection, picture,
+				       center, angle, num_stops, stops, colors);
 }
diff --git a/src/cairo-xcb-connection-shm.c b/src/cairo-xcb-connection-shm.c
index 060a03e..3e76301 100644
--- a/src/cairo-xcb-connection-shm.c
+++ b/src/cairo-xcb-connection-shm.c
@@ -41,35 +41,12 @@ _cairo_xcb_connection_shm_attach (cairo_xcb_connection_t *connection,
 				  uint32_t id,
 				  cairo_bool_t readonly)
 {
-    struct {
-	uint8_t req;
-	uint8_t shm_req;
-	uint16_t length;
-	uint32_t segment;
-	uint32_t id;
-	uint8_t readonly;
-	uint8_t pad1;
-	uint16_t pad2;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 16);
-
-    req.req = connection->shm->major_opcode;
-    req.shm_req = 1;
-    req.length = sizeof (req) >> 2;
-    req.segment = _cairo_xcb_connection_get_xid (connection);
-    req.id = id;
-    req.readonly = readonly;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
-    return req.segment;
+    uint32_t segment = _cairo_xcb_connection_get_xid (connection);
+    xcb_shm_attach (connection->xcb_connection, segment, id, readonly);
+    return segment;
 }
 
-uint64_t
+unsigned int
 _cairo_xcb_connection_shm_put_image (cairo_xcb_connection_t *connection,
 				     xcb_drawable_t dst,
 				     xcb_gcontext_t gc,
@@ -85,53 +62,11 @@ _cairo_xcb_connection_shm_put_image (cairo_xcb_connection_t *connection,
 				     uint32_t shm,
 				     uint32_t offset)
 {
-    struct {
-	uint8_t req;
-	uint8_t shm_req;
-	uint16_t len;
-	uint32_t dst;
-	uint32_t gc;
-	uint16_t total_width;
-	uint16_t total_height;
-	int16_t src_x;
-	int16_t src_y;
-	uint16_t src_width;
-	uint16_t src_height;
-	int16_t dst_x;
-	int16_t dst_y;
-	uint8_t depth;
-	uint8_t format;
-	uint8_t send_event;
-	uint8_t pad;
-	uint32_t shm;
-	uint32_t offset;
-    } req;
-    struct iovec vec[2];
-
-    req.req = connection->shm->major_opcode;
-    req.shm_req = 3;
-    req.len = sizeof (req) >> 2;
-    req.dst = dst;
-    req.gc = gc;
-    req.total_width = total_width;
-    req.total_height = total_height;
-    req.src_x = src_x;
-    req.src_y = src_y;
-    req.src_width = width;
-    req.src_height = height;
-    req.dst_x = dst_x;
-    req.dst_y = dst_y;
-    req.depth = depth;
-    req.format = XCB_IMAGE_FORMAT_Z_PIXMAP;
-    req.send_event = 0;
-    req.shm = shm;
-    req.offset = offset;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
-    return connection->seqno;
+    xcb_void_cookie_t cookie;
+    cookie = xcb_shm_put_image (connection->xcb_connection, dst, gc, total_width, total_height,
+				src_x, src_y, width, height, dst_x, dst_y, depth,
+				XCB_IMAGE_FORMAT_Z_PIXMAP, 0, shm, offset);
+    return cookie.sequence;
 }
 
 cairo_status_t
@@ -164,31 +99,13 @@ _cairo_xcb_connection_shm_get_image (cairo_xcb_connection_t *connection,
 	return _cairo_error (CAIRO_STATUS_READ_ERROR);
     }
 
-    return _cairo_xcb_connection_take_socket (connection);
+    return CAIRO_STATUS_SUCCESS;
 }
 
 void
 _cairo_xcb_connection_shm_detach (cairo_xcb_connection_t *connection,
 				  uint32_t segment)
 {
-    struct {
-	uint8_t req;
-	uint8_t shm_req;
-	uint16_t length;
-	uint32_t segment;
-    } req;
-    struct iovec vec[1];
-
-    COMPILE_TIME_ASSERT (sizeof (req) == 8);
-
-    req.req = connection->shm->major_opcode;
-    req.shm_req = 2;
-    req.length = sizeof (req) >> 2;
-    req.segment = segment;
-
-    vec[0].iov_base = &req;
-    vec[0].iov_len = sizeof (req);
-
-    _cairo_xcb_connection_write (connection, vec, 1);
+    xcb_shm_detach (connection->xcb_connection, segment);
     _cairo_xcb_connection_put_xid (connection, segment);
 }
diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c
index 0488390..74b9f21 100644
--- a/src/cairo-xcb-connection.c
+++ b/src/cairo-xcb-connection.c
@@ -540,13 +540,6 @@ _device_finish (void *device)
 	_cairo_xcb_screen_finish (screen);
     }
 
-    if (connection->has_socket) {
-	/* Send a request so that xcb takes the socket from us, preventing
-	 * a later use-after-free on shutdown of the connection.
-	 */
-	xcb_no_operation (connection->xcb_connection);
-    }
-
     if (was_cached)
 	cairo_device_destroy (device);
 }
@@ -624,7 +617,6 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
     _cairo_device_init (&connection->device, &_cairo_xcb_device_backend);
 
     connection->xcb_connection = xcb_connection;
-    connection->has_socket = FALSE;
 
     cairo_list_init (&connection->fonts);
     cairo_list_init (&connection->screens);
@@ -787,39 +779,6 @@ _cairo_xcb_connection_get_xid (cairo_xcb_connection_t *connection)
     return xid;
 }
 
-static void
-_cairo_xcb_return_socket (void *closure)
-{
-    cairo_xcb_connection_t *connection = closure;
-
-    CAIRO_MUTEX_LOCK (connection->device.mutex);
-    connection->has_socket = FALSE;
-    CAIRO_MUTEX_UNLOCK (connection->device.mutex);
-}
-
-cairo_status_t
-_cairo_xcb_connection_take_socket (cairo_xcb_connection_t *connection)
-{
-    assert (CAIRO_MUTEX_IS_LOCKED (connection->device.mutex));
-
-    if (unlikely (connection->device.status))
-	return connection->device.status;
-
-    if (! connection->has_socket) {
-	if (! xcb_take_socket (connection->xcb_connection,
-			       _cairo_xcb_return_socket,
-			       connection,
-			       0, &connection->seqno))
-	{
-	    return connection->device.status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
-	}
-
-	connection->has_socket = TRUE;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
 /* public (debug) interface */
 
 void
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index e066911..c7f42f6 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -66,7 +66,7 @@ struct _cairo_xcb_shm_info {
     cairo_xcb_connection_t *connection;
     uint32_t shm;
     uint32_t offset;
-    uint64_t seqno;
+    unsigned int seqno;
     void *mem;
     cairo_xcb_shm_mem_pool_t *pool;
 };
@@ -170,7 +170,6 @@ struct _cairo_xcb_connection {
     cairo_device_t device;
 
     xcb_connection_t *xcb_connection;
-    cairo_bool_t has_socket;
 
     xcb_render_pictformat_t standard_formats[5];
     cairo_hash_table_t *xrender_formats;
@@ -183,7 +182,6 @@ struct _cairo_xcb_connection {
     const xcb_query_extension_reply_t *render;
     const xcb_query_extension_reply_t *shm;
     const xcb_query_extension_reply_t *dri2;
-    uint64_t seqno;
 
     cairo_list_t free_xids;
     cairo_freepool_t xid_pool;
@@ -246,9 +244,6 @@ _cairo_xcb_connection_acquire (cairo_xcb_connection_t *connection)
     return cairo_device_acquire (&connection->device);
 }
 
-cairo_private cairo_status_t
-_cairo_xcb_connection_take_socket (cairo_xcb_connection_t *connection);
-
 cairo_private uint32_t
 _cairo_xcb_connection_get_xid (cairo_xcb_connection_t *connection);
 
@@ -451,19 +446,6 @@ _cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
 				    const cairo_color_t	*color,
 				    cairo_boxes_t *boxes);
 
-static inline void
-_cairo_xcb_connection_write (cairo_xcb_connection_t *connection,
-			     struct iovec *vec,
-			     int count)
-{
-    if (unlikely (connection->device.status))
-	return;
-
-    connection->seqno++;
-    if (unlikely (! xcb_writev (connection->xcb_connection, vec, count, 1)))
-	connection->device.status = _cairo_error (CAIRO_STATUS_WRITE_ERROR);
-}
-
 cairo_private xcb_pixmap_t
 _cairo_xcb_connection_create_pixmap (cairo_xcb_connection_t *connection,
 				     uint8_t depth,
@@ -552,7 +534,7 @@ _cairo_xcb_connection_shm_attach (cairo_xcb_connection_t *connection,
 				  uint32_t id,
 				  cairo_bool_t readonly);
 
-cairo_private uint64_t
+cairo_private unsigned int
 _cairo_xcb_connection_shm_put_image (cairo_xcb_connection_t *connection,
 				     xcb_drawable_t dst,
 				     xcb_gcontext_t gc,
diff --git a/src/cairo-xcb-shm.c b/src/cairo-xcb-shm.c
index 417496e..cfcf6d1 100644
--- a/src/cairo-xcb-shm.c
+++ b/src/cairo-xcb-shm.c
@@ -541,8 +541,7 @@ _cairo_xcb_shm_info_destroy (cairo_xcb_shm_info_t *shm_info)
     _cairo_freepool_free (&connection->shm_info_freelist, shm_info);
 
     /* scan for old, unused pools - hold at least one in reserve */
-    if (! cairo_list_is_singular (&connection->shm_pools) &&
-	_cairo_xcb_connection_take_socket (connection) == CAIRO_STATUS_SUCCESS)
+    if (! cairo_list_is_singular (&connection->shm_pools))
     {
 	cairo_xcb_shm_mem_pool_t *pool, *next;
 	cairo_list_t head;
diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c
index 3fbb072..f12d735 100644
--- a/src/cairo-xcb-surface-core.c
+++ b/src/cairo-xcb-surface-core.c
@@ -64,10 +64,8 @@ _cairo_xcb_pixmap_finish (void *abstract_surface)
 	if (unlikely (status))
 	    return status;
 
-	if (_cairo_xcb_connection_take_socket (surface->connection) == CAIRO_STATUS_SUCCESS) {
-	    _cairo_xcb_connection_free_pixmap (surface->connection,
-					       surface->pixmap);
-	}
+	_cairo_xcb_connection_free_pixmap (surface->connection,
+					   surface->pixmap);
 	_cairo_xcb_connection_release (surface->connection);
     }
 
@@ -472,10 +470,6 @@ _cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t		*dst,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (dst->connection);
-    if (unlikely (status))
-	goto CLEANUP_CONNECTION;
-
     src = _cairo_xcb_pixmap_for_pattern (dst, src_pattern, extents);
     status = src->base.status;
     if (unlikely (status))
@@ -566,12 +560,6 @@ _cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (dst->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (dst->connection);
-	return status;
-    }
-
     gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
 
 #if 0
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 6f29224..6a42225 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -115,8 +115,7 @@ _cairo_xcb_picture_finish (void *abstract_surface)
     _cairo_xcb_screen_remove_surface_picture (surface->screen, &surface->base);
 
     if (surface->owner == NULL) {
-	if (_cairo_xcb_connection_take_socket (connection) == CAIRO_STATUS_SUCCESS)
-	    _cairo_xcb_connection_render_free_picture (connection, surface->picture);
+	_cairo_xcb_connection_render_free_picture (connection, surface->picture);
     }
 
     _cairo_xcb_connection_release (connection);
@@ -2349,12 +2348,6 @@ _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (dst->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (dst->connection);
-	return status;
-    }
-
     gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
 
     rect.x = rect.y = 0;
@@ -2422,12 +2415,6 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (dst->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (dst->connection);
-	return status;
-    }
-
     if (dst->deferred_clear) {
 	status = _cairo_xcb_surface_clear (dst);
 	if (unlikely (status)) {
@@ -2576,12 +2563,6 @@ _composite_boxes (cairo_xcb_surface_t *dst,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (dst->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (dst->connection);
-	return status;
-    }
-
     _cairo_xcb_surface_ensure_picture (dst);
     if (dst->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES && ! need_clip_mask &&
 	(op == CAIRO_OPERATOR_CLEAR || src->type == CAIRO_PATTERN_TYPE_SOLID))
@@ -2703,11 +2684,6 @@ _upload_image_inplace (cairo_xcb_surface_t *surface,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (surface->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (surface->connection);
-	return status;
-    }
     gc = _cairo_xcb_screen_get_gc (surface->screen, surface->drawable, image->depth);
 
     /* Do we need to trim the image? */
@@ -3993,8 +3969,6 @@ _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 
     status = _cairo_xcb_connection_acquire (connection);
     have_connection = status == CAIRO_STATUS_SUCCESS;
-    if (likely (have_connection))
-	status = _cairo_xcb_connection_take_socket (connection);
 
     for (i = 0; i < NUM_GLYPHSETS; i++) {
 	cairo_xcb_font_glyphset_info_t *glyphset_info;
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 24e33bb..5ee79e0 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -203,12 +203,6 @@ _cairo_xcb_surface_create_similar (void			*abstract_other,
     if (unlikely (status))
 	return _cairo_surface_create_in_error (status);
 
-    status =_cairo_xcb_connection_take_socket (connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (connection);
-	return _cairo_surface_create_in_error (status);
-    }
-
     if (content == other->base.content) {
 	pixmap = _cairo_xcb_connection_create_pixmap (connection,
 						      other->depth,
@@ -289,15 +283,13 @@ _cairo_xcb_surface_finish (void *abstract_surface)
 
     status = _cairo_xcb_connection_acquire (surface->connection);
     if (status == CAIRO_STATUS_SUCCESS) {
-	if (_cairo_xcb_connection_take_socket (surface->connection) == CAIRO_STATUS_SUCCESS) {
-	    if (surface->picture != XCB_NONE) {
-		_cairo_xcb_connection_render_free_picture (surface->connection,
-							   surface->picture);
-	    }
-
-	    if (surface->owns_pixmap)
-		_cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
+	if (surface->picture != XCB_NONE) {
+	    _cairo_xcb_connection_render_free_picture (surface->connection,
+						       surface->picture);
 	}
+
+	if (surface->owns_pixmap)
+	    _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
 	_cairo_xcb_connection_release (surface->connection);
     }
 
@@ -428,10 +420,6 @@ _get_image (cairo_xcb_surface_t		 *surface,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (connection);
-    if (unlikely (status))
-	goto FAIL;
-
     if (use_shm) {
 	status = _get_shm_image (surface, image_out);
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
@@ -650,12 +638,6 @@ _put_image (cairo_xcb_surface_t    *surface,
     if (unlikely (status))
 	return status;
 
-    status = _cairo_xcb_connection_take_socket (surface->connection);
-    if (unlikely (status)) {
-	_cairo_xcb_connection_release (surface->connection);
-	return status;
-    }
-
     if (image->pixman_format == surface->pixman_format) {
 	xcb_gcontext_t gc;
 
-- 
1.7.2.3


--------------030306060302090809020400
Content-Type: application/octet-stream;
 name="0001-XCB-Stop-taking-the-xcb-socket.patch.sig"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="0001-XCB-Stop-taking-the-xcb-socket.patch.sig"

iQEcBAABCAAGBQJNFMxBAAoJECLkKOvLj8sGtrAH/i+o+YPjq4zi+44VbcSM40RUWEGWJJHc
2+4JgrZ3VMjW97h+NfEtcYuvsIZ++HJ/fnPcVnZswaTs82X0YzSRjxaL7rJpQI3opBwpAADV
nU0mnGDdpFuuapDM4mjgytZr6rcxIl5shoTrMzM0+LWXoHJyIItC4C6UzIpSXikbfuQCBQtt
gymyGV2sCmhQS6yMugBD9cIvPIb3f81+hBRrdCdXLhBk+6HZcRi11fBaQHvAhc+npkTXYx8F
hTpGf0UyTO3DRgKQWrS6LiaX2Qtme9ByA6adiKUrjC+MGSwYhDB8i4Wc+y8/cH2B9cKNSkFD
fDumfwHLJCLj56SWrLwCQtA=
--------------030306060302090809020400--


More information about the cairo mailing list