summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-30 19:50:44 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-30 20:11:07 +0100
commite9bc2180d73acc7133d715ed4380ed20fb4364c0 (patch)
tree491caca556027fa602da362616f9264d3c6314b3 /src
parent8e4e0aa7ee5b4e0963409cda825705a09aae61e1 (diff)
[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!
Diffstat (limited to 'src')
-rw-r--r--src/cairo-freelist-private.h5
-rw-r--r--src/cairo-freelist.c33
-rw-r--r--src/cairo-xcb-surface.c712
3 files changed, 504 insertions, 246 deletions
diff --git a/src/cairo-freelist-private.h b/src/cairo-freelist-private.h
index d48a7201..5be22b1f 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 6277f907..acf31573 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 7c5731f4..1e47c989 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: