[cairo-commit] 2 commits - perf/cairo-perf.c perf/cairo-perf.h perf/long-lines.c perf/Makefile.am src/cairo-surface-fallback.c

Carl Worth cworth at kemper.freedesktop.org
Fri Jan 5 16:52:09 PST 2007


 perf/Makefile.am             |    1 
 perf/cairo-perf.c            |    1 
 perf/cairo-perf.h            |    1 
 perf/long-lines.c            |  117 +++++++++++++++++++++++++++++++++++++++++++
 src/cairo-surface-fallback.c |   28 ++++++----
 5 files changed, 138 insertions(+), 10 deletions(-)

New commits:
diff-tree c96a71e709e537f690da6d4a184aa4c64fe11028 (from cc11c264ec0c7d6586c9349bcdbe3f4156e7ab6e)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Jan 5 15:56:06 2007 -0800

    Restrict _clip_and_composite_trapezoids to destination extents
    
    This is a fix for a huge performance bug (as measured by perf/long-lines).
    Previously, if no explicit clip was set, _clip_and_composite_trapezoids
    would allocate a mask as large as the trapezoids and rasterize into it.
    With this fix, it restricts the mask by the extents of the destination
    surface.
    
    This doesn't address the identical performance problem with the xlib
    backend, which is due to a very similar bug in the X server.
    
    image-rgb  long-lines-uncropped-100 465.42 -> 5.03: 92.66x speedup
    █████████████████████████████████████████████▉
    image-rgba long-lines-uncropped-100 460.80 -> 5.02: 91.87x speedup
    █████████████████████████████████████████████▍

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 02033c8..1a7d666 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -511,7 +511,7 @@ _clip_and_composite_trapezoids (cairo_pa
 				cairo_antialias_t antialias)
 {
     cairo_status_t status;
-    pixman_region16_t *trap_region;
+    pixman_region16_t *trap_region = NULL;
     pixman_region16_t *clear_region = NULL;
     cairo_rectangle_int16_t extents;
     cairo_composite_traps_info_t traps_info;
@@ -519,30 +519,38 @@ _clip_and_composite_trapezoids (cairo_pa
     if (traps->num_traps == 0)
 	return CAIRO_STATUS_SUCCESS;
 
+    status = _cairo_surface_get_extents (dst, &extents);
+    if (status)
+	return status;
+
     status = _cairo_traps_extract_region (traps, &trap_region);
     if (status)
 	return status;
 
     if (_cairo_operator_bounded_by_mask (op))
     {
+	cairo_rectangle_int16_t trap_extents;
 	if (trap_region) {
 	    status = _cairo_clip_intersect_to_region (clip, trap_region);
-	    _cairo_region_extents_rectangle (trap_region, &extents);
+	    if (status)
+		goto out;
+
+	    _cairo_region_extents_rectangle (trap_region, &trap_extents);
 	} else {
-	    cairo_box_t trap_extents;
-	    _cairo_traps_extents (traps, &trap_extents);
-	    _cairo_box_round_to_rectangle (&trap_extents, &extents);
-	    status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+	    cairo_box_t trap_box;
+	    _cairo_traps_extents (traps, &trap_box);
+	    _cairo_box_round_to_rectangle (&trap_box, &trap_extents);
 	}
+
+	_cairo_rectangle_intersect (&extents, &trap_extents);
+	status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+	if (status)
+	    goto out;
     }
     else
     {
 	cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
 
-	status = _cairo_surface_get_extents (dst, &extents);
-	if (status)
-	    return status;
-
 	if (trap_region && !clip_surface) {
 	    /* If we optimize drawing with an unbounded operator to
 	     * _cairo_surface_fill_rectangles() or to drawing with a
diff-tree cc11c264ec0c7d6586c9349bcdbe3f4156e7ab6e (from 11dd9eab693297961b988a73e22bf4d5850eb485)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Jan 3 16:27:52 2007 -0800

    Add long-lines perf case
    
    This shows some very bad slowness for lines that are mostly
    offscreen (like 100x slower than just drawing the visible
    portion).

diff --git a/perf/Makefile.am b/perf/Makefile.am
index 7e53420..0d5f244 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -21,6 +21,7 @@ cairo_perf_SOURCES =		\
 	cairo-stats.h		\
 	box-outline.c		\
 	fill.c			\
+	long-lines.c		\
 	paint.c			\
 	stroke.c		\
 	subimage_copy.c		\
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 1b63635..0708ed9 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -327,5 +327,6 @@ cairo_perf_case_t perf_cases[] = {
     { world_map, 800, 800},
     { box_outline, 100, 100},
     { mosaic, 800, 800 },
+    { long_lines, 100, 100},
     { NULL }
 };
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index bf56e8b..2bfd665 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -103,5 +103,6 @@ CAIRO_PERF_DECL (zrusin);
 CAIRO_PERF_DECL (world_map);
 CAIRO_PERF_DECL (box_outline);
 CAIRO_PERF_DECL (mosaic);
+CAIRO_PERF_DECL (long_lines);
 
 #endif
diff --git a/perf/long-lines.c b/perf/long-lines.c
new file mode 100644
index 0000000..62e8e16
--- /dev/null
+++ b/perf/long-lines.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-perf.h"
+
+/* This test case is designed to illustrate a performance bug in
+ * drawing very long lines, where most of the line is out of bounds of
+ * the destination surface, (but some portion of the line is
+ * visibile). These results are in the "long-lines-uncropped" report.
+ *
+ * For comparison, this test also renders the visible portions of the
+ * same lines, (this is the "long-lines-cropped" report).
+ */
+
+typedef enum { LONG_LINES_UNCROPPED, LONG_LINES_CROPPED } long_lines_crop_t;
+#define NUM_LINES    20
+#define LONG_FACTOR  50.0
+
+static cairo_perf_ticks_t
+do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
+{
+    int i;
+    double x, y, dx, dy, min_x, min_y, max_x, max_y;
+    double outer_width, outer_height;
+
+    cairo_save (cr);
+
+    cairo_translate (cr, width / 2, height / 2);
+
+    if (crop == LONG_LINES_UNCROPPED) {
+	outer_width = LONG_FACTOR * width;
+	outer_height = LONG_FACTOR * height;
+	cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */
+    } else {
+	outer_width = width;
+	outer_height = height;
+	cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
+    }
+
+    min_x = x = - outer_width / 2.0;
+    min_y = y = - outer_height / 2.0;
+    max_x = outer_width / 2.0;
+    max_y = outer_width / 2.0;
+    dx = outer_width / NUM_LINES;
+    dy = outer_height / NUM_LINES;
+
+    cairo_perf_timer_start ();
+
+    for (i = 0; i < NUM_LINES; i++) {
+	cairo_move_to (cr, 0, 0);
+	cairo_line_to (cr, x, min_y);
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, 0, 0);
+	cairo_line_to (cr, x, max_y);
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, 0, 0);
+	cairo_line_to (cr, min_x, y);
+	cairo_stroke (cr);
+
+	cairo_move_to (cr, 0, 0);
+	cairo_line_to (cr, max_x, y);
+	cairo_stroke (cr);
+
+	x += dx;
+	y += dy;
+    }
+
+    cairo_perf_timer_stop ();
+
+    cairo_restore (cr);
+
+    return cairo_perf_timer_elapsed ();
+}
+
+static cairo_perf_ticks_t
+long_lines_uncropped (cairo_t *cr, int width, int height)
+{
+    return do_long_lines (cr, width, height, LONG_LINES_UNCROPPED);
+}
+
+static cairo_perf_ticks_t
+long_lines_cropped (cairo_t *cr, int width, int height)
+{
+    return do_long_lines (cr, width, height, LONG_LINES_CROPPED);
+}
+
+void
+long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+{
+    cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
+    cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
+}


More information about the cairo-commit mailing list