diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-10 13:36:53 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-10 13:36:53 +0100 |
commit | e540d040bddc717f17e0e2510cffc0bc3cb41ccd (patch) | |
tree | e5a76a9cd0c0f23d708cd6bd14136565bbbb13bf | |
parent | 8b486db9a9d74b40df296382eb1833bc40ae791a (diff) |
xcb: trivial memfault fixes.
The first fixes required to kick-start memfault testing of the xcb
backend.
-rw-r--r-- | boilerplate/cairo-boilerplate-xcb.c | 22 | ||||
-rw-r--r-- | src/cairo-xcb-connection-render.c | 35 | ||||
-rw-r--r-- | src/cairo-xcb-connection.c | 57 | ||||
-rw-r--r-- | src/cairo-xcb-private.h | 2 | ||||
-rw-r--r-- | src/cairo-xcb-screen.c | 15 | ||||
-rw-r--r-- | src/cairo-xcb-surface-core.c | 1 | ||||
-rw-r--r-- | src/cairo-xcb-surface-render.c | 32 | ||||
-rw-r--r-- | src/cairo-xcb-surface.c | 5 | ||||
-rw-r--r-- | src/cairo-xlib-xcb-surface.c | 1 |
9 files changed, 123 insertions, 47 deletions
diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c index 5ddf3fa8..0a5f5a4f 100644 --- a/boilerplate/cairo-boilerplate-xcb.c +++ b/boilerplate/cairo-boilerplate-xcb.c @@ -128,8 +128,10 @@ _cairo_boilerplate_xcb_create_surface (const char *name, height = 1; xtc->c = c = xcb_connect(NULL,NULL); - if (xcb_connection_has_error(c)) + if (c == NULL || xcb_connection_has_error(c)) { + free (xtc); return NULL; + } root = xcb_setup_roots_iterator(xcb_get_setup(c)).data; @@ -233,8 +235,10 @@ _cairo_boilerplate_xcb_create_window (const char *name, height = 1; xtc->c = c = xcb_connect(NULL,NULL); - if (xcb_connection_has_error(c)) + if (xcb_connection_has_error(c)) { + free (xtc); return NULL; + } xtc->surface = NULL; @@ -302,8 +306,10 @@ _cairo_boilerplate_xcb_create_window_db (const char *name, height = 1; xtc->c = c = xcb_connect(NULL,NULL); - if (xcb_connection_has_error(c)) + if (xcb_connection_has_error(c)) { + free (xtc); return NULL; + } xtc->surface = NULL; @@ -374,8 +380,10 @@ _cairo_boilerplate_xcb_create_render_0_0 (const char *name, height = 1; xtc->c = c = xcb_connect(NULL,NULL); - if (xcb_connection_has_error(c)) + if (xcb_connection_has_error(c)) { + free (xtc); return NULL; + } root = xcb_setup_roots_iterator(xcb_get_setup(c)).data; @@ -422,6 +430,12 @@ _cairo_boilerplate_xcb_create_render_0_0 (const char *name, xtc->drawable, render_format, width, height); + if (cairo_surface_status (tmp)) { + free (formats); + xcb_disconnect (c); + free (xtc); + return tmp; + } cairo_xcb_device_debug_cap_xrender_version (cairo_surface_get_device (tmp), 0, 0); diff --git a/src/cairo-xcb-connection-render.c b/src/cairo-xcb-connection-render.c index 97f8ccef..63eb59df 100644 --- a/src/cairo-xcb-connection-render.c +++ b/src/cairo-xcb-connection-render.c @@ -733,25 +733,42 @@ _cairo_xcb_connection_render_fill_rectangles (cairo_xcb_connection_t *conne uint32_t dst; xcb_render_color_t color; } req; - struct iovec vec[2]; - uint32_t len = (sizeof (req) + num_rects * sizeof (xcb_rectangle_t)) >> 2; + struct iovec vec[3]; + uint32_t prefix[2]; + uint32_t len; COMPILE_TIME_ASSERT (sizeof (req) == 20); - assert(len < connection->root->maximum_request_length); req.major = connection->render->major_opcode; req.minor = 26; - req.length = (sizeof (req) + num_rects * sizeof (xcb_rectangle_t)) >> 2; req.op = op; req.dst = dst; req.color = color; - vec[0].iov_base = &req; - vec[0].iov_len = sizeof (req); - vec[1].iov_base = rects; - vec[1].iov_len = num_rects * sizeof (xcb_rectangle_t); + len = (sizeof (req) + num_rects * sizeof (xcb_rectangle_t)) >> 2; + if (len < connection->root->maximum_request_length) { + req.length = len; - _cairo_xcb_connection_write (connection, vec, 2); + vec[0].iov_base = &req; + vec[0].iov_len = sizeof (req); + + len = 1; + } else { + prefix[0] = *(uint32_t *) &req; + prefix[1] = len + 1; + vec[0].iov_base = prefix; + vec[0].iov_len = sizeof (prefix); + vec[1].iov_base = (uint32_t *) &req + 1; + vec[1].iov_len = sizeof (req) - 4; + + len = 2; + } + + vec[len].iov_base = rects; + vec[len].iov_len = num_rects * sizeof (xcb_rectangle_t); + len++; + + _cairo_xcb_connection_write (connection, vec, len); } void diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c index 25e821e0..9da4eb3e 100644 --- a/src/cairo-xcb-connection.c +++ b/src/cairo-xcb-connection.c @@ -594,6 +594,8 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) const xcb_query_extension_reply_t *ext; cairo_status_t status; + CAIRO_MUTEX_INITIALIZE (); + CAIRO_MUTEX_LOCK (_cairo_xcb_connections_mutex); if (connections.next == NULL) { /* XXX _cairo_init () */ @@ -619,31 +621,29 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) goto unlock; _cairo_device_init (&connection->device, &_cairo_xcb_device_backend); - CAIRO_MUTEX_INIT (connection->shm_mutex); - CAIRO_MUTEX_INIT (connection->screens_mutex); connection->xcb_connection = xcb_connection; connection->has_socket = FALSE; - xcb_prefetch_extension_data (xcb_connection, &xcb_big_requests_id); - xcb_prefetch_extension_data (xcb_connection, &xcb_render_id); -#if CAIRO_HAS_XCB_SHM_FUNCTIONS - xcb_prefetch_extension_data (xcb_connection, &xcb_shm_id); -#endif -#if 0 - xcb_prefetch_extension_data (xcb_connection, &xcb_cairo_id); -#endif -#if CAIRO_HAS_XCB_DRM_FUNCTIONS - xcb_prefetch_extension_data (xcb_connection, &xcb_dri2_id); -#endif - - xcb_prefetch_maximum_request_length (xcb_connection); - cairo_list_init (&connection->fonts); cairo_list_init (&connection->screens); - cairo_list_add (&connection->link, &connections); + cairo_list_init (&connection->link); connection->xrender_formats = _cairo_hash_table_create (_xrender_formats_equal); + if (connection->xrender_formats == NULL) { + CAIRO_MUTEX_FINI (connection->device.mutex); + free (connection); + connection = NULL; + goto unlock; + } + connection->visual_to_xrender_format = _cairo_hash_table_create (_xrender_formats_equal); + if (connection->visual_to_xrender_format == NULL) { + _cairo_hash_table_destroy (connection->xrender_formats); + CAIRO_MUTEX_FINI (connection->device.mutex); + free (connection); + connection = NULL; + goto unlock; + } cairo_list_init (&connection->free_xids); _cairo_freepool_init (&connection->xid_pool, @@ -656,14 +656,34 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) connection->maximum_request_length = xcb_get_maximum_request_length (xcb_connection); + CAIRO_MUTEX_INIT (connection->shm_mutex); + CAIRO_MUTEX_INIT (connection->screens_mutex); + + CAIRO_MUTEX_LOCK (connection->device.mutex); + connection->flags = 0; + xcb_prefetch_extension_data (xcb_connection, &xcb_big_requests_id); + xcb_prefetch_extension_data (xcb_connection, &xcb_render_id); +#if CAIRO_HAS_XCB_SHM_FUNCTIONS + xcb_prefetch_extension_data (xcb_connection, &xcb_shm_id); +#endif +#if 0 + xcb_prefetch_extension_data (xcb_connection, &xcb_cairo_id); +#endif +#if CAIRO_HAS_XCB_DRM_FUNCTIONS + xcb_prefetch_extension_data (xcb_connection, &xcb_dri2_id); +#endif + + xcb_prefetch_maximum_request_length (xcb_connection); + connection->root = xcb_get_setup (xcb_connection); connection->render = NULL; ext = xcb_get_extension_data (xcb_connection, &xcb_render_id); if (ext != NULL && ext->present) { status = _cairo_xcb_connection_query_render (connection); if (unlikely (status)) { + CAIRO_MUTEX_UNLOCK (connection->device.mutex); _cairo_xcb_connection_destroy (connection); connection = NULL; goto unlock; @@ -696,6 +716,9 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) } #endif + CAIRO_MUTEX_UNLOCK (connection->device.mutex); + + cairo_list_add (&connection->link, &connections); unlock: CAIRO_MUTEX_UNLOCK (_cairo_xcb_connections_mutex); diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h index 1c8fc41a..e0669111 100644 --- a/src/cairo-xcb-private.h +++ b/src/cairo-xcb-private.h @@ -437,7 +437,7 @@ cairo_private void _cairo_xcb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font); -cairo_private void +cairo_private cairo_status_t _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst); cairo_private cairo_status_t diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c index 0c44e4d3..c80bf2d9 100644 --- a/src/cairo-xcb-screen.c +++ b/src/cairo-xcb-screen.c @@ -247,6 +247,11 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection, screen->connection = connection; screen->xcb_screen = xcb_screen; + _cairo_freelist_init (&screen->pattern_cache_entry_freelist, + sizeof (struct pattern_cache_entry)); + cairo_list_init (&screen->link); + cairo_list_init (&screen->surfaces); + if (connection->flags & CAIRO_XCB_HAS_DRI2) screen->device = _xcb_drm_device (xcb_connection, xcb_screen); else @@ -283,25 +288,21 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection, if (unlikely (status)) goto error_linear; - _cairo_freelist_init (&screen->pattern_cache_entry_freelist, - sizeof (struct pattern_cache_entry)); - cairo_list_add (&screen->link, &connection->screens); - cairo_list_init (&screen->surfaces); unlock: CAIRO_MUTEX_UNLOCK (connection->screens_mutex); return screen; -error_surface: - _cairo_cache_fini (&screen->surface_pattern_cache); error_linear: _cairo_cache_fini (&screen->linear_pattern_cache); +error_surface: + _cairo_cache_fini (&screen->surface_pattern_cache); error_screen: + CAIRO_MUTEX_UNLOCK (connection->screens_mutex); cairo_device_destroy (screen->device); free (screen); - CAIRO_MUTEX_UNLOCK (connection->screens_mutex); return NULL; } diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c index 2a903a07..3fbb0722 100644 --- a/src/cairo-xcb-surface-core.c +++ b/src/cairo-xcb-surface-core.c @@ -363,7 +363,6 @@ _cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target, { cairo_surface_t *source; cairo_xcb_pixmap_t *pixmap; - cairo_status_t status; source = pattern->surface; pixmap = (cairo_xcb_pixmap_t *) diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index c108bae2..9c2d4621 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -2335,11 +2335,22 @@ _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst, return status; } -void +cairo_status_t _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst) { xcb_gcontext_t gc; xcb_rectangle_t rect; + cairo_status_t status; + + status = _cairo_xcb_connection_acquire (dst->connection); + if (unlikely (status)) + return status; + + status = _cairo_xcb_connection_take_socket (dst->connection); + if (unlikely (status)) { + _cairo_xcb_connection_release (dst->connection); + return status; + } gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth); @@ -2353,7 +2364,10 @@ _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst) _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc); + _cairo_xcb_connection_release (dst->connection); + dst->deferred_clear = FALSE; + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -2405,8 +2419,13 @@ _clip_and_composite (cairo_xcb_surface_t *dst, return status; } - if (dst->deferred_clear) - _cairo_xcb_surface_clear (dst); + if (dst->deferred_clear) { + status = _cairo_xcb_surface_clear (dst); + if (unlikely (status)) { + _cairo_xcb_connection_release (dst->connection); + return status; + } + } _cairo_xcb_surface_ensure_picture (dst); @@ -2745,8 +2764,11 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst, if ((dst->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0) return _core_boxes (dst, op, src, boxes, antialias, clip, extents); - if (dst->deferred_clear) - _cairo_xcb_surface_clear (dst); + if (dst->deferred_clear) { + status = _cairo_xcb_surface_clear (dst); + if (unlikely (status)) + return status; + } /* Use a fast path if the boxes are pixel aligned */ status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents); diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index 7b728323..49b2dfbb 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -687,10 +687,11 @@ _cairo_xcb_surface_flush (void *abstract_surface) return surface->drm->backend->flush (surface->drm); if (likely (surface->fallback == NULL)) { + status = CAIRO_STATUS_SUCCESS; if (! surface->base.finished && surface->deferred_clear) - _cairo_xcb_surface_clear (surface); + status = _cairo_xcb_surface_clear (surface); - return CAIRO_STATUS_SUCCESS; + return status; } status = surface->base.status; diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c index 7e674bf0..84e9e339 100644 --- a/src/cairo-xlib-xcb-surface.c +++ b/src/cairo-xlib-xcb-surface.c @@ -346,7 +346,6 @@ static xcb_screen_t * _cairo_xcb_screen_from_root (xcb_connection_t *connection, xcb_window_t id) { - xcb_depth_iterator_t d; xcb_screen_iterator_t s; s = xcb_setup_roots_iterator (xcb_get_setup (connection)); |