[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