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().
This commit is contained in:
Chris Wilson 2008-09-19 10:54:13 +01:00
parent 27ee8dd9c6
commit 9930eefbbd
5 changed files with 105 additions and 149 deletions

View file

@ -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) "

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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 */