[cairo-commit] 2 commits - boilerplate/cairo-boilerplate-xcb.c src/cairo-freelist.c src/cairo-freelist-private.h src/cairo-xcb-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 30 12:12:23 PDT 2009


 boilerplate/cairo-boilerplate-xcb.c |   36 +
 src/cairo-freelist-private.h        |    5 
 src/cairo-freelist.c                |   33 +
 src/cairo-xcb-surface.c             |  712 +++++++++++++++++++++++-------------
 4 files changed, 537 insertions(+), 249 deletions(-)

New commits:
commit 39284159234d5318c90fa3a72178cd3d14fe0fbb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 30 20:11:12 2009 +0100

    [boilerplate/xcb] Fix pixmap depth
    
    All the error checking, finally pointed out that I was creating a pixmap
    with the wrong depth! Oops.

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index 51fde39..0ab2026 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -73,6 +73,7 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
     xcb_connection_t *c;
     xcb_render_pictforminfo_t *render_format;
     xcb_pict_standard_t format;
+    xcb_void_cookie_t cookie;
     cairo_surface_t *surface;
     cairo_status_t status;
 
@@ -92,22 +93,34 @@ _cairo_boilerplate_xcb_create_surface (const char		 *name,
     root = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
 
     xtc->pixmap = xcb_generate_id (c);
-    xcb_create_pixmap (c, 32, xtc->pixmap, root->root,
-			 width, height);
-
     switch (content) {
     case CAIRO_CONTENT_COLOR:
+	cookie = xcb_create_pixmap_checked (c, 24,
+					    xtc->pixmap, root->root,
+					    width, height);
 	format = XCB_PICT_STANDARD_RGB_24;
 	break;
+
     case CAIRO_CONTENT_COLOR_ALPHA:
+	cookie = xcb_create_pixmap_checked (c, 32,
+					    xtc->pixmap, root->root,
+					    width, height);
 	format = XCB_PICT_STANDARD_ARGB_32;
 	break;
+
     case CAIRO_CONTENT_ALPHA:  /* would be XCB_PICT_STANDARD_A_8 */
     default:
 	fprintf (stderr, "Invalid content for XCB test: %d\n", content);
 	return NULL;
     }
 
+    /* slow, but sure */
+    if (xcb_request_check (c, cookie) != NULL) {
+	xcb_disconnect (c);
+	free (xtc);
+	return NULL;
+    }
+
     render_format = xcb_render_util_find_standard_format (xcb_render_util_query_formats (c), format);
     if (render_format->id == 0)
 	return NULL;
commit e9bc2180d73acc7133d715ed4380ed20fb4364c0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 30 19:50:44 2009 +0100

    [xcb] Deferred error checking.
    
    XCB avoids the dreaded abort on XError mechanism by forcing the client
    to perform deferred error checking. So do so. This allows us to combine
    the fire-and-forget rendering model with accurate error checking,
    without killing the client or mixing our errors with theirs.
    
    XCB for the win!

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index de71fa6..51fde39 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -133,6 +133,23 @@ _cairo_boilerplate_xcb_finish_surface (cairo_surface_t		*surface)
 {
     xcb_target_closure_t *xtc = cairo_surface_get_user_data (surface,
 							     &xcb_closure_key);
+    xcb_generic_event_t *ev;
+
+    cairo_surface_flush (surface);
+
+    if (cairo_surface_status (surface))
+	return cairo_surface_status (surface);
+
+    while ((ev = xcb_poll_for_event (xtc->c)) != NULL) {
+	if (ev->response_type == 0 /* trust me! */) {
+	    xcb_generic_error_t *error = (xcb_generic_error_t *) ev;
+
+	    fprintf (stderr, "Detected error during xcb run: %d major=%d, minor=%d\n",
+		     error->error_code, error->major_code, error->minor_code);
+
+	    return CAIRO_STATUS_WRITE_ERROR;
+	}
+    }
 
     if (xcb_connection_has_error (xtc->c))
 	return CAIRO_STATUS_WRITE_ERROR;
diff --git a/src/cairo-freelist-private.h b/src/cairo-freelist-private.h
index d48a720..5be22b1 100644
--- a/src/cairo-freelist-private.h
+++ b/src/cairo-freelist-private.h
@@ -132,6 +132,11 @@ _cairo_freepool_alloc (cairo_freepool_t *freepool)
     return node;
 }
 
+cairo_private cairo_status_t
+_cairo_freepool_alloc_array (cairo_freepool_t *freepool,
+			     int count,
+			     void **array);
+
 static inline void
 _cairo_freepool_free (cairo_freepool_t *freepool, void *ptr)
 {
diff --git a/src/cairo-freelist.c b/src/cairo-freelist.c
index 6277f90..acf3157 100644
--- a/src/cairo-freelist.c
+++ b/src/cairo-freelist.c
@@ -138,3 +138,36 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool)
 
     return pool + 1;
 }
+
+cairo_status_t
+_cairo_freepool_alloc_array (cairo_freepool_t *freepool,
+			     int count,
+			     void **array)
+{
+    int i;
+
+    for (i = 0; i < count; i++) {
+	cairo_freelist_node_t *node;
+
+	node = freepool->first_free_node;
+	if (likely (node != NULL)) {
+	    VG (VALGRIND_MAKE_MEM_DEFINED (node, sizeof (node->next)));
+	    freepool->first_free_node = node->next;
+	    VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize));
+	} else {
+	    node = _cairo_freepool_alloc_from_pool (freepool);
+	    if (unlikely (node == NULL))
+		goto CLEANUP;
+	}
+
+	array[i] = node;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+
+  CLEANUP:
+    while (i--)
+	_cairo_freepool_free (freepool, array[i]);
+
+    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+}
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 7c5731f..1e47c98 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -38,6 +38,8 @@
 #include "cairo-xcb.h"
 #include "cairo-xcb-xrender.h"
 #include "cairo-clip-private.h"
+#include "cairo-list-private.h"
+#include "cairo-freelist-private.h"
 #include <xcb/xcb_renderutil.h>
 
 #define AllPlanes               ((unsigned long)~0L)
@@ -79,8 +81,16 @@ typedef struct cairo_xcb_surface {
 
     xcb_render_picture_t src_picture, dst_picture;
     xcb_render_pictforminfo_t xrender_format;
+
+    cairo_list_t to_be_checked;
+    cairo_freepool_t cookie_pool;
 } cairo_xcb_surface_t;
 
+typedef struct _cairo_xcb_cookie {
+    cairo_list_t link;
+    xcb_void_cookie_t xcb;
+} cairo_xcb_cookie_t;
+
 #define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor)	\
 	(((surface)->render_major > major) ||			\
 	 (((surface)->render_major == major) && ((surface)->render_minor >= minor)))
@@ -105,7 +115,7 @@ typedef struct cairo_xcb_surface {
 #define CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface)	CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
 #define CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface)	CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface);
 
 static int
@@ -124,6 +134,22 @@ _CAIRO_FORMAT_DEPTH (cairo_format_t format)
     }
 }
 
+static cairo_status_t
+_cairo_xcb_add_cookie_to_be_checked (cairo_xcb_surface_t *surface,
+				     xcb_void_cookie_t xcb)
+{
+    cairo_xcb_cookie_t *cookie;
+
+    cookie = _cairo_freepool_alloc (&surface->cookie_pool);
+    if (unlikely (cookie == NULL))
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    cookie->xcb = xcb;
+    cairo_list_add_tail (&cookie->link, &surface->to_be_checked);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static xcb_render_pictforminfo_t *
 _CAIRO_FORMAT_TO_XRENDER_FORMAT(xcb_connection_t *dpy, cairo_format_t format)
 {
@@ -167,24 +193,40 @@ _xcb_render_format_to_content (xcb_render_pictforminfo_t *xrender_format)
 	return CAIRO_CONTENT_COLOR;
 }
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface)
 {
-    if (surface->have_clip_rects)
-	xcb_set_clip_rectangles(surface->dpy, XCB_CLIP_ORDERING_YX_SORTED, surface->gc,
-			     0, 0,
-			     surface->num_clip_rects,
-			     surface->clip_rects );
+    if (surface->have_clip_rects) {
+	xcb_void_cookie_t cookie;
+
+	cookie = xcb_set_clip_rectangles_checked (surface->dpy,
+					 XCB_CLIP_ORDERING_YX_SORTED, surface->gc,
+					 0, 0,
+					 surface->num_clip_rects,
+					 surface->clip_rects);
+
+	return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface)
 {
-    if (surface->have_clip_rects)
-	xcb_render_set_picture_clip_rectangles (surface->dpy, surface->dst_picture,
-					   0, 0,
-					   surface->num_clip_rects,
-					   surface->clip_rects);
+    if (surface->have_clip_rects) {
+	xcb_void_cookie_t cookie;
+
+	cookie = xcb_render_set_picture_clip_rectangles_checked (surface->dpy,
+								 surface->dst_picture,
+								 0, 0,
+								 surface->num_clip_rects,
+								 surface->clip_rects);
+
+	return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
@@ -298,6 +340,7 @@ static cairo_status_t
 _cairo_xcb_surface_finish (void *abstract_surface)
 {
     cairo_xcb_surface_t *surface = abstract_surface;
+
     if (surface->dst_picture != XCB_NONE)
 	xcb_render_free_picture (surface->dpy, surface->dst_picture);
 
@@ -313,6 +356,8 @@ _cairo_xcb_surface_finish (void *abstract_surface)
     free (surface->clip_rects);
     cairo_region_destroy (surface->clip_region);
 
+    _cairo_freepool_fini (&surface->cookie_pool);
+
     surface->dpy = NULL;
 
     return CAIRO_STATUS_SUCCESS;
@@ -418,12 +463,15 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
     if (surface->use_pixmap == 0)
     {
 	xcb_generic_error_t *error;
-	imagerep = xcb_get_image_reply(surface->dpy,
-				    xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
-						surface->drawable,
-						extents.x, extents.y,
-						extents.width, extents.height,
-						AllPlanes), &error);
+
+	imagerep = xcb_get_image_reply (surface->dpy,
+					xcb_get_image (surface->dpy,
+						       XCB_IMAGE_FORMAT_Z_PIXMAP,
+						       surface->drawable,
+						       extents.x, extents.y,
+						       extents.width, extents.height,
+						       AllPlanes),
+					&error);
 
 	/* If we get an error, the surface must have been a window,
 	 * so retry with the safe code path.
@@ -446,27 +494,48 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
 	 * temporary pixmap
 	 */
 	xcb_pixmap_t pixmap;
+	cairo_xcb_cookie_t *cookies[2];
+	cairo_status_t status;
+
+	status = _cairo_xcb_surface_ensure_gc (surface);
+	if (unlikely (status))
+	    return status;
+
+	status = _cairo_freepool_alloc_array (&surface->cookie_pool,
+					      ARRAY_LENGTH (cookies),
+					      (void **) cookies);
+	if (unlikely (status))
+	    return status;
+
 	pixmap = xcb_generate_id (surface->dpy);
-	xcb_create_pixmap (surface->dpy,
-			 surface->depth,
-			 pixmap,
-			 surface->drawable,
-			 extents.width, extents.height);
-	_cairo_xcb_surface_ensure_gc (surface);
-
-	xcb_copy_area (surface->dpy, surface->drawable, pixmap, surface->gc,
-		     extents.x, extents.y, 0, 0, extents.width, extents.height);
-
-	imagerep = xcb_get_image_reply(surface->dpy,
-				    xcb_get_image(surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
-						pixmap,
-						extents.x, extents.y,
-						extents.width, extents.height,
-						AllPlanes), 0);
+	cookies[0]->xcb = xcb_create_pixmap_checked (surface->dpy,
+						     surface->depth,
+						     pixmap,
+						     surface->drawable,
+						     extents.width, extents.height);
+	cairo_list_add_tail (&cookies[0]->link, &surface->to_be_checked);
+
+	cookies[1]->xcb = xcb_copy_area_checked (surface->dpy,
+						 surface->drawable,
+						 pixmap, surface->gc,
+						 extents.x, extents.y,
+						 0, 0,
+						 extents.width, extents.height);
+	cairo_list_add_tail (&cookies[1]->link, &surface->to_be_checked);
+
+	imagerep = xcb_get_image_reply (surface->dpy,
+					xcb_get_image (surface->dpy,
+						       XCB_IMAGE_FORMAT_Z_PIXMAP,
+						       pixmap,
+						       extents.x, extents.y,
+						       extents.width, extents.height,
+						       AllPlanes),
+					0);
+
 	xcb_free_pixmap (surface->dpy, pixmap);
 
     }
-    if (!imagerep)
+    if (unlikely (imagerep == NULL))
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
     bpp = _bits_per_pixel(surface->dpy, imagerep->depth);
@@ -551,43 +620,57 @@ _get_image_surface (cairo_xcb_surface_t     *surface,
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 }
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_ensure_src_picture (cairo_xcb_surface_t    *surface)
 {
     if (!surface->src_picture) {
-	surface->src_picture = xcb_generate_id(surface->dpy);
-	xcb_render_create_picture (surface->dpy,
-	                           surface->src_picture,
-	                           surface->drawable,
-	                           surface->xrender_format.id,
-				   0, NULL);
+	xcb_void_cookie_t cookie;
+
+	surface->src_picture = xcb_generate_id (surface->dpy);
+	cookie = xcb_render_create_picture_checked (surface->dpy,
+						    surface->src_picture,
+						    surface->drawable,
+						    surface->xrender_format.id,
+						    0, NULL);
+
+	return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
     }
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_ensure_dst_picture (cairo_xcb_surface_t    *surface)
 {
     if (!surface->dst_picture) {
-	surface->dst_picture = xcb_generate_id(surface->dpy);
-	xcb_render_create_picture (surface->dpy,
-	                           surface->dst_picture,
-	                           surface->drawable,
-	                           surface->xrender_format.id,
-				   0, NULL);
-	_cairo_xcb_surface_set_picture_clip_rects (surface);
+	xcb_void_cookie_t cookie;
+
+	surface->dst_picture = xcb_generate_id (surface->dpy);
+	cookie = xcb_render_create_picture_checked (surface->dpy,
+						    surface->dst_picture,
+						    surface->drawable,
+						    surface->xrender_format.id,
+						    0, NULL);
+
+	return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
     }
 
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 _cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface)
 {
+    xcb_void_cookie_t cookie;
+
     if (surface->gc)
-	return;
+	return CAIRO_STATUS_SUCCESS;
 
     surface->gc = xcb_generate_id(surface->dpy);
-    xcb_create_gc (surface->dpy, surface->gc, surface->drawable, 0, 0);
-    _cairo_xcb_surface_set_gc_clip_rects(surface);
+    cookie = xcb_create_gc_checked (surface->dpy, surface->gc, surface->drawable, 0, 0);
+    _cairo_xcb_surface_set_gc_clip_rects (surface);
+
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
 }
 
 static cairo_status_t
@@ -603,6 +686,7 @@ _draw_image_surface (cairo_xcb_surface_t    *surface,
     int bpp, bpl;
     uint32_t data_len;
     uint8_t *data, left_pad=0;
+    xcb_void_cookie_t cookie;
 
     /* equivalent of XPutImage(..., src_x,src_y, dst_x,dst_y, width,height); */
     /* XXX: assumes image and surface formats and depths are the same */
@@ -650,17 +734,17 @@ _draw_image_surface (cairo_xcb_surface_t    *surface,
 	}
     }
     _cairo_xcb_surface_ensure_gc (surface);
-    xcb_put_image (surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
-	surface->drawable, surface->gc,
-	width, height,
-	dst_x, dst_y,
-	left_pad, image->depth,
-	data_len, data);
+    cookie = xcb_put_image_checked (surface->dpy, XCB_IMAGE_FORMAT_Z_PIXMAP,
+				    surface->drawable, surface->gc,
+				    width, height,
+				    dst_x, dst_y,
+				    left_pad, image->depth,
+				    data_len, data);
 
     if (data < image->data || data >= image->data + image->height * bpl)
-	free(data);
+	free (data);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
 }
 
 static cairo_status_t
@@ -817,9 +901,7 @@ _cairo_xcb_surface_set_matrix (cairo_xcb_surface_t *surface,
 			       cairo_matrix_t	   *matrix)
 {
     xcb_render_transform_t xtransform;
-
-    if (!surface->src_picture)
-	return CAIRO_STATUS_SUCCESS;
+    xcb_void_cookie_t cookie;
 
     xtransform.matrix11 = _cairo_fixed_16_16_from_double (matrix->xx);
     xtransform.matrix12 = _cairo_fixed_16_16_from_double (matrix->xy);
@@ -847,9 +929,10 @@ _cairo_xcb_surface_set_matrix (cairo_xcb_surface_t *surface,
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    xcb_render_set_picture_transform (surface->dpy, surface->src_picture, xtransform);
-
-    return CAIRO_STATUS_SUCCESS;
+    cookie = xcb_render_set_picture_transform_checked (surface->dpy,
+						       surface->src_picture,
+						       xtransform);
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
 }
 
 static cairo_status_t
@@ -857,9 +940,7 @@ _cairo_xcb_surface_set_filter (cairo_xcb_surface_t *surface,
 			       cairo_filter_t	   filter)
 {
     const char *render_filter;
-
-    if (!surface->src_picture)
-	return CAIRO_STATUS_SUCCESS;
+    xcb_void_cookie_t cookie;
 
     if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface))
     {
@@ -891,59 +972,70 @@ _cairo_xcb_surface_set_filter (cairo_xcb_surface_t *surface,
 	break;
     }
 
-    xcb_render_set_picture_filter(surface->dpy, surface->src_picture,
-			     strlen(render_filter), render_filter, 0, NULL);
+    cookie = xcb_render_set_picture_filter_checked (surface->dpy, surface->src_picture,
+						    strlen(render_filter), render_filter,
+						    0, NULL);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
 }
 
 static cairo_status_t
-_cairo_xcb_surface_set_repeat (cairo_xcb_surface_t *surface, int repeat)
+_cairo_xcb_surface_set_repeat (cairo_xcb_surface_t *surface, cairo_extend_t extend)
 {
     uint32_t mask = XCB_RENDER_CP_REPEAT;
-    uint32_t pa[] = { repeat };
-
-    if (!surface->src_picture)
-	return CAIRO_STATUS_SUCCESS;
-
-    xcb_render_change_picture (surface->dpy, surface->src_picture, mask, pa);
-
-    return CAIRO_STATUS_SUCCESS;
-}
+    uint32_t pa[1];
+    xcb_void_cookie_t cookie;
 
-static cairo_int_status_t
-_cairo_xcb_surface_set_attributes (cairo_xcb_surface_t	      *surface,
-				   cairo_surface_attributes_t *attributes)
-{
-    cairo_int_status_t status;
-
-    _cairo_xcb_surface_ensure_src_picture (surface);
-
-    status = _cairo_xcb_surface_set_matrix (surface, &attributes->matrix);
-    if (status)
-	return status;
-
-    switch (attributes->extend) {
+    switch (extend) {
     case CAIRO_EXTEND_NONE:
-	_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NONE);
+	pa[0] = XCB_RENDER_REPEAT_NONE;
 	break;
+
     case CAIRO_EXTEND_REPEAT:
-	_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NORMAL);
+	pa[0] = XCB_RENDER_REPEAT_NORMAL;
 	break;
+
     case CAIRO_EXTEND_REFLECT:
 	if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface))
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_REFLECT);
+
+	pa[0] = XCB_RENDER_REPEAT_REFLECT;
 	break;
+
     case CAIRO_EXTEND_PAD:
 	if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface))
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	_cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_PAD);
+
+	pa[0] = XCB_RENDER_REPEAT_PAD;
 	break;
+
     default:
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
+    cookie = xcb_render_change_picture_checked (surface->dpy, surface->src_picture,
+						mask, pa);
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
+}
+
+static cairo_int_status_t
+_cairo_xcb_surface_set_attributes (cairo_xcb_surface_t	      *surface,
+				   cairo_surface_attributes_t *attributes)
+{
+    cairo_int_status_t status;
+
+    status = _cairo_xcb_surface_ensure_src_picture (surface);
+    if (status)
+	return status;
+
+    status = _cairo_xcb_surface_set_matrix (surface, &attributes->matrix);
+    if (status)
+	return status;
+
+    status = _cairo_xcb_surface_set_repeat (surface, attributes->extend);
+    if (status)
+	return status;
+
     status = _cairo_xcb_surface_set_filter (surface, attributes->filter);
     if (status)
 	return status;
@@ -1204,6 +1296,7 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
     composite_operation_t       operation;
     int				itx, ity;
     cairo_bool_t                is_integer_translation;
+    xcb_void_cookie_t		cookie;
 
     if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1244,49 +1337,55 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
     switch (operation)
     {
     case DO_RENDER:
-	_cairo_xcb_surface_ensure_dst_picture (dst);
+	status = _cairo_xcb_surface_ensure_dst_picture (dst);
+	if (unlikely (status))
+	    goto BAIL;
+
 	if (mask) {
 	    status = _cairo_xcb_surface_set_attributes (mask, &mask_attr);
-	    if (status)
+	    if (unlikely (status))
 		goto BAIL;
 
-	    xcb_render_composite (dst->dpy,
-			      _render_operator (op),
-			      src->src_picture,
-			      mask->src_picture,
-			      dst->dst_picture,
-			      src_x + src_attr.x_offset,
-			      src_y + src_attr.y_offset,
-			      mask_x + mask_attr.x_offset,
-			      mask_y + mask_attr.y_offset,
-			      dst_x, dst_y,
-			      width, height);
+	    cookie = xcb_render_composite_checked (dst->dpy,
+						   _render_operator (op),
+						   src->src_picture,
+						   mask->src_picture,
+						   dst->dst_picture,
+						   src_x + src_attr.x_offset,
+						   src_y + src_attr.y_offset,
+						   mask_x + mask_attr.x_offset,
+						   mask_y + mask_attr.y_offset,
+						   dst_x, dst_y,
+						   width, height);
 	} else {
 	    static xcb_render_picture_t maskpict = { XCB_NONE };
 
-	    xcb_render_composite (dst->dpy,
-				_render_operator (op),
-				src->src_picture,
-				maskpict,
-				dst->dst_picture,
-				src_x + src_attr.x_offset,
-				src_y + src_attr.y_offset,
-				0, 0,
-				dst_x, dst_y,
-				width, height);
+	    cookie = xcb_render_composite_checked (dst->dpy,
+						   _render_operator (op),
+						   src->src_picture,
+						   maskpict,
+						   dst->dst_picture,
+						   src_x + src_attr.x_offset,
+						   src_y + src_attr.y_offset,
+						   0, 0,
+						   dst_x, dst_y,
+						   width, height);
 	}
 	break;
 
     case DO_XCOPYAREA:
-	_cairo_xcb_surface_ensure_gc (dst);
-	xcb_copy_area (dst->dpy,
-		   src->drawable,
-		   dst->drawable,
-		   dst->gc,
-		   src_x + src_attr.x_offset,
-		   src_y + src_attr.y_offset,
-		   dst_x, dst_y,
-		   width, height);
+	status = _cairo_xcb_surface_ensure_gc (dst);
+	if (unlikely (status))
+	    return status;
+
+	cookie = xcb_copy_area_checked (dst->dpy,
+					src->drawable,
+					dst->drawable,
+					dst->gc,
+					src_x + src_attr.x_offset,
+					src_y + src_attr.y_offset,
+					dst_x, dst_y,
+					width, height);
 	break;
 
     case DO_XTILE:
@@ -1298,7 +1397,10 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
 	 * _recategorize_composite_operation.
 	 */
 
-	_cairo_xcb_surface_ensure_gc (dst);
+	status = _cairo_xcb_surface_ensure_gc (dst);
+	if (unlikely (status))
+	    return status;
+
 	is_integer_translation =
 	    _cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
 	assert (is_integer_translation == TRUE);
@@ -1314,7 +1416,10 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
 	    xcb_rectangle_t rect = { dst_x, dst_y, width, height };
 
 	    xcb_change_gc( dst->dpy, dst->gc, mask, values );
-	    xcb_poly_fill_rectangle(dst->dpy, dst->drawable, dst->gc, 1, &rect);
+	    cookie = xcb_poly_fill_rectangle_checked (dst->dpy,
+						      dst->drawable,
+						      dst->gc,
+						      1, &rect);
 	}
 	break;
 
@@ -1323,7 +1428,11 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
 	ASSERT_NOT_REACHED;
     }
 
-    if (!_cairo_operator_bounded_by_source (op))
+    status = _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
+    if (unlikely (status))
+	goto BAIL;
+
+    if (!_cairo_operator_bounded_by_source (op)) {
       status = _cairo_surface_composite_fixup_unbounded (&dst->base,
 							 &src_attr, src->width, src->height,
 							 mask ? &mask_attr : NULL,
@@ -1333,6 +1442,7 @@ _cairo_xcb_surface_composite (cairo_operator_t		op,
 							 mask_x, mask_y,
 							 dst_x, dst_y, width, height,
 							 clip_region);
+    }
 
  BAIL:
     if (mask)
@@ -1355,6 +1465,7 @@ _cairo_xcb_surface_fill_rectangles (void			     *abstract_surface,
     xcb_rectangle_t static_xrects[16];
     xcb_rectangle_t *xrects = static_xrects;
     cairo_status_t status;
+    xcb_void_cookie_t cookie;
     int i;
 
     if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface))
@@ -1381,45 +1492,74 @@ _cairo_xcb_surface_fill_rectangles (void			     *abstract_surface,
         xrects[i].height = rects[i].height;
     }
 
-    _cairo_xcb_surface_ensure_dst_picture (surface);
-    xcb_render_fill_rectangles (surface->dpy,
-			   _render_operator (op),
-			   surface->dst_picture,
-			   render_color, num_rects, xrects);
+    status = _cairo_xcb_surface_ensure_dst_picture (surface);
+    if (unlikely (status)) {
+	if (xrects != static_xrects)
+	    free (xrects);
+	return status;
+    }
+
+    cookie = xcb_render_fill_rectangles_checked (surface->dpy,
+						 _render_operator (op),
+						 surface->dst_picture,
+						 render_color, num_rects, xrects);
 
     if (xrects != static_xrects)
-        free(xrects);
+        free (xrects);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (surface, cookie);
 }
 
 /* Creates an A8 picture of size @width x @height, initialized with @color
  */
-static xcb_render_picture_t
+static cairo_status_t
 _create_a8_picture (cairo_xcb_surface_t *surface,
 		    xcb_render_color_t   *color,
 		    int                   width,
 		    int                   height,
-		    cairo_bool_t          repeat)
+		    cairo_bool_t          repeat,
+		    xcb_render_picture_t    *out)
 {
     uint32_t values[] = { TRUE };
     uint32_t mask = repeat ? XCB_RENDER_CP_REPEAT : 0;
 
-    xcb_pixmap_t pixmap = xcb_generate_id (surface->dpy);
-    xcb_render_picture_t picture = xcb_generate_id (surface->dpy);
-
-    xcb_render_pictforminfo_t *format
-	= _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface->dpy, CAIRO_FORMAT_A8);
+    xcb_pixmap_t pixmap;
+    xcb_render_picture_t picture;
+    xcb_render_pictforminfo_t *format;
     xcb_rectangle_t rect = { 0, 0, width, height };
 
-    xcb_create_pixmap (surface->dpy, 8, pixmap, surface->drawable,
-		       width <= 0 ? 1 : width,
-		       height <= 0 ? 1 : height);
-    xcb_render_create_picture (surface->dpy, picture, pixmap, format->id, mask, values);
-    xcb_render_fill_rectangles (surface->dpy, XCB_RENDER_PICT_OP_SRC, picture, *color, 1, &rect);
+    cairo_xcb_cookie_t *cookie[3];
+    cairo_status_t status;
+
+    status = _cairo_freepool_alloc_array (&surface->cookie_pool,
+					  ARRAY_LENGTH (cookie),
+					  (void **) cookie);
+    if (unlikely (status))
+	return status;
+
+    pixmap = xcb_generate_id (surface->dpy);
+    picture = xcb_generate_id (surface->dpy);
+
+    cookie[0]->xcb = xcb_create_pixmap_checked (surface->dpy, 8, pixmap, surface->drawable,
+						width <= 0 ? 1 : width,
+						height <= 0 ? 1 : height);
+    cairo_list_add_tail (&cookie[0]->link, &surface->to_be_checked);
+
+    format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (surface->dpy, CAIRO_FORMAT_A8);
+    cookie[1]->xcb = xcb_render_create_picture_checked (surface->dpy,
+						picture, pixmap, format->id,
+						mask, values);
+    cairo_list_add_tail (&cookie[1]->link, &surface->to_be_checked);
+
+    cookie[2]->xcb = xcb_render_fill_rectangles_checked (surface->dpy,
+							 XCB_RENDER_PICT_OP_SRC,
+							 picture, *color, 1, &rect);
+    cairo_list_add_tail (&cookie[2]->link, &surface->to_be_checked);
+
     xcb_free_pixmap (surface->dpy, pixmap);
 
-    return picture;
+    *out = picture;
+    return CAIRO_STATUS_SUCCESS;
 }
 
 /* Creates a temporary mask for the trapezoids covering the area
@@ -1440,6 +1580,8 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
     xcb_render_color_t solid = { 0xffff, 0xffff, 0xffff, 0xffff };
     xcb_render_picture_t mask_picture, solid_picture;
     xcb_render_trapezoid_t *offset_traps;
+    xcb_void_cookie_t cookie;
+    cairo_status_t status;
     int i;
 
     /* This would be considerably simpler using XRenderAddTraps(), but since
@@ -1449,12 +1591,22 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
      * optimization that avoids creating another intermediate surface on
      * the servers that have XRenderAddTraps().
      */
-    mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
-    solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
+    status = _create_a8_picture (dst, &transparent, width, height, FALSE, &mask_picture);
+    if (unlikely (status))
+	return status;
+
+    status = _create_a8_picture (dst, &solid, 1, 1, TRUE, &solid_picture);
+    if (unlikely (status)) {
+	xcb_render_free_picture (dst->dpy, mask_picture);
+	return status;
+    }
 
     offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
-    if (offset_traps == NULL)
+    if (offset_traps == NULL) {
+	xcb_render_free_picture (dst->dpy, solid_picture);
+	xcb_render_free_picture (dst->dpy, mask_picture);
 	return	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
 
     for (i = 0; i < num_traps; i++) {
 	offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y;
@@ -1469,15 +1621,21 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
         offset_traps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y) - 0x10000 * dst_y;
     }
 
-    xcb_render_trapezoids (dst->dpy, XCB_RENDER_PICT_OP_ADD,
-				solid_picture, mask_picture,
-				pict_format->id,
-				0, 0,
-				num_traps, offset_traps);
+    cookie = xcb_render_trapezoids_checked (dst->dpy, XCB_RENDER_PICT_OP_ADD,
+					    solid_picture, mask_picture,
+					    pict_format->id,
+					    0, 0,
+					    num_traps, offset_traps);
 
     xcb_render_free_picture (dst->dpy, solid_picture);
     free (offset_traps);
 
+    status = _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
+    if (unlikely (status)) {
+	xcb_render_free_picture (dst->dpy, mask_picture);
+	return status;
+    }
+
     *mask_picture_out = mask_picture;
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1554,7 +1712,9 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
     render_src_x = src_x + render_reference_x - dst_x;
     render_src_y = src_y + render_reference_y - dst_y;
 
-    _cairo_xcb_surface_ensure_dst_picture (dst);
+    status = _cairo_xcb_surface_ensure_dst_picture (dst);
+    if (unlikely (status))
+	goto BAIL;
 
     status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
     if (unlikely (status))
@@ -1565,6 +1725,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
 	goto BAIL;
 
     if (!_cairo_operator_bounded_by_mask (op)) {
+	xcb_void_cookie_t cookie;
+
 	/* xcb_render_composite+trapezoids() creates a mask only large enough for the
 	 * trapezoids themselves, but if the operator is unbounded, then we need
 	 * to actually composite all the way out to the bounds, so we create
@@ -1583,19 +1745,22 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
 	if (status)
 	    goto BAIL;
 
-	xcb_render_composite (dst->dpy,
-			  _render_operator (op),
-			  src->src_picture,
-			  mask_picture,
-			  dst->dst_picture,
-			  src_x + attributes.x_offset,
-			  src_y + attributes.y_offset,
-			  0, 0,
-			  dst_x, dst_y,
-			  width, height);
-
+	cookie = xcb_render_composite_checked (dst->dpy,
+					       _render_operator (op),
+					       src->src_picture,
+					       mask_picture,
+					       dst->dst_picture,
+					       src_x + attributes.x_offset,
+					       src_y + attributes.y_offset,
+					       0, 0,
+					       dst_x, dst_y,
+					       width, height);
 	xcb_render_free_picture (dst->dpy, mask_picture);
 
+	status = _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
+	if (unlikely (status))
+	    goto BAIL;
+
 	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
 								 &attributes, src->width, src->height,
 								 width, height,
@@ -1605,8 +1770,9 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
 								 clip_region);
 
     } else {
-        xcb_render_trapezoid_t xtraps_stack[16];
+        xcb_render_trapezoid_t xtraps_stack[CAIRO_STACK_ARRAY_LENGTH (xcb_render_trapezoid_t)];
         xcb_render_trapezoid_t *xtraps = xtraps_stack;
+	xcb_void_cookie_t cookie;
         int i;
 
         if (num_traps > ARRAY_LENGTH(xtraps_stack)) {
@@ -1630,16 +1796,18 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t	op,
             xtraps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y);
         }
 
-	xcb_render_trapezoids (dst->dpy,
-				    _render_operator (op),
-				    src->src_picture, dst->dst_picture,
-				    render_format->id,
-				    render_src_x + attributes.x_offset,
-				    render_src_y + attributes.y_offset,
-				    num_traps, xtraps);
+	cookie = xcb_render_trapezoids_checked (dst->dpy,
+						_render_operator (op),
+						src->src_picture, dst->dst_picture,
+						render_format->id,
+						render_src_x + attributes.x_offset,
+						render_src_y + attributes.y_offset,
+						num_traps, xtraps);
 
         if (xtraps != xtraps_stack)
-            free(xtraps);
+            free (xtraps);
+
+	status = _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
     }
 
  BAIL:
@@ -1663,6 +1831,41 @@ _cairo_xcb_surface_get_extents (void		        *abstract_surface,
     return TRUE;
 }
 
+static cairo_status_t
+_cairo_xcb_surface_flush (void		        *abstract_surface)
+{
+    cairo_xcb_surface_t *surface = abstract_surface;
+    cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+    while (! cairo_list_is_empty (&surface->to_be_checked)) {
+	cairo_xcb_cookie_t *cookie;
+	xcb_generic_error_t *error;
+
+	cookie = cairo_list_first_entry (&surface->to_be_checked,
+					 cairo_xcb_cookie_t,
+					 link);
+
+	error = xcb_request_check (surface->dpy, cookie->xcb);
+	if (error != NULL) {
+#if 0
+	    /* XXX */
+	    fprintf (stderr, "Delayed error detected: %d, major=%d, minor=%d, seqno=%d\n",
+		     error->error_code,
+		     error->major_code,
+		     error->minor_code,
+		     error->sequence);
+#endif
+	    if (status == CAIRO_STATUS_SUCCESS)
+		status = _cairo_error (CAIRO_STATUS_WRITE_ERROR); /* XXX CAIRO_STATUS_CONNECTION_ERROR */
+	}
+
+	cairo_list_del (&cookie->link);
+	_cairo_freepool_free (&surface->cookie_pool, cookie);
+    }
+
+    return status;
+}
+
 /* XXX: _cairo_xcb_surface_get_font_options */
 
 static void
@@ -1733,7 +1936,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
     _cairo_xcb_surface_get_extents,
     NULL, /* old_show_glyphs */
     NULL, /* get_font_options */
-    NULL, /* flush */
+    _cairo_xcb_surface_flush,
     NULL, /* mark_dirty_rectangle */
     _cairo_xcb_surface_scaled_font_fini,
     _cairo_xcb_surface_scaled_glyph_fini,
@@ -1867,6 +2070,10 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
     surface->num_clip_rects = 0;
     surface->clip_region = NULL;
 
+    cairo_list_init (&surface->to_be_checked);
+    _cairo_freepool_init (&surface->cookie_pool,
+			  sizeof (cairo_xcb_cookie_t));
+
     return &surface->base;
 }
 
@@ -2050,10 +2257,15 @@ _cairo_xcb_surface_font_init (xcb_connection_t		    *dpy,
     font_private->format = format;
     font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format);
     font_private->glyphset = xcb_generate_id(dpy);
-    xcb_render_create_glyph_set (dpy, font_private->glyphset, font_private->xrender_format->id);
+
+    /* XXX checking, adding to CloseDisplay */
+    xcb_render_create_glyph_set (dpy,
+				 font_private->glyphset,
+				 font_private->xrender_format->id);
 
     scaled_font->surface_private = font_private;
     scaled_font->surface_backend = &cairo_xcb_surface_backend;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -2077,8 +2289,8 @@ _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
     if (font_private != NULL && scaled_glyph->surface_private != NULL) {
 	xcb_render_glyph_t glyph_index = _cairo_scaled_glyph_index(scaled_glyph);
 	xcb_render_free_glyphs (font_private->dpy,
-			   font_private->glyphset,
-			   1, &glyph_index);
+				font_private->glyphset,
+				1, &glyph_index);
     }
 }
 
@@ -2091,9 +2303,9 @@ _native_byte_order_lsb (void)
 }
 
 static cairo_status_t
-_cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
-			       cairo_scaled_font_t  *scaled_font,
-			       cairo_scaled_glyph_t *scaled_glyph)
+_cairo_xcb_surface_add_glyph (cairo_xcb_surface_t *dst,
+			      cairo_scaled_font_t  *scaled_font,
+			      cairo_scaled_glyph_t *scaled_glyph)
 {
     xcb_render_glyphinfo_t glyph_info;
     xcb_render_glyph_t glyph_index;
@@ -2101,10 +2313,11 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xcb_surface_font_private_t *font_private;
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
+    xcb_void_cookie_t cookie;
 
     if (scaled_font->surface_private == NULL) {
-	status = _cairo_xcb_surface_font_init (dpy, scaled_font,
-						glyph_surface->format);
+	status = _cairo_xcb_surface_font_init (dst->dpy, scaled_font,
+					       glyph_surface->format);
 	if (status)
 	    return status;
     }
@@ -2115,29 +2328,28 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
      * format.
      */
     if (glyph_surface->format != font_private->format) {
-	cairo_t *cr;
+	cairo_surface_pattern_t pattern;
 	cairo_surface_t *tmp_surface;
-	double x_offset, y_offset;
 
 	tmp_surface = cairo_image_surface_create (font_private->format,
 						  glyph_surface->width,
 						  glyph_surface->height);
-	cr = cairo_create (tmp_surface);
-	cairo_surface_get_device_offset (&glyph_surface->base, &x_offset, &y_offset);
-	cairo_set_source_surface (cr, &glyph_surface->base, x_offset, y_offset);
-	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-	cairo_paint (cr);
-
-	status = cairo_status (cr);
-
-	cairo_destroy (cr);
+	status = tmp_surface->status;
+	if (unlikely (status))
+	    goto BAIL;
 
 	tmp_surface->device_transform = glyph_surface->base.device_transform;
 	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
 
+	_cairo_pattern_init_for_surface (&pattern, &glyph_surface->base);
+	status = _cairo_surface_paint (tmp_surface,
+				       CAIRO_OPERATOR_SOURCE, &pattern.base,
+				       NULL);
+	_cairo_pattern_fini (&pattern.base);
+
 	glyph_surface = (cairo_image_surface_t *) tmp_surface;
 
-	if (status)
+	if (unlikely (status))
 	    goto BAIL;
     }
 
@@ -2155,7 +2367,7 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
     switch (scaled_glyph->surface->format) {
     case CAIRO_FORMAT_A1:
 	/* local bitmaps are always stored with bit == byte */
-	if (_native_byte_order_lsb() != (xcb_get_setup(dpy)->bitmap_format_bit_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
+	if (_native_byte_order_lsb() != (xcb_get_setup(dst->dpy)->bitmap_format_bit_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
 	    int		    c = glyph_surface->stride * glyph_surface->height;
 	    unsigned char   *d;
 	    unsigned char   *new, *n;
@@ -2181,7 +2393,7 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
     case CAIRO_FORMAT_A8:
 	break;
     case CAIRO_FORMAT_ARGB32:
-	if (_native_byte_order_lsb() != (xcb_get_setup(dpy)->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
+	if (_native_byte_order_lsb() != (xcb_get_setup(dst->dpy)->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
 	    unsigned int    c = glyph_surface->stride * glyph_surface->height;
 	    unsigned char   *d;
 	    unsigned char   *new, *n;
@@ -2215,14 +2427,16 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
 
     glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
 
-    xcb_render_add_glyphs (dpy, font_private->glyphset,
-		      1, &glyph_index, &glyph_info,
-		      glyph_surface->stride * glyph_surface->height,
-		      data);
+    cookie = xcb_render_add_glyphs_checked (dst->dpy, font_private->glyphset,
+					    1, &glyph_index, &glyph_info,
+					    glyph_surface->stride * glyph_surface->height,
+					    data);
 
     if (data != glyph_surface->data)
 	free (data);
 
+    status = _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
+
  BAIL:
     if (glyph_surface != scaled_glyph->surface)
 	cairo_surface_destroy (&glyph_surface->base);
@@ -2243,6 +2457,7 @@ _cairo_xcb_surface_show_glyphs_8  (cairo_xcb_surface_t *dst,
 {
     cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private;
     xcb_render_util_composite_text_stream_t *stream;
+    xcb_void_cookie_t cookie;
     int i;
     int thisX, thisY;
     int lastX = 0, lastY = 0;
@@ -2259,18 +2474,18 @@ _cairo_xcb_surface_show_glyphs_8  (cairo_xcb_surface_t *dst,
 	lastY = thisY;
     }
 
-    xcb_render_util_composite_text (dst->dpy,
-			    _render_operator (op),
-			    src->src_picture,
-			    dst->dst_picture,
-			    font_private->xrender_format->id,
-                            src_x_offset + _cairo_lround (glyphs[0].x),
-                            src_y_offset + _cairo_lround (glyphs[0].y),
-			    stream);
+    cookie = xcb_render_util_composite_text_checked (dst->dpy,
+						     _render_operator (op),
+						     src->src_picture,
+						     dst->dst_picture,
+						     font_private->xrender_format->id,
+						     src_x_offset + _cairo_lround (glyphs[0].x),
+						     src_y_offset + _cairo_lround (glyphs[0].y),
+						     stream);
 
     xcb_render_util_composite_text_free (stream);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
 }
 
 static cairo_status_t
@@ -2284,6 +2499,7 @@ _cairo_xcb_surface_show_glyphs_16 (cairo_xcb_surface_t *dst,
 {
     cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private;
     xcb_render_util_composite_text_stream_t *stream;
+    xcb_void_cookie_t cookie;
     int i;
     int thisX, thisY;
     int lastX = 0, lastY = 0;
@@ -2300,18 +2516,18 @@ _cairo_xcb_surface_show_glyphs_16 (cairo_xcb_surface_t *dst,
 	lastY = thisY;
     }
 
-    xcb_render_util_composite_text (dst->dpy,
-			    _render_operator (op),
-			    src->src_picture,
-			    dst->dst_picture,
-			    font_private->xrender_format->id,
-                            src_x_offset + _cairo_lround (glyphs[0].x),
-                            src_y_offset + _cairo_lround (glyphs[0].y),
-			    stream);
+    cookie = xcb_render_util_composite_text_checked (dst->dpy,
+						     _render_operator (op),
+						     src->src_picture,
+						     dst->dst_picture,
+						     font_private->xrender_format->id,
+						     src_x_offset + _cairo_lround (glyphs[0].x),
+						     src_y_offset + _cairo_lround (glyphs[0].y),
+						     stream);
 
     xcb_render_util_composite_text_free (stream);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
 }
 
 static cairo_status_t
@@ -2325,6 +2541,7 @@ _cairo_xcb_surface_show_glyphs_32 (cairo_xcb_surface_t *dst,
 {
     cairo_xcb_surface_font_private_t *font_private = scaled_font->surface_private;
     xcb_render_util_composite_text_stream_t *stream;
+    xcb_void_cookie_t cookie;
     int i;
     int thisX, thisY;
     int lastX = 0, lastY = 0;
@@ -2341,18 +2558,18 @@ _cairo_xcb_surface_show_glyphs_32 (cairo_xcb_surface_t *dst,
 	lastY = thisY;
     }
 
-    xcb_render_util_composite_text (dst->dpy,
-			    _render_operator (op),
-			    src->src_picture,
-			    dst->dst_picture,
-			    font_private->xrender_format->id,
-                            src_x_offset + _cairo_lround (glyphs[0].x),
-                            src_y_offset + _cairo_lround (glyphs[0].y),
-			    stream);
+    cookie = xcb_render_util_composite_text_checked (dst->dpy,
+						     _render_operator (op),
+						     src->src_picture,
+						     dst->dst_picture,
+						     font_private->xrender_format->id,
+						     src_x_offset + _cairo_lround (glyphs[0].x),
+						     src_y_offset + _cairo_lround (glyphs[0].y),
+						     stream);
 
     xcb_render_util_composite_text_free (stream);
 
-    return CAIRO_STATUS_SUCCESS;
+    return _cairo_xcb_add_cookie_to_be_checked (dst, cookie);
 }
 
 typedef cairo_status_t (*cairo_xcb_surface_show_glyphs_func_t)
@@ -2376,8 +2593,6 @@ _cairo_xcb_surface_owns_font (cairo_xcb_surface_t *dst,
     return TRUE;
 }
 
-
-
 static cairo_status_t
 _cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
 				cairo_glyph_t       *glyphs,
@@ -2422,14 +2637,18 @@ _cairo_xcb_surface_emit_glyphs (cairo_xcb_surface_t *dst,
 	if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
 	    output_glyphs[o++] = glyphs[i];
 	    if (scaled_glyph->surface_private == NULL) {
-		_cairo_xcb_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
+		_cairo_xcb_surface_add_glyph (dst, scaled_font, scaled_glyph);
 		scaled_glyph->surface_private = (void *) 1;
 	    }
 	}
     }
     num_glyphs = o;
 
-    _cairo_xcb_surface_ensure_dst_picture (dst);
+    status = _cairo_xcb_surface_ensure_dst_picture (dst);
+    if (status) {
+	free (output_glyphs);
+	return status;
+    }
 
     max_chunk_size = xcb_get_maximum_request_length (dst->dpy);
     if (max_index < 256) {
@@ -2592,7 +2811,7 @@ _cairo_xcb_surface_show_glyphs (void			*abstract_dst,
     /* Send all unsent glyphs to the server, and count the max of the glyph indices */
     _cairo_scaled_font_freeze_cache (scaled_font);
 
-    if (_cairo_xcb_surface_owns_font (dst, scaled_font))
+    if (_cairo_xcb_surface_owns_font (dst, scaled_font)) {
 	status = _cairo_xcb_surface_emit_glyphs (dst,
 						 glyphs, num_glyphs,
 						 scaled_font,
@@ -2600,8 +2819,9 @@ _cairo_xcb_surface_show_glyphs (void			*abstract_dst,
 						 src,
 						 &attributes,
 						 remaining_glyphs);
-    else
+    } else {
 	status = CAIRO_INT_STATUS_UNSUPPORTED;
+    }
     _cairo_scaled_font_thaw_cache (scaled_font);
 
   BAIL:


More information about the cairo-commit mailing list