xcb: Move the allocation of a shm surface into its own function

This simplifies the fallback to an image surface when something causes an error.

Additionally, this causes errors from _cairo_xcb_connection_allocate_shm_info to
be handled via falling back to a normal image surface while previously those
were returned to the caller.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2011-01-30 15:43:00 +01:00
parent 48cb9186a2
commit 72788a0660

View file

@ -140,6 +140,69 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
return surface;
}
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
static cairo_status_t
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
pixman_format_code_t pixman_format,
int width, int height,
cairo_image_surface_t **image_out,
cairo_xcb_shm_info_t **shm_info_out)
{
cairo_surface_t *image = NULL;
cairo_xcb_shm_info_t *shm_info = NULL;
cairo_status_t status;
size_t size, stride;
if (! (connection->flags & CAIRO_XCB_HAS_SHM))
return CAIRO_INT_STATUS_UNSUPPORTED;
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
size = stride * height;
if (size <= CAIRO_XCB_SHM_SMALL_IMAGE)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_xcb_connection_allocate_shm_info (connection,
size, &shm_info);
if (unlikely (status))
return status;
image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
pixman_format,
width, height,
stride);
status = image->status;
if (unlikely (status)) {
_cairo_xcb_shm_info_destroy (shm_info);
return status;
}
status = _cairo_user_data_array_set_data (&image->user_data,
(const cairo_user_data_key_t *) connection,
shm_info,
(cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
if (unlikely (status)) {
cairo_surface_destroy (image);
_cairo_xcb_shm_info_destroy (shm_info);
return status;
}
*image_out = (cairo_image_surface_t *) image;
*shm_info_out = shm_info;
return CAIRO_STATUS_SUCCESS;
}
#else
static cairo_status_t
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
pixman_format_code_t pixman_format,
int width, int height,
cairo_image_surface_t **image_out,
cairo_xcb_shm_info_t **shm_info_out)
{
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#endif
cairo_status_t
_cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
pixman_format_code_t pixman_format,
@ -151,42 +214,14 @@ _cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
cairo_xcb_shm_info_t *shm_info = NULL;
cairo_status_t status;
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
if ((connection->flags & CAIRO_XCB_HAS_SHM)) {
size_t size, stride;
status = _cairo_xcb_shm_image_create_shm (connection,
pixman_format,
width,
height,
image_out,
shm_info_out);
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
size = stride * height;
if (size > CAIRO_XCB_SHM_SMALL_IMAGE) {
status = _cairo_xcb_connection_allocate_shm_info (connection,
size, &shm_info);
if (unlikely (status))
return status;
image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
pixman_format,
width, height,
stride);
status = image->status;
if (unlikely (status)) {
_cairo_xcb_shm_info_destroy (shm_info);
return status;
}
status = _cairo_user_data_array_set_data (&image->user_data,
(const cairo_user_data_key_t *) connection,
shm_info,
(cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
if (unlikely (status)) {
cairo_surface_destroy (image);
_cairo_xcb_shm_info_destroy (shm_info);
return status;
}
}
}
#endif
if (image == NULL) {
if (status != CAIRO_STATUS_SUCCESS) {
image = _cairo_image_surface_create_with_pixman_format (NULL,
pixman_format,
width, height,
@ -194,11 +229,11 @@ _cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
status = image->status;
if (unlikely (status))
return status;
*image_out = (cairo_image_surface_t *) image;
*shm_info_out = shm_info;
}
*image_out = (cairo_image_surface_t *) image;
*shm_info_out = shm_info;
return CAIRO_STATUS_SUCCESS;
}