From 9930eefbbd4448d598faff12fc0f7127555c8c94 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 19 Sep 2008 10:54:13 +0100 Subject: [PATCH] Simple perf tweaks for a rectilinear Hilbert curve. Some tweaks to avoid stack copies and branches that save ~25% in _cairo_traps_tessellate_convex_quad(). --- src/cairo-bentley-ottmann.c | 36 +++---- src/cairo-slope.c | 6 +- src/cairo-surface-fallback.c | 12 +-- src/cairo-traps.c | 175 +++++++++++++---------------------- src/cairoint.h | 25 ++--- 5 files changed, 105 insertions(+), 149 deletions(-) diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c index 8e97f1fd5..e89e1fd73 100644 --- a/src/cairo-bentley-ottmann.c +++ b/src/cairo-bentley-ottmann.c @@ -1078,35 +1078,35 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left, /* Only emit trapezoids with positive height. */ if (fixed_top < fixed_bot) { - cairo_point_t left_top, left_bot, right_top, right_bot; + cairo_line_t left_line; + cairo_line_t right_line; cairo_fixed_t xmin = bo_traps->xmin; cairo_fixed_t ymin = bo_traps->ymin; fixed_top += ymin; fixed_bot += ymin; - left_top.x = left->top.x + xmin; - left_top.y = left->top.y + ymin; - right_top.x = right->top.x + xmin; - right_top.y = right->top.y + ymin; - left_bot.x = left->bottom.x + xmin; - left_bot.y = left->bottom.y + ymin; - right_bot.x = right->bottom.x + xmin; - right_bot.y = right->bottom.y + ymin; + left_line.p1.x = left->top.x + xmin; + left_line.p1.y = left->top.y + ymin; + right_line.p1.x = right->top.x + xmin; + right_line.p1.y = right->top.y + ymin; + + left_line.p2.x = left->bottom.x + xmin; + left_line.p2.y = left->bottom.y + ymin; + right_line.p2.x = right->bottom.x + xmin; + right_line.p2.y = right->bottom.y + ymin; /* Avoid emitting the trapezoid if it is obviously degenerate. * TODO: need a real collinearity test here for the cases * where the trapezoid is degenerate, yet the top and bottom * coordinates aren't equal. */ - if (left_top.x != right_top.x || - left_top.y != right_top.y || - left_bot.x != right_bot.x || - left_bot.y != right_bot.y) + if (left_line.p1.x != right_line.p1.x || + left_line.p1.y != right_line.p1.y || + left_line.p2.x != right_line.p2.x || + left_line.p2.y != right_line.p2.y) { - _cairo_traps_add_trap_from_points (bo_traps->traps, - fixed_top, - fixed_bot, - left_top, left_bot, - right_top, right_bot); + _cairo_traps_add_trap (bo_traps->traps, + fixed_top, fixed_bot, + &left_line, &right_line); #if DEBUG_PRINT_STATE printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) " diff --git a/src/cairo-slope.c b/src/cairo-slope.c index d3f0db42e..e3a070b38 100644 --- a/src/cairo-slope.c +++ b/src/cairo-slope.c @@ -37,7 +37,9 @@ #include "cairoint.h" void -_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b) +_cairo_slope_init (cairo_slope_t *slope, + const cairo_point_t *a, + const cairo_point_t *b) { slope->dx = b->x - a->x; slope->dy = b->y - a->y; @@ -62,7 +64,7 @@ _cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b) > 0 => a more positive than b */ int -_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b) +_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b) { cairo_fixed_48_16_t diff; diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 427554be3..c7c7b11fd 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -702,9 +702,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface, box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); - status = _cairo_traps_init_box (&traps, &box); - if (status) - return status; + _cairo_traps_init_box (&traps, &box); status = _clip_and_composite_trapezoids (source, op, @@ -830,7 +828,6 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); _cairo_traps_init (&traps); - _cairo_traps_limit (&traps, &box); status = _cairo_path_fixed_stroke_to_traps (path, @@ -838,10 +835,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, ctm, ctm_inverse, tolerance, &traps); - if (status) { - _cairo_traps_fini (&traps); - return status; - } + if (status) + goto FAIL; status = _clip_and_composite_trapezoids (source, op, @@ -850,6 +845,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface, surface->clip, antialias); +FAIL: _cairo_traps_fini (&traps); return status; diff --git a/src/cairo-traps.c b/src/cairo-traps.c index cdfdadd35..fabfecb09 100644 --- a/src/cairo-traps.c +++ b/src/cairo-traps.c @@ -41,13 +41,6 @@ /* private functions */ -static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps); - -static void -_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_line_t *left, cairo_line_t *right); - static int _compare_point_fixed_by_y (const void *av, const void *bv); @@ -94,12 +87,8 @@ _cairo_traps_clear (cairo_traps_t *traps) void _cairo_traps_fini (cairo_traps_t *traps) { - if (traps->traps && traps->traps != traps->traps_embedded) + if (traps->traps != traps->traps_embedded) free (traps->traps); - - traps->traps = NULL; - traps->traps_size = 0; - traps->num_traps = 0; } /** @@ -111,9 +100,9 @@ _cairo_traps_fini (cairo_traps_t *traps) * Initializes a #cairo_traps_t to contain a single rectangular * trapezoid. **/ -cairo_status_t +void _cairo_traps_init_box (cairo_traps_t *traps, - cairo_box_t *box) + const cairo_box_t *box) { _cairo_traps_init (traps); @@ -131,25 +120,41 @@ _cairo_traps_init_box (cairo_traps_t *traps, traps->traps[0].right.p2 = box->p2; traps->extents = *box; - - return traps->status; } -cairo_status_t -_cairo_traps_status (cairo_traps_t *traps) +/* make room for at least one more trap */ +static cairo_bool_t +_cairo_traps_grow (cairo_traps_t *traps) { - return traps->status; + cairo_trapezoid_t *new_traps; + int new_size = 2 * MAX (traps->traps_size, 16); + + if (traps->traps == traps->traps_embedded) { + new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); + if (new_traps != NULL) + memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); + } else { + new_traps = _cairo_realloc_ab (traps->traps, + new_size, sizeof (cairo_trapezoid_t)); + } + + if (new_traps == NULL) { + traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + return FALSE; + } + + traps->traps = new_traps; + traps->traps_size = new_size; + return TRUE; } -static void -_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, +void +_cairo_traps_add_trap (cairo_traps_t *traps, + cairo_fixed_t top, cairo_fixed_t bottom, cairo_line_t *left, cairo_line_t *right) { cairo_trapezoid_t *trap; - if (traps->status) - return; - /* Note: With the goofy trapezoid specification, (where an * arbitrary two points on the lines can specified for the left * and right edges), these limit checks would not work in @@ -209,9 +214,8 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo return; } - if (traps->num_traps >= traps->traps_size) { - traps->status = _cairo_traps_grow (traps); - if (traps->status) + if (traps->num_traps == traps->traps_size) { + if (! _cairo_traps_grow (traps)) return; } @@ -246,51 +250,6 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo traps->num_traps++; } -void -_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_point_t left_p1, cairo_point_t left_p2, - cairo_point_t right_p1, cairo_point_t right_p2) -{ - cairo_line_t left; - cairo_line_t right; - - if (traps->status) - return; - - left.p1 = left_p1; - left.p2 = left_p2; - - right.p1 = right_p1; - right.p2 = right_p2; - - _cairo_traps_add_trap (traps, top, bottom, &left, &right); -} - -/* make room for at least one more trap */ -static cairo_status_t -_cairo_traps_grow (cairo_traps_t *traps) -{ - cairo_trapezoid_t *new_traps; - int new_size = 2 * MAX (traps->traps_size, 16); - - if (traps->traps == traps->traps_embedded) { - new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t)); - if (new_traps) - memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded)); - } else { - new_traps = _cairo_realloc_ab (traps->traps, - new_size, sizeof (cairo_trapezoid_t)); - } - - if (new_traps == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - traps->traps = new_traps; - traps->traps_size = new_size; - - return CAIRO_STATUS_SUCCESS; -} - static int _compare_point_fixed_by_y (const void *av, const void *bv) { @@ -379,7 +338,8 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, * quadrilateral. We would not benefit from having any distinct * implementation of triangle vs. quadrilateral tessellation here. */ cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) +_cairo_traps_tessellate_triangle (cairo_traps_t *traps, + const cairo_point_t t[3]) { cairo_point_t quad[4]; @@ -392,12 +352,15 @@ _cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]) } cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) +_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, + const cairo_point_t q[4]) { int a, b, c, d; int i; cairo_slope_t ab, ad; cairo_bool_t b_left_of_d; + cairo_line_t left; + cairo_line_t right; /* Choose a as a point with minimal y */ a = 0; @@ -462,15 +425,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * | / \| \ \ c.y d.y cd ad * d d d */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[b], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[c].y, - q[b], q[c], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[c].y, q[d].y, - q[c], q[d], q[a], q[d]); + left.p1 = q[a]; left.p2 = q[b]; + right.p1 = q[a]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + left.p1 = q[b]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); + left.p1 = q[c]; left.p2 = q[d]; + _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); } else { /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad)) * @@ -482,15 +443,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * / / |/ \ | c.y d.y ad cd * d d d */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[d], q[a], q[b]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[c].y, - q[a], q[d], q[b], q[c]); - _cairo_traps_add_trap_from_points (traps, - q[c].y, q[d].y, - q[a], q[d], q[c], q[d]); + left.p1 = q[a]; left.p2 = q[d]; + right.p1 = q[a]; right.p2 = q[b]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + right.p1 = q[b]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right); + right.p1 = q[c]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right); } } else { if (b_left_of_d) { @@ -504,15 +463,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * // \ / \| d.y c.y bc dc * c c c */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[b], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[d].y, - q[b], q[c], q[a], q[d]); - _cairo_traps_add_trap_from_points (traps, - q[d].y, q[c].y, - q[b], q[c], q[d], q[c]); + left.p1 = q[a]; left.p2 = q[b]; + right.p1 = q[a]; right.p2 = q[d]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + left.p1 = q[b]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); + right.p1 = q[d]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); } else { /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad)) * @@ -524,15 +481,13 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]) * |/ \ / \\ d.y c.y dc bc * c c c */ - _cairo_traps_add_trap_from_points (traps, - q[a].y, q[b].y, - q[a], q[d], q[a], q[b]); - _cairo_traps_add_trap_from_points (traps, - q[b].y, q[d].y, - q[a], q[d], q[b], q[c]); - _cairo_traps_add_trap_from_points (traps, - q[d].y, q[c].y, - q[d], q[c], q[b], q[c]); + left.p1 = q[a]; left.p2 = q[d]; + right.p1 = q[a]; right.p2 = q[b]; + _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right); + right.p1 = q[b]; right.p2 = q[c]; + _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right); + left.p1 = q[d]; left.p2 = q[c]; + _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right); } } diff --git a/src/cairoint.h b/src/cairoint.h index 80fde84bf..376909403 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2168,9 +2168,9 @@ cairo_private cairo_bool_t _cairo_traps_get_limit (cairo_traps_t *traps, cairo_box_t *limits); -cairo_private cairo_status_t +cairo_private void _cairo_traps_init_box (cairo_traps_t *traps, - cairo_box_t *box); + const cairo_box_t *box); cairo_private void _cairo_traps_clear (cairo_traps_t *traps); @@ -2178,22 +2178,23 @@ _cairo_traps_clear (cairo_traps_t *traps); cairo_private void _cairo_traps_fini (cairo_traps_t *traps); -cairo_private cairo_status_t -_cairo_traps_status (cairo_traps_t *traps); +#define _cairo_traps_status(T) (T)->status cairo_private void _cairo_traps_translate (cairo_traps_t *traps, int x, int y); cairo_private cairo_status_t -_cairo_traps_tessellate_triangle (cairo_traps_t *traps, cairo_point_t t[3]); +_cairo_traps_tessellate_triangle (cairo_traps_t *traps, + const cairo_point_t t[3]); cairo_private cairo_status_t -_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, cairo_point_t q[4]); +_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps, + const cairo_point_t q[4]); cairo_private void -_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom, - cairo_point_t left_p1, cairo_point_t left_p2, - cairo_point_t right_p1, cairo_point_t right_p2); +_cairo_traps_add_trap (cairo_traps_t *traps, + cairo_fixed_t top, cairo_fixed_t bottom, + cairo_line_t *left, cairo_line_t *right); cairo_private cairo_status_t _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, @@ -2225,10 +2226,12 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps, /* cairo-slope.c */ cairo_private void -_cairo_slope_init (cairo_slope_t *slope, cairo_point_t *a, cairo_point_t *b); +_cairo_slope_init (cairo_slope_t *slope, + const cairo_point_t *a, + const cairo_point_t *b); cairo_private int -_cairo_slope_compare (cairo_slope_t *a, cairo_slope_t *b); +_cairo_slope_compare (const cairo_slope_t *a, const cairo_slope_t *b); /* cairo-pattern.c */