[cairo-commit] 3 commits - configure.in src/cairo-atomic-private.h src/cairo-path-fill.c src/cairo-path-fixed.c src/cairo-path-fixed-private.h src/cairo-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Nov 5 00:51:16 PST 2007


 configure.in                   |   15 ++++++
 src/cairo-atomic-private.h     |   20 ++++++---
 src/cairo-path-fill.c          |    2 
 src/cairo-path-fixed-private.h |   20 +++++----
 src/cairo-path-fixed.c         |   89 ++++++++++++++++++++++++-----------------
 src/cairo-surface.c            |   48 ++++++++++++----------
 6 files changed, 126 insertions(+), 68 deletions(-)

New commits:
commit 901b0c97523a2da00ccf91cf4cee3bf55ce989b5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Nov 4 11:55:25 2007 +0000

    [cairo-path-fixed] Exponentially enlarge cairo_path_buf_t.
    
    Allocate subsequent path bufs twice as large as the previous buf,
    whilst still embedding a small initial buf into cairo_path_fixed_t
    that handles the most frequent usage.

diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index 2542029..f8e4ab0 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -214,7 +214,7 @@ static cairo_int_status_t
 _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
 				  cairo_traps_t		*traps)
 {
-    cairo_path_buf_t *buf = path->buf_head;
+    cairo_path_buf_t *buf = &path->buf_head.base;
     int final;
 
     /* Ensure the path has the operators we expect for a rectangular path.
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 6e1300a..f506c34 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -46,18 +46,24 @@ enum cairo_path_op {
 typedef char cairo_path_op_t;
 
 /* make cairo_path_fixed fit a 512 bytes.  about 50 items */
-#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \
-			   / (sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
+#define CAIRO_PATH_BUF_SIZE ((512 - 4 * sizeof (void*) - sizeof (cairo_path_buf_t)) \
+			   / (2 * sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
 
 typedef struct _cairo_path_buf {
     struct _cairo_path_buf *next, *prev;
+    int buf_size;
     int num_ops;
     int num_points;
 
-    cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
-    cairo_point_t points[CAIRO_PATH_BUF_SIZE];
-
+    cairo_path_op_t *op;
+    cairo_point_t *points;
 } cairo_path_buf_t;
+typedef struct _cairo_path_buf_fixed {
+    cairo_path_buf_t base;
+
+    cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
+    cairo_point_t points[2 * CAIRO_PATH_BUF_SIZE];
+} cairo_path_buf_fixed_t;
 
 struct _cairo_path_fixed {
     cairo_point_t last_move_point;
@@ -65,8 +71,8 @@ struct _cairo_path_fixed {
     unsigned int has_current_point	: 1;
     unsigned int has_curve_to		: 1;
 
-    cairo_path_buf_t *buf_tail;
-    cairo_path_buf_t  buf_head[1];
+    cairo_path_buf_t       *buf_tail;
+    cairo_path_buf_fixed_t  buf_head;
 };
 
 #endif /* CAIRO_PATH_FIXED_PRIVATE_H */
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 6aaa2ee..05f8144 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -52,7 +52,7 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
 			   cairo_path_buf_t   *buf);
 
 static cairo_path_buf_t *
-_cairo_path_buf_create (void);
+_cairo_path_buf_create (int buf_size);
 
 static void
 _cairo_path_buf_destroy (cairo_path_buf_t *buf);
@@ -69,12 +69,15 @@ _cairo_path_buf_add_points (cairo_path_buf_t *buf,
 void
 _cairo_path_fixed_init (cairo_path_fixed_t *path)
 {
-    path->buf_head->next = NULL;
-    path->buf_head->prev = NULL;
-    path->buf_tail = path->buf_head;
+    path->buf_head.base.next = NULL;
+    path->buf_head.base.prev = NULL;
+    path->buf_tail = &path->buf_head.base;
 
-    path->buf_head->num_ops = 0;
-    path->buf_head->num_points = 0;
+    path->buf_head.base.num_ops = 0;
+    path->buf_head.base.num_points = 0;
+    path->buf_head.base.buf_size = CAIRO_PATH_BUF_SIZE;
+    path->buf_head.base.op = path->buf_head.op;
+    path->buf_head.base.points = path->buf_head.points;
 
     path->current_point.x = 0;
     path->current_point.y = 0;
@@ -90,27 +93,32 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
     cairo_path_buf_t *buf, *other_buf;
 
     _cairo_path_fixed_init (path);
+
     path->current_point = other->current_point;
     path->has_current_point = other->has_current_point;
     path->has_curve_to = other->has_curve_to;
     path->last_move_point = other->last_move_point;
 
-    path->buf_head->num_ops = other->buf_head->num_ops;
-    path->buf_head->num_points = other->buf_head->num_points;
-    memcpy (path->buf_head->op, other->buf_head->op,
-	    other->buf_head->num_ops * sizeof (other->buf_head->op[0]));
-    memcpy (path->buf_head->points, other->buf_head->points,
-	    other->buf_head->num_points * sizeof (other->buf_head->points[0]));
-    for (other_buf = other->buf_head->next;
+    path->buf_head.base.num_ops = other->buf_head.base.num_ops;
+    path->buf_head.base.num_points = other->buf_head.base.num_points;
+    path->buf_head.base.buf_size = other->buf_head.base.buf_size;
+    memcpy (path->buf_head.op, other->buf_head.base.op,
+	    other->buf_head.base.num_ops * sizeof (other->buf_head.op[0]));
+    memcpy (path->buf_head.points, other->buf_head.points,
+	    other->buf_head.base.num_points * sizeof (other->buf_head.points[0]));
+    for (other_buf = other->buf_head.base.next;
 	 other_buf;
 	 other_buf = other_buf->next)
     {
-	buf = _cairo_path_buf_create ();
+	buf = _cairo_path_buf_create (other_buf->buf_size);
 	if (buf == NULL) {
 	    _cairo_path_fixed_fini (path);
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 	}
-	memcpy (buf, other_buf, sizeof (cairo_path_buf_t));
+	memcpy (buf->op, other_buf->op,
+		buf->num_ops * sizeof (buf->op[0]));
+	memcpy (buf->points, other_buf->points,
+		buf->num_points * sizeof (buf->points[0]));
 	_cairo_path_fixed_add_buf (path, buf);
     }
 
@@ -137,17 +145,17 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path)
 {
     cairo_path_buf_t *buf;
 
-    buf = path->buf_head->next;
+    buf = path->buf_head.base.next;
     while (buf) {
 	cairo_path_buf_t *this = buf;
 	buf = buf->next;
 	_cairo_path_buf_destroy (this);
     }
-    path->buf_head->next = NULL;
-    path->buf_head->prev = NULL;
-    path->buf_tail = path->buf_head;
-    path->buf_head->num_ops = 0;
-    path->buf_head->num_points = 0;
+    path->buf_head.base.next = NULL;
+    path->buf_head.base.prev = NULL;
+    path->buf_tail = &path->buf_head.base;
+    path->buf_head.base.num_ops = 0;
+    path->buf_head.base.num_points = 0;
 
     path->has_current_point = FALSE;
     path->has_curve_to = FALSE;
@@ -360,20 +368,20 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
 		       cairo_point_t	  *points,
 		       int		   num_points)
 {
-    if ((unsigned int) path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
-	(unsigned int) path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
-    {
-	cairo_path_buf_t *buf;
+    cairo_path_buf_t *buf = path->buf_tail;
 
-	buf = _cairo_path_buf_create ();
+    if (buf->num_ops + 1 > buf->buf_size ||
+	buf->num_points + num_points > 2 * buf->buf_size)
+    {
+	buf = _cairo_path_buf_create (buf->buf_size * 2);
 	if (buf == NULL)
 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
 	_cairo_path_fixed_add_buf (path, buf);
     }
 
-    _cairo_path_buf_add_op (path->buf_tail, op);
-    _cairo_path_buf_add_points (path->buf_tail, points, num_points);
+    _cairo_path_buf_add_op (buf, op);
+    _cairo_path_buf_add_points (buf, points, num_points);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -390,17 +398,23 @@ _cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
 }
 
 static cairo_path_buf_t *
-_cairo_path_buf_create (void)
+_cairo_path_buf_create (int buf_size)
 {
     cairo_path_buf_t *buf;
 
-    buf = malloc (sizeof (cairo_path_buf_t));
-
+    buf = _cairo_malloc_ab_plus_c (buf_size,
+	                           sizeof (cairo_path_op_t) +
+				   2 * sizeof (cairo_point_t),
+				   sizeof (cairo_path_buf_t));
     if (buf) {
 	buf->next = NULL;
 	buf->prev = NULL;
 	buf->num_ops = 0;
 	buf->num_points = 0;
+	buf->buf_size = buf_size;
+
+	buf->op = (cairo_path_op_t *) (buf + 1);
+	buf->points = (cairo_point_t *) (buf->op + buf_size);
     }
 
     return buf;
@@ -454,7 +468,7 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t			*path,
     cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
     int step = forward ? 1 : -1;
 
-    for (buf = forward ? path->buf_head : path->buf_tail;
+    for (buf = forward ? &path->buf_head.base : path->buf_tail;
 	 buf;
 	 buf = forward ? buf->next : buf->prev)
     {
@@ -512,7 +526,7 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
 				    cairo_fixed_t scalex,
 				    cairo_fixed_t scaley)
 {
-    cairo_path_buf_t *buf = path->buf_head;
+    cairo_path_buf_t *buf = &path->buf_head.base;
     int i;
 
     while (buf) {
@@ -569,14 +583,19 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
 	path->last_move_point.y != other->last_move_point.y)
 	return FALSE;
 
-    other_buf = other->buf_head;
-    for (path_buf = path->buf_head; path_buf != NULL; path_buf = path_buf->next) {
+    other_buf = &other->buf_head.base;
+    for (path_buf = &path->buf_head.base;
+	 path_buf != NULL;
+	 path_buf = path_buf->next)
+    {
 	if (other_buf == NULL ||
 	    path_buf->num_ops != other_buf->num_ops ||
 	    path_buf->num_points != other_buf->num_points ||
 	    memcmp (path_buf->op, other_buf->op, path_buf->num_ops) != 0 ||
 	    memcmp (path_buf->points, other_buf->points, path_buf->num_points != 0))
+	{
 	    return FALSE;
+	}
 	other_buf = other_buf->next;
     }
     return TRUE;
commit 92a18464bae40b19a26402eb2aa4950cac04c3a0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Nov 3 10:41:55 2007 +0000

    [cairo-surface] Avoid allocation for common case of 1 box.
    
    _cairo_surface_fill_region(): avoid allocating the array of boxes if we
    know that the region only contains one box and is therefore defined by its
    extents.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 9e1acdc..97a8b9e 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1285,41 +1285,49 @@ _cairo_surface_fill_region (cairo_surface_t	   *surface,
 			    cairo_region_t         *region)
 {
     int num_boxes;
-    cairo_box_int_t *boxes;
+    cairo_box_int_t *boxes = NULL;
     cairo_rectangle_int_t stack_rects[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_rectangle_int_t)];
-    cairo_rectangle_int_t *rects;
+    cairo_rectangle_int_t *rects = stack_rects;
     cairo_status_t status;
     int i;
 
     assert (! surface->is_snapshot);
 
-    status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
-    if (status)
-	return status;
+    num_boxes = _cairo_region_num_boxes (region);
 
     if (num_boxes == 0)
 	return CAIRO_STATUS_SUCCESS;
 
-    rects = stack_rects;
-    if (num_boxes > ARRAY_LENGTH (stack_rects)) {
-	rects = _cairo_malloc_ab (num_boxes, sizeof (cairo_rectangle_int_t));
-	if (!rects) {
-	    _cairo_region_boxes_fini (region, boxes);
-	    return _cairo_surface_set_error (surface, CAIRO_STATUS_NO_MEMORY);
-        }
-    }
+    /* handle the common case of a single box without allocation */
+    if (num_boxes > 1) {
+	status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
+	if (status)
+	    return status;
+
+	if (num_boxes > ARRAY_LENGTH (stack_rects)) {
+	    rects = _cairo_malloc_ab (num_boxes,
+		                      sizeof (cairo_rectangle_int_t));
+	    if (!rects) {
+		_cairo_region_boxes_fini (region, boxes);
+		return _cairo_surface_set_error (surface,
+			                         CAIRO_STATUS_NO_MEMORY);
+	    }
+	}
 
-    for (i = 0; i < num_boxes; i++) {
-	rects[i].x = boxes[i].p1.x;
-	rects[i].y = boxes[i].p1.y;
-	rects[i].width = boxes[i].p2.x - boxes[i].p1.x;
-	rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
-    }
+	for (i = 0; i < num_boxes; i++) {
+	    rects[i].x = boxes[i].p1.x;
+	    rects[i].y = boxes[i].p1.y;
+	    rects[i].width = boxes[i].p2.x - boxes[i].p1.x;
+	    rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
+	}
+    } else
+	_cairo_region_get_extents (region, &rects[0]);
 
     status =  _cairo_surface_fill_rectangles (surface, op,
 					      color, rects, num_boxes);
 
-    _cairo_region_boxes_fini (region, boxes);
+    if (boxes != NULL)
+	_cairo_region_boxes_fini (region, boxes);
 
     if (rects != stack_rects)
 	free (rects);
commit e60a7c39cdcdfd474c4f6cc3b4612870726f55dc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 25 10:24:01 2007 +0100

    [cairo-atomic] Check whether we can access int/pointers atomically.
    
    Add a configure check to determine whether the host cpu can read/write
    cairo_atomic_t without an explicit memory barrier, and update the macros
    within cairo-atomic-private.h to reflect this knowledge.

diff --git a/configure.in b/configure.in
index f85e33c..7fbe408 100644
--- a/configure.in
+++ b/configure.in
@@ -103,6 +103,21 @@ AC_TRY_LINK([int atomic_add(int i) { return __sync_fetch_and_add (&i, 1); }], []
 
 AC_MSG_RESULT([$cairo_atomic_primitives])
 
+AC_MSG_CHECKING([whether atomic ops require a memory barrier])
+case $host_cpu in
+    i?86)
+	cairo_atomic_op_needs_memory_barrier="no"
+	;;
+    *)
+	cairo_atomic_op_needs_memory_barrier="yes"
+	;;
+esac
+if test "x$cairo_atomic_op_needs_memory_barrier" = "xyes"; then
+    AC_DEFINE_UNQUOTED(CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER, 1,
+		       [whether Cairo needs memory barriers around atomic ops])
+fi
+AC_MSG_RESULT([$cairo_atomic_op_needs_memory_barrier])
+
 dnl ===========================================================================
 
 AC_CHECK_LIBM
diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index fbf1d9a..85fe956 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -51,9 +51,6 @@ typedef int cairo_atomic_int_t;
 
 # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
 # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
-# define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
-
 # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
 
 #else
@@ -71,16 +68,29 @@ cairo_private cairo_bool_t
 _cairo_atomic_int_dec_and_test (int *x);
 
 cairo_private int
+_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
+
+#endif
+
+
+#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
+
+# include "cairo-compiler-private.h"
+
+cairo_private int
 _cairo_atomic_int_get (int *x);
 
 cairo_private void
 _cairo_atomic_int_set (int *x, int value);
 
-cairo_private int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
+#else
+
+# define _cairo_atomic_int_get(x) (*x)
+# define _cairo_atomic_int_set(x, value) ((*x) = value)
 
 #endif
 
+
 #define _cairo_status_set_error(status, err) do { \
     /* hide compiler warnings about cairo_status_t != int (gcc treats its as \
      * an unsigned integer instead, and about ignoring the return value. */  \


More information about the cairo-commit mailing list