/** * SECTION:cairo-xcb * @Title: XCB Surfaces * @Short_Description: X Window System rendering using the XCB library * @See_Also: #cairo_surface_t * * The XCB surface is used to render cairo graphics to X Window System * windows and pixmaps using the XCB library. * * Note that the XCB surface automatically takes advantage of the X render * extension if it is available.
**/
/** * CAIRO_HAS_XCB_SURFACE: * * Defined if the xcb surface backend is available. * This macro can be used to conditionally compile backend-specific code. * * Since: 1.12
**/
static cairo_surface_t *
_get_shm_image (cairo_xcb_surface_t *surface, int x, int y, int width, int height)
{ #if CAIRO_HAS_XCB_SHM_FUNCTIONS
cairo_xcb_shm_info_t *shm_info;
cairo_surface_t *image;
cairo_status_t status;
if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0) return NULL;
status = _cairo_xcb_connection_shm_get_image (surface->connection,
surface->drawable,
x, y,
width, height,
shm_info->shm,
shm_info->offset); if (unlikely (status)) {
cairo_surface_destroy (image);
image = _cairo_surface_create_in_error (status);
}
done: return image; #else return NULL; #endif
}
static cairo_surface_t *
_get_image (cairo_xcb_surface_t *surface,
cairo_bool_t use_shm, int x, int y, int width, int height)
{
cairo_surface_t *image;
cairo_xcb_connection_t *connection;
xcb_get_image_reply_t *reply;
cairo_int_status_t status;
status = _cairo_xcb_connection_acquire (connection); if (unlikely (status)) return _cairo_surface_create_in_error (status);
if (use_shm) {
image = _get_shm_image (surface, x, y, width, height); if (image) { if (image->status == CAIRO_STATUS_SUCCESS) {
_cairo_xcb_connection_release (connection); return image;
}
cairo_surface_destroy (image);
}
}
reply =_cairo_xcb_connection_get_image (connection,
surface->drawable,
x, y,
width, height);
if (reply == NULL && ! surface->owns_pixmap) { /* xcb_get_image_t from a window is dangerous because it can * produce errors if the window is unmapped or partially * outside the screen. We could check for errors and * retry, but to keep things simple, we just create a * temporary pixmap * * If we hit this fallback too often, we should remember so and * skip the round-trip from the above GetImage request, * similar to what cairo-xlib does.
*/
xcb_pixmap_t pixmap;
xcb_gcontext_t gc;
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);
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_subimage (surface->connection,
surface->drawable, gc,
x, y,
width, height,
PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
image->stride,
x, y,
image->depth,
image->data);
if (likely (surface->fallback == NULL)) {
status = CAIRO_STATUS_SUCCESS; if (! surface->base.finished && surface->deferred_clear)
status = _cairo_xcb_surface_clear (surface);
return status;
}
status = surface->base.status; if (status == CAIRO_STATUS_SUCCESS &&
(! surface->base._finishing || ! surface->owns_pixmap)) {
status = cairo_surface_status (&surface->fallback->base);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
CAIRO_FILL_RULE_WINDING,
&surface->fallback_damage);
if (status == CAIRO_STATUS_SUCCESS)
status = _put_image_boxes (surface,
surface->fallback,
&surface->fallback_damage);
/* Do we have a deferred clear and this image surface does NOT cover the * whole xcb surface? Have to apply the clear in that case, else * uploading the image will handle the problem for us.
*/ if (surface->deferred_clear &&
! (extents->width == surface->width &&
extents->height == surface->height)) {
status = _cairo_xcb_surface_clear (surface); if (unlikely (status)) {
cairo_surface_destroy(image); return _cairo_image_surface_create_in_error (status);
}
}
surface->deferred_clear = FALSE;
s = xcb_setup_roots_iterator (xcb_get_setup (connection)); for (; s.rem; xcb_screen_next (&s)) { if (s.data->root_visual == visual->visual_id) {
*depth = s.data->root_depth; return s.data;
}
d = xcb_screen_allowed_depths_iterator(s.data); for (; d.rem; xcb_depth_next (&d)) {
xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
for (; v.rem; xcb_visualtype_next (&v)) { if (v.data->visual_id == visual->visual_id) {
*depth = d.data->depth; return s.data;
}
}
}
}
return NULL;
}
/** * cairo_xcb_surface_create: * @connection: an XCB connection * @drawable: an XCB drawable * @visual: the visual to use for drawing to @drawable. The depth * of the visual must match the depth of the drawable. * Currently, only TrueColor visuals are fully supported. * @width: the current width of @drawable * @height: the current height of @drawable * * Creates an XCB surface that draws to the given drawable. * The way that colors are represented in the drawable is specified * by the provided visual. * * Note: If @drawable is a Window, then the function * cairo_xcb_surface_set_size() must be called whenever the size of the * window changes. * * When @drawable is a Window containing child windows then drawing to * the created surface will be clipped by those child windows. When * the created surface is used as a source, the contents of the * children will be included. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. * * Since: 1.12
**/
cairo_surface_t *
cairo_xcb_surface_create (xcb_connection_t *connection,
xcb_drawable_t drawable,
xcb_visualtype_t *visual, int width, int height)
{
cairo_xcb_screen_t *screen;
xcb_screen_t *xcb_screen;
cairo_format_masks_t image_masks;
pixman_format_code_t pixman_format;
xcb_render_pictformat_t xrender_format; int depth;
if (xcb_connection_has_error (connection)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
/** * cairo_xcb_surface_create_for_bitmap: * @connection: an XCB connection * @screen: the XCB screen associated with @bitmap * @bitmap: an XCB drawable (a Pixmap with depth 1) * @width: the current width of @bitmap * @height: the current height of @bitmap * * Creates an XCB surface that draws to the given bitmap. * This will be drawn to as a %CAIRO_FORMAT_A1 object. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. * * Since: 1.12
**/
cairo_surface_t *
cairo_xcb_surface_create_for_bitmap (xcb_connection_t *connection,
xcb_screen_t *screen,
xcb_pixmap_t bitmap, int width, int height)
{
cairo_xcb_screen_t *cairo_xcb_screen;
if (xcb_connection_has_error (connection)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
/** * cairo_xcb_surface_create_with_xrender_format: * @connection: an XCB connection * @drawable: an XCB drawable * @screen: the XCB screen associated with @drawable * @format: the picture format to use for drawing to @drawable. The * depth of @format mush match the depth of the drawable. * @width: the current width of @drawable * @height: the current height of @drawable * * Creates an XCB surface that draws to the given drawable. * The way that colors are represented in the drawable is specified * by the provided picture format. * * Note: If @drawable is a Window, then the function * cairo_xcb_surface_set_size() must be called whenever the size of the * window changes. * * When @drawable is a Window containing child windows then drawing to * the created surface will be clipped by those child windows. When * the created surface is used as a source, the contents of the * children will be included. * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. * * This function always returns a valid pointer, but it will return a * pointer to a "nil" surface if an error such as out of memory * occurs. You can use cairo_surface_status() to check for this. * * Since: 1.12
**/
cairo_surface_t *
cairo_xcb_surface_create_with_xrender_format (xcb_connection_t *connection,
xcb_screen_t *screen,
xcb_drawable_t drawable,
xcb_render_pictforminfo_t *format, int width, int height)
{
cairo_xcb_screen_t *cairo_xcb_screen;
cairo_format_masks_t image_masks;
pixman_format_code_t pixman_format;
if (xcb_connection_has_error (connection)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
/* This does the necessary fixup when a surface's drawable or size changed. */ staticvoid
_drawable_changed (cairo_xcb_surface_t *surface)
{
_cairo_surface_set_error (&surface->base,
_cairo_surface_begin_modification (&surface->base));
_cairo_boxes_clear (&surface->fallback_damage);
cairo_surface_destroy (&surface->fallback->base);
/** * cairo_xcb_surface_set_size: * @surface: a #cairo_surface_t for the XCB backend * @width: the new width of the surface * @height: the new height of the surface * * Informs cairo of the new size of the XCB drawable underlying the * surface. For a surface created for a window (rather than a pixmap), * this function must be called each time the size of the window * changes. (For a subwindow, you are normally resizing the window * yourself, but for a toplevel window, it is necessary to listen for * ConfigureNotify events.) * * A pixmap can never change size, so it is never necessary to call * this function on a surface created for a pixmap. * * If cairo_surface_flush() wasn't called, some pending operations * might be discarded. * * Since: 1.12
**/ void
cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface, int width, int height)
{
cairo_xcb_surface_t *surface;
if (unlikely (abstract_surface->status)) return; if (unlikely (abstract_surface->finished)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); return;
}
if ( !_cairo_surface_is_xcb(abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return;
}
/** * cairo_xcb_surface_set_drawable: * @surface: a #cairo_surface_t for the XCB backend * @drawable: the new drawable of the surface * @width: the new width of the surface * @height: the new height of the surface * * Informs cairo of the new drawable and size of the XCB drawable underlying the * surface. * * If cairo_surface_flush() wasn't called, some pending operations * might be discarded. * * Since: 1.12
**/ void
cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
xcb_drawable_t drawable, int width, int height)
{
cairo_xcb_surface_t *surface;
if (unlikely (abstract_surface->status)) return; if (unlikely (abstract_surface->finished)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); return;
}
if ( !_cairo_surface_is_xcb(abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return;
}
/* XXX: and what about this case? */ if (surface->owns_pixmap) return;
_drawable_changed (surface);
if (surface->drawable != drawable) {
cairo_status_t status;
status = _cairo_xcb_connection_acquire (surface->connection); if (unlikely (status)) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.