mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-17 04:18:06 +02:00
[perf] Add pixman_region_init_rects and use in extract_region
Avoid O(N*N) loop in traps_extract_region by letting us hand pixman an array of rects all at once.
This commit is contained in:
parent
285b702ef6
commit
2477e57de5
8 changed files with 143 additions and 17 deletions
|
|
@ -36,7 +36,8 @@ cairo_perf_SOURCES = \
|
|||
world-map.c \
|
||||
world-map.h \
|
||||
zrusin.c \
|
||||
zrusin-another.h
|
||||
zrusin-another.h \
|
||||
long-dashed-lines.c
|
||||
|
||||
if CAIRO_HAS_WIN32_SURFACE
|
||||
cairo_perf_SOURCES += cairo-perf-win32.c
|
||||
|
|
|
|||
|
|
@ -420,5 +420,6 @@ cairo_perf_case_t perf_cases[] = {
|
|||
{ long_lines, 100, 100},
|
||||
{ unaligned_clip, 100, 100},
|
||||
{ rectangles, 512, 512},
|
||||
{ long_dashed_lines, 512, 512},
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -107,5 +107,6 @@ CAIRO_PERF_DECL (mosaic);
|
|||
CAIRO_PERF_DECL (long_lines);
|
||||
CAIRO_PERF_DECL (unaligned_clip);
|
||||
CAIRO_PERF_DECL (rectangles);
|
||||
CAIRO_PERF_DECL (long_dashed_lines);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
67
perf/long-dashed-lines.c
Normal file
67
perf/long-dashed-lines.c
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/*
|
||||
* Copyright © 2007 Mozilla Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static cairo_perf_ticks_t
|
||||
do_long_dashed_lines (cairo_t *cr, int width, int height)
|
||||
{
|
||||
double dash[2] = { 2.0, 2.0 };
|
||||
int i;
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
|
||||
cairo_set_dash (cr, dash, 2, 0.0);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
for (i = 0; i < height-1; i++) {
|
||||
double y0 = (double) i + 0.5;
|
||||
cairo_move_to (cr, 0.0, y0);
|
||||
cairo_line_to (cr, width, y0);
|
||||
}
|
||||
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
void
|
||||
long_dashed_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines);
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
#define pixman_region_copy _cairo_pixman_region_copy
|
||||
#define pixman_region_init _cairo_pixman_region_init
|
||||
#define pixman_region_init_rect _cairo_pixman_region_init_rect
|
||||
#define pixman_region_init_rects _cairo_pixman_region_init_rects
|
||||
#define pixman_region_init_with_extents _cairo_pixman_region_init_with_extents
|
||||
#define pixman_region_fini _cairo_pixman_region_fini
|
||||
#define pixman_region_empty _cairo_pixman_region_empty
|
||||
|
|
|
|||
|
|
@ -141,6 +141,8 @@ pixman_region_init_rect(pixman_region16_t *region,
|
|||
int x, int y, unsigned int width, unsigned int height);
|
||||
pixman_private void
|
||||
pixman_region_init_with_extents(pixman_region16_t *region, pixman_box16_t *extents);
|
||||
pixman_private pixman_region_status_t
|
||||
pixman_region_init_rects(pixman_region16_t *region, pixman_box16_t *boxes, int count);
|
||||
pixman_private void
|
||||
pixman_region_fini (pixman_region16_t *region);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ static pixman_region16_data_t pixman_brokendata = {0, 0};
|
|||
|
||||
static pixman_region_status_t
|
||||
pixman_break (pixman_region16_t *pReg);
|
||||
static pixman_region_status_t
|
||||
pixman_rect_alloc(pixman_region16_t * region, int n);
|
||||
|
||||
/*
|
||||
* The functions in this file implement the Region abstraction used extensively
|
||||
|
|
@ -311,6 +313,33 @@ pixman_region_init_with_extents(pixman_region16_t *region, pixman_box16_t *exten
|
|||
region->data = NULL;
|
||||
}
|
||||
|
||||
pixman_region_status_t
|
||||
pixman_region_init_rects(pixman_region16_t *region, pixman_box16_t *boxes, int count)
|
||||
{
|
||||
int overlap;
|
||||
|
||||
if (count == 1) {
|
||||
pixman_region_init_rect(region,
|
||||
boxes[0].x1,
|
||||
boxes[0].y1,
|
||||
boxes[0].x2 - boxes[0].x1,
|
||||
boxes[0].y2 - boxes[0].y1);
|
||||
return PIXMAN_REGION_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
pixman_region_init(region);
|
||||
if (!pixman_rect_alloc(region, count))
|
||||
return PIXMAN_REGION_STATUS_FAILURE;
|
||||
|
||||
/* Copy in the rects */
|
||||
memcpy (PIXREGION_RECTS(region), boxes, sizeof(pixman_box16_t) * count);
|
||||
region->data->numRects = count;
|
||||
|
||||
/* Validate */
|
||||
region->extents.x1 = region->extents.x2 = 0;
|
||||
return pixman_region_validate (region, &overlap);
|
||||
}
|
||||
|
||||
void
|
||||
pixman_region_fini (pixman_region16_t *region)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -597,7 +597,11 @@ cairo_int_status_t
|
|||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
int i;
|
||||
#define NUM_STATIC_BOXES 16
|
||||
pixman_box16_t static_boxes[NUM_STATIC_BOXES];
|
||||
pixman_box16_t *boxes;
|
||||
int i, box_count;
|
||||
pixman_region_status_t status;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++)
|
||||
if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
|
||||
|
|
@ -609,26 +613,46 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
pixman_region_init (region);
|
||||
if (traps->num_traps <= NUM_STATIC_BOXES) {
|
||||
boxes = static_boxes;
|
||||
} else {
|
||||
/*boxes = _cairo_malloc2 (traps->num_traps, sizeof(pixman_box16_t));*/
|
||||
boxes = malloc (traps->num_traps * sizeof(pixman_box16_t));
|
||||
|
||||
if (boxes == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
box_count = 0;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
|
||||
int y = _cairo_fixed_integer_part(traps->traps[i].top);
|
||||
int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
|
||||
int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y;
|
||||
int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
|
||||
int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
|
||||
int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
|
||||
int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);
|
||||
|
||||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator,
|
||||
* if we call pixman_region_union_rect(), it bizarrly fails on such
|
||||
* an empty rectangle, so skip them.
|
||||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
|
||||
* skip these.
|
||||
*/
|
||||
if (width == 0 || height == 0)
|
||||
continue;
|
||||
if (x1 == x2 || y1 == y2)
|
||||
continue;
|
||||
|
||||
if (pixman_region_union_rect (region, region,
|
||||
x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_fini (region);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
boxes[box_count].x1 = (short) x1;
|
||||
boxes[box_count].y1 = (short) y1;
|
||||
boxes[box_count].x2 = (short) x2;
|
||||
boxes[box_count].y2 = (short) y2;
|
||||
|
||||
box_count++;
|
||||
}
|
||||
|
||||
status = pixman_region_init_rects (region, boxes, box_count);
|
||||
|
||||
if (boxes != static_boxes)
|
||||
free (boxes);
|
||||
|
||||
if (status != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_fini (region);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue