[cairo-commit] 4 commits - src/cairo-xcb-private.h src/cairo-xcb-shm.c src/cairo-xcb-surface.c src/cairo-xcb-surface-core.c src/cairo-xcb-surface-render.c
Uli Schlachter
psychon at kemper.freedesktop.org
Mon Jan 31 10:23:17 PST 2011
src/cairo-xcb-private.h | 7 ++
src/cairo-xcb-shm.c | 10 +++
src/cairo-xcb-surface-core.c | 111 ++++++++++++++++++++++++++---------------
src/cairo-xcb-surface-render.c | 61 ----------------------
src/cairo-xcb-surface.c | 3 -
5 files changed, 91 insertions(+), 101 deletions(-)
New commits:
commit 2e81f79e95a60a706f517b1bd989039b302dba8a
Author: Uli Schlachter <psychon at znc.in>
Date: Sun Jan 30 16:29:50 2011 +0100
xcb: Use a normal image surface if SHM fails
If we can't use SHM, we still have PutImage. So instead of returning the error
to the caller, it makes sense to retry with a normal image surface.
Signed-off-by: Uli Schlachter <psychon at znc.in>
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 33e42ce..c350f6f 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -159,8 +159,7 @@ _cairo_xcb_surface_create_similar_image (cairo_xcb_surface_t *other,
pixman_format,
width, height,
&image);
- if (_cairo_status_is_error (status))
- return _cairo_surface_create_in_error (status);
+ /* Ignore errors and fall through */
}
#endif
commit 72788a06604ca50fe14354b92d2fd3b186a959bb
Author: Uli Schlachter <psychon at znc.in>
Date: Sun Jan 30 15:43:00 2011 +0100
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 at znc.in>
diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c
index bcfb7a1..6801e3f 100644
--- a/src/cairo-xcb-surface-core.c
+++ b/src/cairo-xcb-surface-core.c
@@ -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;
-
- 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
+ status = _cairo_xcb_shm_image_create_shm (connection,
+ pixman_format,
+ width,
+ height,
+ image_out,
+ shm_info_out);
- 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;
}
commit 48cb9186a23923ad5e9e3c31a193ab3d99ec6c5d
Author: Uli Schlachter <psychon at znc.in>
Date: Sun Jan 30 15:35:36 2011 +0100
xcb: Remove a duplicate static function
Both cairo-xcb-surface-core.c and cairo-xcb-surface-render.c contained an
identical definition of _cairo_xcb_shm_image_create. This commits removes the
one from cairo-xcb-surface-render.c and adds the other one to
cairo-xcb-private.h.
Signed-off-by: Uli Schlachter <psychon at znc.in>
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index b6b25ce..0692f59 100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -534,6 +534,13 @@ _cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t *connection,
xcb_rectangle_t *rectangles);
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
+cairo_private cairo_status_t
+_cairo_xcb_shm_image_create (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_private uint32_t
_cairo_xcb_connection_shm_attach (cairo_xcb_connection_t *connection,
uint32_t id,
diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c
index b752a33..bcfb7a1 100644
--- a/src/cairo-xcb-surface-core.c
+++ b/src/cairo-xcb-surface-core.c
@@ -140,7 +140,7 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
return surface;
}
-static cairo_status_t
+cairo_status_t
_cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
pixman_format_code_t pixman_format,
int width, int height,
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 9a059fc..80cd016 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -727,67 +727,6 @@ _cairo_xcb_solid_picture (cairo_xcb_surface_t *target,
return picture;
}
-static cairo_status_t
-_cairo_xcb_shm_image_create (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;
-
-#if CAIRO_HAS_XCB_SHM_FUNCTIONS
- if ((connection->flags & CAIRO_XCB_HAS_SHM)) {
- size_t size, stride;
-
- 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) {
- image = _cairo_image_surface_create_with_pixman_format (NULL,
- pixman_format,
- width, height,
- 0);
- status = image->status;
- if (unlikely (status))
- return status;
- }
-
- *image_out = (cairo_image_surface_t *) image;
- *shm_info_out = shm_info;
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_xcb_picture_t *
_render_to_picture (cairo_xcb_surface_t *target,
const cairo_pattern_t *pattern,
commit 274289d8c6c8a04060cd9c3a3cf0f819899c1353
Author: Uli Schlachter <psychon at znc.in>
Date: Sun Jan 30 16:19:50 2011 +0100
xcb: Limit the amount of SHM used
Without this, one could make cairo attach to lots of shared memory. I managed to
make cairo use 1.5 GiB of shared memory according to top. This was done by
disabling XRENDER and thus causing lots of fallbacks.
Signed-off-by: Uli Schlachter <psychon at znc.in>
diff --git a/src/cairo-xcb-shm.c b/src/cairo-xcb-shm.c
index c3e3d35..55be475 100644
--- a/src/cairo-xcb-shm.c
+++ b/src/cairo-xcb-shm.c
@@ -43,6 +43,8 @@
#include <sys/shm.h>
#include <errno.h>
+#define CAIRO_MAX_SHM_MEMORY (16*1024*1024)
+
/* a simple buddy allocator for memory pools
* XXX fragmentation? use Doug Lea's malloc?
*/
@@ -489,6 +491,7 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection,
cairo_xcb_shm_info_t *shm_info;
cairo_xcb_shm_mem_pool_t *pool, *next;
size_t bytes, maxbits = 16, minbits = 8;
+ size_t shm_allocated = 0;
void *mem = NULL;
cairo_status_t status;
@@ -513,9 +516,16 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection,
_cairo_xcb_connection_shm_detach (connection,
pool->shmseg);
_cairo_xcb_shm_mem_pool_destroy (pool);
+ } else {
+ shm_allocated += pool->max_bytes;
}
}
+ if (unlikely (shm_allocated >= CAIRO_MAX_SHM_MEMORY)) {
+ CAIRO_MUTEX_UNLOCK (connection->shm_mutex);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
pool = malloc (sizeof (cairo_xcb_shm_mem_pool_t));
if (unlikely (pool == NULL)) {
CAIRO_MUTEX_UNLOCK (connection->shm_mutex);
More information about the cairo-commit
mailing list