static cairo_xcb_pixmap_t * _pixmap_from_image (cairo_xcb_surface_t *target, xcb_render_pictformat_t format, cairo_image_surface_t *image, cairo_xcb_shm_info_t *shm_info) { xcb_gcontext_t gc; cairo_xcb_pixmap_t *pixmap; pixmap = _cairo_xcb_pixmap_create (target, image->width, image->height); if (unlikely (pixmap->base.status)) return pixmap; gc = _cairo_xcb_screen_get_gc (target->screen, pixmap->pixmap, image->depth); if (shm_info != NULL) { shm_info->seqno = _cairo_xcb_connection_shm_put_image (target->connection, pixmap->pixmap, gc, image->width, image->height, 0, 0, image->width, image->height, 0, 0, image->depth, shm_info->shm, shm_info->offset); } else { int len; /* Do we need to trim the image? */ len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)); if (len == image->stride) { _cairo_xcb_connection_put_image (target->connection, pixmap->pixmap, gc, image->width, image->height, 0, 0, image->depth, image->stride, image->data); } else { _cairo_xcb_connection_put_subimage (target->connection, pixmap->pixmap, gc, 0, 0, image->width, image->height, PIXMAN_FORMAT_BPP (image->pixman_format) / 8, image->stride, 0, 0, image->depth, image->data); } } _cairo_xcb_screen_put_gc (target->screen, image->depth, gc); return pixmap; }
static cairo_status_t _put_image_boxes (cairo_xcb_surface_t *surface, cairo_image_surface_t *image, cairo_boxes_t *boxes) { cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; xcb_gcontext_t gc; if (boxes->num_boxes == 0) return CAIRO_STATUS_SUCCESS; /* XXX track damaged region? */ status = _cairo_xcb_connection_acquire (surface->connection); if (unlikely (status)) return status; assert (image->pixman_format == surface->pixman_format); assert (image->depth == surface->depth); assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format))); gc = _cairo_xcb_screen_get_gc (surface->screen, surface->drawable, surface->depth); status = _put_shm_image_boxes (surface, image, gc, boxes); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { struct _cairo_boxes_chunk *chunk; for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { int i; for (i = 0; i < chunk->count; i++) { cairo_box_t *b = &chunk->base[i]; int x = _cairo_fixed_integer_part (b->p1.x); int y = _cairo_fixed_integer_part (b->p1.y); int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x); int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y); _cairo_xcb_connection_put_image (surface->connection, surface->drawable, gc, width, height, x, y, image->depth, image->stride, image->data + x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 + y * image->stride); } } status = CAIRO_STATUS_SUCCESS; } _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc); _cairo_xcb_connection_release (surface->connection); return status; }
static cairo_status_t _put_image (cairo_xcb_surface_t *surface, cairo_image_surface_t *image) { cairo_status_t status = CAIRO_STATUS_SUCCESS; /* XXX track damaged region? */ status = _cairo_xcb_connection_acquire (surface->connection); 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; assert (image->width == surface->width); assert (image->height == surface->height); assert (image->depth == surface->depth); assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format))); gc = _cairo_xcb_screen_get_gc (surface->screen, surface->drawable, surface->depth); status = _put_shm_image (surface, gc, image); if (status == CAIRO_INT_STATUS_UNSUPPORTED) { _cairo_xcb_connection_put_image (surface->connection, surface->drawable, gc, image->width, image->height, 0, 0, image->depth, image->stride, image->data); status = CAIRO_STATUS_SUCCESS; } _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc); } else { ASSERT_NOT_REACHED; } _cairo_xcb_connection_release (surface->connection); return status; }