mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-18 06:00:47 +01:00
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:
parent
27ee8dd9c6
commit
9930eefbbd
5 changed files with 105 additions and 149 deletions
|
|
@ -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) "
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue