[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