[cairo-commit] 16 commits - perf/cairo-perf.c perf/cairo-perf-cover.c perf/cairo-perf.h perf/fill.c perf/Makefile.am perf/paint.c perf/README perf/stroke.c perf/tessellate.c src/cairo.c src/cairo-gstate.c src/cairo-image-surface.c src/cairo-path-data.c src/cairo-path-data-private.h src/cairo-pattern.c

Carl Worth cworth at kemper.freedesktop.org
Wed Oct 4 17:14:16 PDT 2006


 perf/Makefile.am              |    3 
 perf/README                   |   27 ++--
 perf/cairo-perf-cover.c       |  236 ++++++++++++++++++++++++++++++++++++++++++
 perf/cairo-perf.c             |  114 ++++++++++----------
 perf/cairo-perf.h             |   20 ++-
 perf/fill.c                   |   49 ++++++++
 perf/paint.c                  |  162 ----------------------------
 perf/stroke.c                 |   51 +++++++++
 perf/tessellate.c             |    2 
 src/cairo-gstate.c            |    1 
 src/cairo-image-surface.c     |   52 ++++++++-
 src/cairo-path-data-private.h |    2 
 src/cairo-path-data.c         |    2 
 src/cairo-pattern.c           |   54 +++------
 src/cairo.c                   |    8 -
 15 files changed, 505 insertions(+), 278 deletions(-)

New commits:
diff-tree bda77f505c911aea8ce684cb22a1469d1b7a9049 (from d15b8f2d6e0b0c2279fb0b17368f1110396e4bf8)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 16:35:20 2006 -0700

    perf: Bail if cairo_status returns non-success at the end of a test.

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 8e630af..e54e8fb 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -214,8 +214,16 @@ main (int argc, char *argv[])
 					       target->closure);
 
 		perf.cr = cairo_create (surface);
+
 		perf_case->run (&perf, perf.cr, perf.size, perf.size);
 
+		if (cairo_status (perf.cr)) {
+		    fprintf (stderr, "Error: Test left cairo in an error state: %s\n",
+			     cairo_status_to_string (cairo_status (perf.cr)));
+		    exit (1);
+		}
+
+		cairo_destroy (perf.cr);
 		cairo_surface_destroy (surface);
 	    }
 	}
diff-tree d15b8f2d6e0b0c2279fb0b17368f1110396e4bf8 (from 933d84572849a7ad61aca2c381f11a572fa9e9b7)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 16:32:14 2006 -0700

    perf: Add linear and radial gradients to the coverage

diff --git a/perf/cairo-perf-cover.c b/perf/cairo-perf-cover.c
index a4d19d2..53dc7b7 100644
--- a/perf/cairo-perf-cover.c
+++ b/perf/cairo-perf-cover.c
@@ -126,6 +126,72 @@ set_source_similar_surface_rgba (cairo_t
     cairo_surface_destroy (source);
 }
 
+static void
+set_source_linear_rgb (cairo_t *cr,
+		       int	width,
+		       int	height)
+{
+    cairo_pattern_t *linear;
+
+    linear = cairo_pattern_create_linear (0.0, 0.0, width, height);
+    cairo_pattern_add_color_stop_rgb (linear, 0.0, 1, 0, 0); /* red */
+    cairo_pattern_add_color_stop_rgb (linear, 1.0, 0, 0, 1); /* blue */
+
+    cairo_set_source (cr, linear);
+
+    cairo_pattern_destroy (linear);
+}
+
+static void
+set_source_linear_rgba (cairo_t *cr,
+			int	width,
+			int	height)
+{
+    cairo_pattern_t *linear;
+
+    linear = cairo_pattern_create_linear (0.0, 0.0, width, height);
+    cairo_pattern_add_color_stop_rgba (linear, 0.0, 1, 0, 0, 0.5); /* 50% red */
+    cairo_pattern_add_color_stop_rgba (linear, 1.0, 0, 0, 1, 0.0); /*  0% blue */
+
+    cairo_set_source (cr, linear);
+
+    cairo_pattern_destroy (linear);
+}
+
+static void
+set_source_radial_rgb (cairo_t *cr,
+		       int	width,
+		       int	height)
+{
+    cairo_pattern_t *radial;
+
+    radial = cairo_pattern_create_radial (width/2.0, height/2.0, 0.0,
+					  width/2.0, height/2.0, width/2.0);
+    cairo_pattern_add_color_stop_rgb (radial, 0.0, 1, 0, 0); /* red */
+    cairo_pattern_add_color_stop_rgb (radial, 1.0, 0, 0, 1); /* blue */
+
+    cairo_set_source (cr, radial);
+
+    cairo_pattern_destroy (radial);
+}
+
+static void
+set_source_radial_rgba (cairo_t *cr,
+			int	width,
+			int	height)
+{
+    cairo_pattern_t *radial;
+
+    radial = cairo_pattern_create_radial (width/2.0, height/2.0, 0.0,
+					  width/2.0, height/2.0, width/2.0);
+    cairo_pattern_add_color_stop_rgba (radial, 0.0, 1, 0, 0, 0.5); /* 50% red */
+    cairo_pattern_add_color_stop_rgba (radial, 1.0, 0, 0, 1, 0.0); /*  0% blue */
+
+    cairo_set_source (cr, radial);
+
+    cairo_pattern_destroy (radial);
+}
+
 typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
 
@@ -143,7 +209,11 @@ cairo_perf_cover_sources_and_operators (
 	{ set_source_image_surface_rgb, "image_rgb" },
 	{ set_source_image_surface_rgba, "image_rgba" },
 	{ set_source_similar_surface_rgb, "similar_rgb" },
-	{ set_source_similar_surface_rgba, "similar_rgba" }
+	{ set_source_similar_surface_rgba, "similar_rgba" },
+	{ set_source_linear_rgb, "linear_rgb" },
+	{ set_source_linear_rgba, "linear_rgba" },
+	{ set_source_radial_rgb, "radial_rgb" },
+	{ set_source_radial_rgba, "radial_rgba" }
     };
 
     struct { cairo_operator_t op; const char *name; } operators[] = {
diff-tree 933d84572849a7ad61aca2c381f11a572fa9e9b7 (from fb61fe82d3b360f09f2984bd3ac7de6720f75662)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 16:17:46 2006 -0700

    Shorten test names in output (drop unneeded _source and _surface)

diff --git a/perf/cairo-perf-cover.c b/perf/cairo-perf-cover.c
index 4ba53f2..a4d19d2 100644
--- a/perf/cairo-perf-cover.c
+++ b/perf/cairo-perf-cover.c
@@ -138,12 +138,12 @@ cairo_perf_cover_sources_and_operators (
     char *expanded_name;
 
     struct { set_source_func_t set_source; const char *name; } sources[] = {
-	{ set_source_solid_rgb, "solid_source_rgb" },
-	{ set_source_solid_rgba, "solid_source_rgba" },
-	{ set_source_image_surface_rgb, "image_surface_rgb" },
-	{ set_source_image_surface_rgba, "image_surface_rgba" },
-	{ set_source_similar_surface_rgb, "similar_surface_rgb" },
-	{ set_source_similar_surface_rgba, "similar_surface_rgba" }
+	{ set_source_solid_rgb, "solid_rgb" },
+	{ set_source_solid_rgba, "solid_rgba" },
+	{ set_source_image_surface_rgb, "image_rgb" },
+	{ set_source_image_surface_rgba, "image_rgba" },
+	{ set_source_similar_surface_rgb, "similar_rgb" },
+	{ set_source_similar_surface_rgba, "similar_rgba" }
     };
 
     struct { cairo_operator_t op; const char *name; } operators[] = {
diff-tree fb61fe82d3b360f09f2984bd3ac7de6720f75662 (from d52256df7c0147c29246dfc930644b6bdbff3c3f)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 16:16:03 2006 -0700

    perf: Add stroke and fill tests

diff --git a/perf/Makefile.am b/perf/Makefile.am
index ccc95dd..a0f0f42 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -18,7 +18,9 @@ cairo_perf_SOURCES =		\
 	cairo-perf.c		\
 	cairo-perf.h		\
 	cairo-perf-cover.c	\
+	fill.c			\
 	paint.c			\
+	stroke.c		\
 	tessellate.c
 
 if CAIRO_HAS_WIN32_SURFACE
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index ff72bfd..8e630af 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -155,13 +155,13 @@ cairo_perf_run (cairo_perf_t		*perf,
     _compute_stats (times, .85 * perf->iterations, &stats);
 
     if (first_run) {
-	printf ("[ # ] %8s-%-4s %35s %9s %5s %s\n",
+	printf ("[ # ] %8s-%-4s %36s %9s %5s %s\n",
 		"backend", "content", "test-size", "mean ms",
 		"std dev.", "iterations");
 	first_run = FALSE;
     }
 
-    printf ("[%3d] %8s-%-4s %33s-%-3d ",
+    printf ("[%3d] %8s-%-4s %34s-%-3d ",
 	    perf->test_number, perf->target->name,
 	    _content_to_string (perf->target->content),
 	    name, perf->size);
@@ -225,7 +225,9 @@ main (int argc, char *argv[])
 }
 
 cairo_perf_case_t perf_cases[] = {
-    { paint, 64, 512},
+    { paint,  64, 512},
+    { fill,   64, 256},
+    { stroke, 64, 256},
     { tessellate, 100, 100},
     { NULL }
 };
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 1000720..ec61254 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -82,10 +82,9 @@ cairo_perf_cover_sources_and_operators (
 
 #define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height);
 
-/* paint.c */
+CAIRO_PERF_DECL (fill);
 CAIRO_PERF_DECL (paint);
-
-/* tessellate.c */
+CAIRO_PERF_DECL (stroke);
 CAIRO_PERF_DECL (tessellate);
 
 #endif
diff --git a/perf/fill.c b/perf/fill.c
new file mode 100644
index 0000000..2a41355
--- /dev/null
+++ b/perf/fill.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-perf.h"
+
+static cairo_perf_ticks_t
+do_fill (cairo_t *cr, int width, int height)
+{
+    cairo_arc (cr,
+	       width/2.0, height/2.0,
+	       width/3.0,
+	       0, 2 * M_PI);
+
+    cairo_perf_timer_start ();
+
+    cairo_fill (cr);
+
+    cairo_perf_timer_stop ();
+
+    return cairo_perf_timer_elapsed ();
+}
+
+void
+fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+{
+    cairo_perf_cover_sources_and_operators (perf, "fill", do_fill);
+}
diff --git a/perf/stroke.c b/perf/stroke.c
new file mode 100644
index 0000000..0b4ea8e
--- /dev/null
+++ b/perf/stroke.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-perf.h"
+
+static cairo_perf_ticks_t
+do_stroke (cairo_t *cr, int width, int height)
+{
+    cairo_arc (cr,
+	       width/2.0, height/2.0,
+	       width/3.0,
+	       0, 2 * M_PI);
+    cairo_close_path (cr);
+
+    cairo_perf_timer_start ();
+
+    cairo_set_line_width (cr, width/5.0);
+    cairo_stroke (cr);
+
+    cairo_perf_timer_stop ();
+
+    return cairo_perf_timer_elapsed ();
+}
+
+void
+stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+{
+    cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke);
+}
diff-tree d52256df7c0147c29246dfc930644b6bdbff3c3f (from ad02773e9babe935250b810f8f9f490eb3d02a64)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 15:39:05 2006 -0700

    perf: Move iteration over sources and operators from paint to new cairo-perf-cover
    
    This will finally allow us to very easily add lots of other
    tests that will similarly involve iterating over the various
    sources and operators of interest.

diff --git a/perf/Makefile.am b/perf/Makefile.am
index d10c3d0..ccc95dd 100644
--- a/perf/Makefile.am
+++ b/perf/Makefile.am
@@ -17,6 +17,7 @@ noinst_PROGRAMS = cairo-perf
 cairo_perf_SOURCES =		\
 	cairo-perf.c		\
 	cairo-perf.h		\
+	cairo-perf-cover.c	\
 	paint.c			\
 	tessellate.c
 
diff --git a/perf/cairo-perf-cover.c b/perf/cairo-perf-cover.c
new file mode 100644
index 0000000..4ba53f2
--- /dev/null
+++ b/perf/cairo-perf-cover.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright © 2006 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-perf.h"
+
+static void
+init_and_set_source_surface (cairo_t		*cr,
+			     cairo_surface_t	*source,
+			     int		 width,
+			     int		 height)
+{
+    cairo_t *cr2;
+
+    /* Fill it with something known */
+    cr2 = cairo_create (source);
+    cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
+    cairo_paint (cr2);
+
+    cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
+    cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
+    cairo_paint (cr2);
+
+    cairo_set_source_rgba (cr2, 1, 0, 0, 0.5); /* 50% red */
+    cairo_new_path (cr2);
+    cairo_rectangle (cr2, 0, 0, width/2.0, height/2.0);
+    cairo_rectangle (cr2, width/2.0, height/2.0, width/2.0, height/2.0);
+    cairo_fill (cr2);
+    cairo_destroy (cr2);
+
+    cairo_set_source_surface (cr, source, 0, 0);
+}
+
+static void
+set_source_solid_rgb (cairo_t	*cr,
+		      int	 width,
+		      int	 height)
+{
+    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
+}
+
+static void
+set_source_solid_rgba (cairo_t	*cr,
+		       int	 width,
+		       int	 height)
+{
+    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
+}
+
+static void
+set_source_image_surface_rgb (cairo_t	*cr,
+			      int	 width,
+			      int	 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					 width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+static void
+set_source_image_surface_rgba (cairo_t	*cr,
+			       int	 width,
+			       int	 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+					 width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+static void
+set_source_similar_surface_rgb (cairo_t	*cr,
+				int	 width,
+				int	 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_surface_create_similar (cairo_get_target (cr),
+					   CAIRO_CONTENT_COLOR,
+					   width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+static void
+set_source_similar_surface_rgba (cairo_t	*cr,
+				 int		 width,
+				 int		 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_surface_create_similar (cairo_get_target (cr),
+					   CAIRO_CONTENT_COLOR_ALPHA,
+					   width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
+
+void
+cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
+					const char		*name,
+					cairo_perf_func_t	 perf_func)
+{
+    unsigned int i, j;
+    char *expanded_name;
+
+    struct { set_source_func_t set_source; const char *name; } sources[] = {
+	{ set_source_solid_rgb, "solid_source_rgb" },
+	{ set_source_solid_rgba, "solid_source_rgba" },
+	{ set_source_image_surface_rgb, "image_surface_rgb" },
+	{ set_source_image_surface_rgba, "image_surface_rgba" },
+	{ set_source_similar_surface_rgb, "similar_surface_rgb" },
+	{ set_source_similar_surface_rgba, "similar_surface_rgba" }
+    };
+
+    struct { cairo_operator_t op; const char *name; } operators[] = {
+	{ CAIRO_OPERATOR_OVER, "over" },
+	{ CAIRO_OPERATOR_SOURCE, "source" }
+    };
+
+    for (i = 0; i < ARRAY_SIZE (sources); i++) {
+	(sources[i].set_source) (perf->cr, perf->size, perf->size);
+
+	for (j = 0; j < ARRAY_SIZE (operators); j++) {
+	    cairo_set_operator (perf->cr, operators[j].op);
+
+	    xasprintf (&expanded_name, "%s_%s_%s",
+		       name, sources[i].name, operators[j].name);
+	    cairo_perf_run (perf, expanded_name, perf_func);
+	    free (expanded_name);
+	}
+    }
+}
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 0c48176..ff72bfd 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -28,15 +28,6 @@
 
 #include "cairo-perf.h"
 
-
-struct _cairo_perf {
-    unsigned int iterations;
-    cairo_boilerplate_target_t *target;
-    unsigned int test_number;
-    unsigned int size;
-    cairo_t *cr;
-};
-
 typedef struct _cairo_perf_case {
     CAIRO_PERF_DECL (*run);
     unsigned int min_size;
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 5c5ec21..1000720 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -59,7 +59,13 @@ void
 cairo_perf_yield (void);
 
 /* running a test case */
-typedef struct _cairo_perf cairo_perf_t;
+typedef struct _cairo_perf {
+    unsigned int iterations;
+    cairo_boilerplate_target_t *target;
+    unsigned int test_number;
+    unsigned int size;
+    cairo_t *cr;
+} cairo_perf_t;
 
 typedef cairo_perf_ticks_t
 (*cairo_perf_func_t) (cairo_t *cr, int width, int height);
@@ -69,6 +75,11 @@ cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
 		cairo_perf_func_t	 perf_func);
 
+void
+cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
+					const char		*name,
+					cairo_perf_func_t	 perf_func);
+
 #define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height);
 
 /* paint.c */
diff --git a/perf/paint.c b/perf/paint.c
index 30948d2..6f75016 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -37,139 +37,8 @@ do_paint (cairo_t *cr, int width, int he
     return cairo_perf_timer_elapsed ();
 }
 
-static void
-init_and_set_source_surface (cairo_t		*cr,
-			     cairo_surface_t	*source,
-			     int		 width,
-			     int		 height)
-{
-    cairo_t *cr2;
-
-    /* Fill it with something known */
-    cr2 = cairo_create (source);
-    cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
-    cairo_paint (cr2);
-
-    cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
-    cairo_paint (cr2);
-
-    cairo_set_source_rgba (cr2, 1, 0, 0, 0.5); /* 50% red */
-    cairo_new_path (cr2);
-    cairo_rectangle (cr2, 0, 0, width/2.0, height/2.0);
-    cairo_rectangle (cr2, width/2.0, height/2.0, width/2.0, height/2.0);
-    cairo_fill (cr2);
-    cairo_destroy (cr2);
-
-    cairo_set_source_surface (cr, source, 0, 0);
-}
-
-static void
-set_source_solid_rgb (cairo_t	*cr,
-		      int	 width,
-		      int	 height)
-{
-    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
-}
-
-static void
-set_source_solid_rgba (cairo_t	*cr,
-		       int	 width,
-		       int	 height)
-{
-    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
-}
-
-static void
-set_source_image_surface_rgb (cairo_t	*cr,
-			      int	 width,
-			      int	 height)
-{
-    cairo_surface_t *source;
-
-    source = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
-					 width, height);
-    init_and_set_source_surface (cr, source, width, height);
-
-    cairo_surface_destroy (source);
-}
-
-static void
-set_source_image_surface_rgba (cairo_t	*cr,
-			       int	 width,
-			       int	 height)
-{
-    cairo_surface_t *source;
-
-    source = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
-					 width, height);
-    init_and_set_source_surface (cr, source, width, height);
-
-    cairo_surface_destroy (source);
-}
-
-static void
-set_source_similar_surface_rgb (cairo_t	*cr,
-				int	 width,
-				int	 height)
-{
-    cairo_surface_t *source;
-
-    source = cairo_surface_create_similar (cairo_get_target (cr),
-					   CAIRO_CONTENT_COLOR,
-					   width, height);
-    init_and_set_source_surface (cr, source, width, height);
-
-    cairo_surface_destroy (source);
-}
-
-static void
-set_source_similar_surface_rgba (cairo_t	*cr,
-				 int		 width,
-				 int		 height)
-{
-    cairo_surface_t *source;
-
-    source = cairo_surface_create_similar (cairo_get_target (cr),
-					   CAIRO_CONTENT_COLOR_ALPHA,
-					   width, height);
-    init_and_set_source_surface (cr, source, width, height);
-
-    cairo_surface_destroy (source);
-}
-
-typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
-#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 void
 paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    unsigned int i, j;
-    char *name;
-
-    struct { set_source_func_t set_source; const char *name; } sources[] = {
-	{ set_source_solid_rgb, "solid_source_rgb" },
-	{ set_source_solid_rgba, "solid_source_rgba" },
-	{ set_source_image_surface_rgb, "image_surface_rgb" },
-	{ set_source_image_surface_rgba, "image_surface_rgba" },
-	{ set_source_similar_surface_rgb, "similar_surface_rgb" },
-	{ set_source_similar_surface_rgba, "similar_surface_rgba" }
-    };
-
-    struct { cairo_operator_t op; const char *name; } operators[] = {
-	{ CAIRO_OPERATOR_OVER, "over" },
-	{ CAIRO_OPERATOR_SOURCE, "source" }
-    };
-
-    for (i = 0; i < ARRAY_SIZE (sources); i++) {
-	(sources[i].set_source) (cr, width, height);
-
-	for (j = 0; j < ARRAY_SIZE (operators); j++) {
-	    cairo_set_operator (cr, operators[j].op);
-
-	    xasprintf (&name, "paint_%s_%s", sources[i].name, operators[j].name);
-	    cairo_perf_run (perf, name, do_paint);
-	    free (name);
-	}
-    }
+    cairo_perf_cover_sources_and_operators (perf, "paint", do_paint);
 }
diff-tree ad02773e9babe935250b810f8f9f490eb3d02a64 (from 783b69a8d33f913949247cc3ba018c35a4a83aa7)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 15:24:19 2006 -0700

    Remove unused variable

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 8beb8c4..5e411d7 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1117,7 +1117,6 @@ _cairo_gstate_fill_extents (cairo_gstate
 {
     cairo_status_t status;
     cairo_traps_t traps;
-    cairo_box_t extents;
 
     _cairo_traps_init (&traps);
 
diff-tree 783b69a8d33f913949247cc3ba018c35a4a83aa7 (from 01502471e31aa28a910039a918ff2aec3810d3c1)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 15:00:57 2006 -0700

    Rename the create_for_status pattern to create_in_error.

diff --git a/src/cairo-path-data-private.h b/src/cairo-path-data-private.h
index 28b70ee..7971c63 100644
--- a/src/cairo-path-data-private.h
+++ b/src/cairo-path-data-private.h
@@ -49,7 +49,7 @@ _cairo_path_data_create_flat (cairo_path
 			      cairo_gstate_t     *gstate);
 
 cairo_private cairo_path_t *
-_cairo_path_data_create_for_status (cairo_status_t status);
+_cairo_path_data_create_in_error (cairo_status_t status);
 
 cairo_private cairo_status_t
 _cairo_path_data_append_to_context (cairo_path_t *path,
diff --git a/src/cairo-path-data.c b/src/cairo-path-data.c
index 880a8f1..0a38496 100644
--- a/src/cairo-path-data.c
+++ b/src/cairo-path-data.c
@@ -332,7 +332,7 @@ _cairo_path_data_populate (cairo_path_t 
 }
 
 cairo_path_t *
-_cairo_path_data_create_for_status (cairo_status_t status)
+_cairo_path_data_create_in_error (cairo_status_t status)
 {
     cairo_path_t *path;
 
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index ef5b8a6..8b9201a 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -261,7 +261,7 @@ _cairo_pattern_create_solid (const cairo
 }
 
 static const cairo_pattern_t *
-_cairo_pattern_create_for_status (cairo_status_t status)
+_cairo_pattern_create_in_error (cairo_status_t status)
 {
     cairo_pattern_t *pattern;
 
@@ -381,7 +381,7 @@ cairo_pattern_create_for_surface (cairo_
 	return (cairo_pattern_t*) &cairo_pattern_nil_null_pointer;
 
     if (surface->status)
-	return (cairo_pattern_t*) _cairo_pattern_create_for_status (surface->status);
+	return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
 
     pattern = malloc (sizeof (cairo_surface_pattern_t));
     if (pattern == NULL) {
diff --git a/src/cairo.c b/src/cairo.c
index b47dd48..31b64d4 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2249,7 +2249,7 @@ cairo_clip_extents (cairo_t *cr,
 }
 
 static cairo_rectangle_list_t *
-_cairo_rectangle_list_create_for_status (cairo_status_t status)
+_cairo_rectangle_list_create_in_error (cairo_status_t status)
 {
     cairo_rectangle_list_t *list;
 
@@ -2282,7 +2282,7 @@ cairo_rectangle_list_t *
 cairo_copy_clip_rectangles (cairo_t *cr)
 {
     if (cr->status)
-        return _cairo_rectangle_list_create_for_status (cr->status);
+        return _cairo_rectangle_list_create_in_error (cr->status);
 
     return _cairo_gstate_copy_clip_rectangles (cr->gstate);
 }
@@ -3019,7 +3019,7 @@ cairo_path_t *
 cairo_copy_path (cairo_t *cr)
 {
     if (cr->status)
-	return _cairo_path_data_create_for_status (cr->status);
+	return _cairo_path_data_create_in_error (cr->status);
 
     return _cairo_path_data_create (&cr->path, cr->gstate);
 }
@@ -3061,7 +3061,7 @@ cairo_path_t *
 cairo_copy_path_flat (cairo_t *cr)
 {
     if (cr->status)
-	return _cairo_path_data_create_for_status (cr->status);
+	return _cairo_path_data_create_in_error (cr->status);
 
     return _cairo_path_data_create_flat (&cr->path, cr->gstate);
 }
diff-tree 01502471e31aa28a910039a918ff2aec3810d3c1 (from c9c259903d03e35fe98781fc6fedf326c40c0c4c)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 14:58:06 2006 -0700

    Add new _cairo_pattern_create_for_status so that patterns properly propagate errors.
    
    In particular, many possible error values on a surface provided
    to cairo_pattern_create_for_surface were previously being swallowed
    and a nil pattern was returned that erroneously reported
    CAIRO_STATUS_NO_MEMORY.

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 659f6cf..ef5b8a6 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -48,40 +48,6 @@ static const cairo_solid_pattern_t cairo
       CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
 };
 
-static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
-    { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
-      CAIRO_REF_COUNT_INVALID,		/* ref_count */
-      CAIRO_STATUS_FILE_NOT_FOUND, /* status */
-      { 1., 0., 0., 1., 0., 0., }, /* matrix */
-      CAIRO_FILTER_DEFAULT,	/* filter */
-      CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
-};
-
-static const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
-    { CAIRO_PATTERN_TYPE_SOLID, 	/* type */
-      CAIRO_REF_COUNT_INVALID,		/* ref_count */
-      CAIRO_STATUS_READ_ERROR,	/* status */
-      { 1., 0., 0., 1., 0., 0., }, /* matrix */
-      CAIRO_FILTER_DEFAULT,	/* filter */
-      CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
-};
-
-static const cairo_pattern_t *
-_cairo_pattern_nil_for_status (cairo_status_t status)
-{
-    /* A switch statement would be more natural here, but we're
-     * avoiding that to prevent a "false positive" warning from
-     * -Wswitch-enum, (and I don't want to maintain a list of all
-     * status values here). */
-    if (status == CAIRO_STATUS_NULL_POINTER)
-	return &cairo_pattern_nil_null_pointer.base;
-    if (status == CAIRO_STATUS_FILE_NOT_FOUND)
-	return &cairo_pattern_nil_file_not_found.base;
-    if (status == CAIRO_STATUS_READ_ERROR)
-	return &cairo_pattern_nil_read_error.base;
-    return &cairo_pattern_nil.base;
-}
-
 /**
  * _cairo_pattern_set_error:
  * @pattern: a pattern
@@ -294,6 +260,20 @@ _cairo_pattern_create_solid (const cairo
     return &pattern->base;
 }
 
+static const cairo_pattern_t *
+_cairo_pattern_create_for_status (cairo_status_t status)
+{
+    cairo_pattern_t *pattern;
+
+    pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK));
+    if (cairo_pattern_status (pattern))
+	return pattern;
+
+    _cairo_pattern_set_error (pattern, status);
+
+    return pattern;
+}
+
 /**
  * cairo_pattern_create_rgb:
  * @red: red component of the color
@@ -398,10 +378,10 @@ cairo_pattern_create_for_surface (cairo_
     cairo_surface_pattern_t *pattern;
 
     if (surface == NULL)
-	return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER);
+	return (cairo_pattern_t*) &cairo_pattern_nil_null_pointer;
 
     if (surface->status)
-	return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status);
+	return (cairo_pattern_t*) _cairo_pattern_create_for_status (surface->status);
 
     pattern = malloc (sizeof (cairo_surface_pattern_t));
     if (pattern == NULL) {
diff-tree c9c259903d03e35fe98781fc6fedf326c40c0c4c (from 4d2b54a271f722de9802ca68246ce6afba89f830)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 15:23:36 2006 -0700

    Cast to squelch warning message

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index a2a08e0..659f6cf 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -1580,7 +1580,7 @@ cairo_pattern_get_color_stop_rgba (cairo
 	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 	return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
 
-    if (index < 0 || index >= gradient->n_stops)
+    if (index < 0 || (unsigned int) index >= gradient->n_stops)
 	return CAIRO_STATUS_INVALID_INDEX;
 
     if (offset)
diff-tree 4d2b54a271f722de9802ca68246ce6afba89f830 (from 7d5fb687af2ec2da94a10200309fa362d694d23f)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 14:56:33 2006 -0700

    Fix cairo_image_surface_create to report INVALID_FORMAT errors.
    
    This adds a new nil cairo_image_surface to hold CAIRO_STATUS_INVALID_FORMAT.
    Previously the detected error was being lost and a nil surface was
    returned that erroneously reported CAIRO_STATUS_NO_MEMORY.

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 62040d8..8dc9087 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -36,6 +36,52 @@
 
 #include "cairoint.h"
 
+const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
+    {
+	&cairo_image_surface_backend,	/* backend */
+	CAIRO_SURFACE_TYPE_IMAGE,
+	CAIRO_CONTENT_COLOR,
+	CAIRO_REF_COUNT_INVALID,	/* ref_count */
+	CAIRO_STATUS_INVALID_FORMAT,	/* status */
+	FALSE,				/* finished */
+	{ 0,	/* size */
+	  0,	/* num_elements */
+	  0,	/* element_size */
+	  NULL,	/* elements */
+	},				/* user_data */
+	{ 1.0, 0.0,
+	  0.0, 1.0,
+	  0.0, 0.0
+	},				/* device_transform */
+	{ 1.0, 0.0,
+	  0.0, 1.0,
+	  0.0, 0.0
+	},				/* device_transform_inverse */
+	0.0,				/* x_fallback_resolution */
+	0.0,				/* y_fallback_resolution */
+	NULL,				/* clip */
+	0,				/* next_clip_serial */
+	0,				/* current_clip_serial */
+	FALSE,				/* is_snapshot */
+	FALSE,				/* has_font_options */
+	{ CAIRO_ANTIALIAS_DEFAULT,
+	  CAIRO_SUBPIXEL_ORDER_DEFAULT,
+	  CAIRO_HINT_STYLE_DEFAULT,
+	  CAIRO_HINT_METRICS_DEFAULT
+	}				/* font_options */
+    },					/* base */
+    CAIRO_FORMAT_ARGB32,		/* format */
+    NULL,				/* data */
+    FALSE,				/* owns_data */
+    FALSE,				/* has_clip */
+    0,					/* width */
+    0,					/* height */
+    0,					/* stride */
+    0,					/* depth */
+    NULL				/* pixman_image */
+};
+
+
 static int
 _cairo_format_bpp (cairo_format_t format)
 {
@@ -248,8 +294,10 @@ cairo_image_surface_create (cairo_format
     pixman_format_t *pixman_format;
     pixman_image_t *pixman_image;
 
-    if (! CAIRO_FORMAT_VALID (format))
-	return (cairo_surface_t*) &_cairo_surface_nil;
+    if (! CAIRO_FORMAT_VALID (format)) {
+	_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
+	return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
+    }
 
     pixman_format = _create_pixman_format (format);
     if (pixman_format == NULL) {
diff-tree 7d5fb687af2ec2da94a10200309fa362d694d23f (from 94759a14daac63d05e5399982be56e73abf552c4)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 14:13:54 2006 -0700

    perf/paint: Test image surface as well as similar surface sources

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index e786ab7..0c48176 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -164,13 +164,13 @@ cairo_perf_run (cairo_perf_t		*perf,
     _compute_stats (times, .85 * perf->iterations, &stats);
 
     if (first_run) {
-	printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
+	printf ("[ # ] %8s-%-4s %35s %9s %5s %s\n",
 		"backend", "content", "test-size", "mean ms",
 		"std dev.", "iterations");
 	first_run = FALSE;
     }
 
-    printf ("[%3d] %8s-%-4s %25s-%-3d ",
+    printf ("[%3d] %8s-%-4s %33s-%-3d ",
 	    perf->test_number, perf->target->name,
 	    _content_to_string (perf->target->content),
 	    name, perf->size);
diff --git a/perf/paint.c b/perf/paint.c
index bedd3c0..30948d2 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -38,27 +38,23 @@ do_paint (cairo_t *cr, int width, int he
 }
 
 static void
-set_source_surface (cairo_t		*cr,
-		    cairo_content_t	 content,
-		    int			 width,
-		    int			 height)
+init_and_set_source_surface (cairo_t		*cr,
+			     cairo_surface_t	*source,
+			     int		 width,
+			     int		 height)
 {
-    cairo_surface_t *source;
     cairo_t *cr2;
 
-    source = cairo_surface_create_similar (cairo_get_target (cr),
-					   content, width, height);
-
     /* Fill it with something known */
     cr2 = cairo_create (source);
     cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
     cairo_paint (cr2);
 
     cairo_set_operator (cr2, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_rgb (cr2, 0, 0, 1);
+    cairo_set_source_rgb (cr2, 0, 0, 1); /* blue */
     cairo_paint (cr2);
 
-    cairo_set_source_rgba (cr2, 1, 0, 0, 0.5);
+    cairo_set_source_rgba (cr2, 1, 0, 0, 0.5); /* 50% red */
     cairo_new_path (cr2);
     cairo_rectangle (cr2, 0, 0, width/2.0, height/2.0);
     cairo_rectangle (cr2, width/2.0, height/2.0, width/2.0, height/2.0);
@@ -66,7 +62,6 @@ set_source_surface (cairo_t		*cr,
     cairo_destroy (cr2);
 
     cairo_set_source_surface (cr, source, 0, 0);
-    cairo_surface_destroy (source);
 }
 
 static void
@@ -86,19 +81,61 @@ set_source_solid_rgba (cairo_t	*cr,
 }
 
 static void
-set_source_surface_rgb (cairo_t	*cr,
-			int	 width,
-			int	 height)
+set_source_image_surface_rgb (cairo_t	*cr,
+			      int	 width,
+			      int	 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					 width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+static void
+set_source_image_surface_rgba (cairo_t	*cr,
+			       int	 width,
+			       int	 height)
+{
+    cairo_surface_t *source;
+
+    source = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+					 width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
+}
+
+static void
+set_source_similar_surface_rgb (cairo_t	*cr,
+				int	 width,
+				int	 height)
 {
-    set_source_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+    cairo_surface_t *source;
+
+    source = cairo_surface_create_similar (cairo_get_target (cr),
+					   CAIRO_CONTENT_COLOR,
+					   width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
 }
 
 static void
-set_source_surface_rgba (cairo_t	*cr,
-			 int		 width,
-			 int		 height)
+set_source_similar_surface_rgba (cairo_t	*cr,
+				 int		 width,
+				 int		 height)
 {
-    set_source_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+    cairo_surface_t *source;
+
+    source = cairo_surface_create_similar (cairo_get_target (cr),
+					   CAIRO_CONTENT_COLOR_ALPHA,
+					   width, height);
+    init_and_set_source_surface (cr, source, width, height);
+
+    cairo_surface_destroy (source);
 }
 
 typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
@@ -111,10 +148,12 @@ paint (cairo_perf_t *perf, cairo_t *cr, 
     char *name;
 
     struct { set_source_func_t set_source; const char *name; } sources[] = {
-	{ set_source_solid_rgb, "solid_rgb" },
-	{ set_source_solid_rgba, "solid_rgba" },
-	{ set_source_surface_rgb, "surface_rgb" },
-	{ set_source_surface_rgba, "surface_rgba" }
+	{ set_source_solid_rgb, "solid_source_rgb" },
+	{ set_source_solid_rgba, "solid_source_rgba" },
+	{ set_source_image_surface_rgb, "image_surface_rgb" },
+	{ set_source_image_surface_rgba, "image_surface_rgba" },
+	{ set_source_similar_surface_rgb, "similar_surface_rgb" },
+	{ set_source_similar_surface_rgba, "similar_surface_rgba" }
     };
 
     struct { cairo_operator_t op; const char *name; } operators[] = {
diff-tree 94759a14daac63d05e5399982be56e73abf552c4 (from 37bc39d82c8d2c2cd8b04ea554925102b4831856)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 13:54:39 2006 -0700

    perf/paint: Use loops for sources and operators rather than open coding.
    
    This looks a bit more complicated for now, but will
    scaled much better to provide complete coverage as
    we extend the cases covered.

diff --git a/perf/paint.c b/perf/paint.c
index 4e92b4d..bedd3c0 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -69,33 +69,68 @@ set_source_surface (cairo_t		*cr,
     cairo_surface_destroy (source);
 }
 
-void
-paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+static void
+set_source_solid_rgb (cairo_t	*cr,
+		      int	 width,
+		      int	 height)
 {
     cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
-    cairo_perf_run (perf, "paint_over_solid", do_paint);
-
-    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
-    cairo_perf_run (perf, "paint_over_solid_alpha", do_paint);
-
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
-    cairo_perf_run (perf, "paint_source_solid", do_paint);
+}
 
+static void
+set_source_solid_rgba (cairo_t	*cr,
+		       int	 width,
+		       int	 height)
+{
     cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
-    cairo_perf_run (perf, "paint_source_solid_alpha", do_paint);
+}
 
-    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+static void
+set_source_surface_rgb (cairo_t	*cr,
+			int	 width,
+			int	 height)
+{
     set_source_surface (cr, CAIRO_CONTENT_COLOR, width, height);
-    cairo_perf_run (perf, "paint_over_surf_rgb24", do_paint);
+}
 
+static void
+set_source_surface_rgba (cairo_t	*cr,
+			 int		 width,
+			 int		 height)
+{
     set_source_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
-    cairo_perf_run (perf, "paint_over_surf_argb32", do_paint);
+}
 
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    set_source_surface (cr, CAIRO_CONTENT_COLOR, width, height);
-    cairo_perf_run (perf, "paint_source_surf_rgb24", do_paint);
+typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
 
-    set_source_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
-    cairo_perf_run (perf, "paint_source_surf_argb32", do_paint);
+void
+paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+{
+    unsigned int i, j;
+    char *name;
+
+    struct { set_source_func_t set_source; const char *name; } sources[] = {
+	{ set_source_solid_rgb, "solid_rgb" },
+	{ set_source_solid_rgba, "solid_rgba" },
+	{ set_source_surface_rgb, "surface_rgb" },
+	{ set_source_surface_rgba, "surface_rgba" }
+    };
+
+    struct { cairo_operator_t op; const char *name; } operators[] = {
+	{ CAIRO_OPERATOR_OVER, "over" },
+	{ CAIRO_OPERATOR_SOURCE, "source" }
+    };
+
+    for (i = 0; i < ARRAY_SIZE (sources); i++) {
+	(sources[i].set_source) (cr, width, height);
+
+	for (j = 0; j < ARRAY_SIZE (operators); j++) {
+	    cairo_set_operator (cr, operators[j].op);
+
+	    xasprintf (&name, "paint_%s_%s", sources[i].name, operators[j].name);
+	    cairo_perf_run (perf, name, do_paint);
+	    free (name);
+	}
+    }
 }
diff-tree 37bc39d82c8d2c2cd8b04ea554925102b4831856 (from d0aae4dbcf6d3ca67a4a7b364fba80f719af2ac1)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 13:35:27 2006 -0700

    perf/paint: Dramatically simplify now that we don't need one callback per run.
    
    This commit begins to show the benefits of the reorganization
    from the last few commits. Specifically, we don't need a callback
    for every run anymore, and now that the cairo_t* is available to
    the paint entry function and the size changes only on the outer
    loop, (rather than inside cairo_perf_run), there's no need for
    the ugly, static cache for the source surface.

diff --git a/perf/paint.c b/perf/paint.c
index de28d3c..4e92b4d 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -26,7 +26,7 @@
 #include "cairo-perf.h"
 
 static cairo_perf_ticks_t
-do_paint (cairo_t *cr, int size)
+do_paint (cairo_t *cr, int width, int height)
 {
     cairo_perf_timer_start ();
 
@@ -37,79 +37,20 @@ do_paint (cairo_t *cr, int size)
     return cairo_perf_timer_elapsed ();
 }
 
-/*
- * paint with solid color
- */
-
-static cairo_perf_ticks_t
-paint_over_solid (cairo_t *cr, int width, int height)
-{
-    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
-
-    return do_paint (cr, width);
-}
-
-static cairo_perf_ticks_t
-paint_over_solid_alpha (cairo_t *cr, int width, int height)
-{
-    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
-
-    return do_paint (cr, width);
-}
-
-static cairo_perf_ticks_t
-paint_source_solid (cairo_t *cr, int width, int height)
-{
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
-
-    return do_paint (cr, width);
-}
-
-static cairo_perf_ticks_t
-paint_source_solid_alpha (cairo_t *cr, int width, int height)
-{
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
-
-    return do_paint (cr, width);
-}
-
-/*
- * paint with surface
- */
-
-int cached_surface_width = 0;
-int cached_surface_height = 0;
-cairo_content_t cached_surface_content = 0;
-cairo_surface_t *cached_surface = NULL;
-
 static void
-ensure_cached_surface (cairo_t *cr, cairo_content_t content, int w, int h)
+set_source_surface (cairo_t		*cr,
+		    cairo_content_t	 content,
+		    int			 width,
+		    int			 height)
 {
-    cairo_surface_t *target_surface = cairo_get_target (cr);
-
+    cairo_surface_t *source;
     cairo_t *cr2;
 
-    if (w == cached_surface_width && h == cached_surface_height &&
-        content == cached_surface_content &&
-        cached_surface &&
-        cairo_surface_get_type (target_surface) == cairo_surface_get_type (cached_surface))
-    {
-        return;
-    }
-
-    if (cached_surface)
-        cairo_surface_destroy (cached_surface);
-    
-    cached_surface = cairo_surface_create_similar (target_surface, content, w, h);
-
-    cached_surface_width = w;
-    cached_surface_height = h;
-    cached_surface_content = content;
+    source = cairo_surface_create_similar (cairo_get_target (cr),
+					   content, width, height);
 
     /* Fill it with something known */
-    cr2 = cairo_create (cached_surface);
+    cr2 = cairo_create (source);
     cairo_set_operator (cr2, CAIRO_OPERATOR_CLEAR);
     cairo_paint (cr2);
 
@@ -119,63 +60,42 @@ ensure_cached_surface (cairo_t *cr, cair
 
     cairo_set_source_rgba (cr2, 1, 0, 0, 0.5);
     cairo_new_path (cr2);
-    cairo_rectangle (cr2, 0, 0, w/2.0, h/2.0);
-    cairo_rectangle (cr2, w/2.0, h/2.0, w/2.0, h/2.0);
+    cairo_rectangle (cr2, 0, 0, width/2.0, height/2.0);
+    cairo_rectangle (cr2, width/2.0, height/2.0, width/2.0, height/2.0);
     cairo_fill (cr2);
     cairo_destroy (cr2);
-}
 
-static cairo_perf_ticks_t
-paint_over_surface_rgb24 (cairo_t *cr, int width, int height)
-{
-    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
-
-    cairo_set_source_surface (cr, cached_surface, 0, 0);
-
-    return do_paint (cr, width);
+    cairo_set_source_surface (cr, source, 0, 0);
+    cairo_surface_destroy (source);
 }
 
-static cairo_perf_ticks_t
-paint_over_surface_argb32 (cairo_t *cr, int width, int height)
+void
+paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
-    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
-
-    cairo_set_source_surface (cr, cached_surface, 0, 0);
-
-    return do_paint (cr, width);
-}
+    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
+    cairo_perf_run (perf, "paint_over_solid", do_paint);
 
-static cairo_perf_ticks_t
-paint_source_surface_rgb24 (cairo_t *cr, int width, int height)
-{
-    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
+    cairo_perf_run (perf, "paint_over_solid_alpha", do_paint);
 
     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_surface (cr, cached_surface, 0, 0);
+    cairo_set_source_rgb (cr, 0.2, 0.6, 0.9);
+    cairo_perf_run (perf, "paint_source_solid", do_paint);
 
-    return do_paint (cr, width);
-}
+    cairo_set_source_rgba (cr, 0.2, 0.6, 0.9, 0.7);
+    cairo_perf_run (perf, "paint_source_solid_alpha", do_paint);
 
-static cairo_perf_ticks_t
-paint_source_surface_argb32 (cairo_t *cr, int width, int height)
-{
-    ensure_cached_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+    set_source_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+    cairo_perf_run (perf, "paint_over_surf_rgb24", do_paint);
 
-    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-    cairo_set_source_surface (cr, cached_surface, 0, 0);
+    set_source_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+    cairo_perf_run (perf, "paint_over_surf_argb32", do_paint);
 
-    return do_paint (cr, width);
-}
+    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+    set_source_surface (cr, CAIRO_CONTENT_COLOR, width, height);
+    cairo_perf_run (perf, "paint_source_surf_rgb24", do_paint);
 
-void
-paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
-{
-    cairo_perf_run (perf, "paint_over_solid", paint_over_solid);
-    cairo_perf_run (perf, "paint_over_solid_alpha", paint_over_solid_alpha);
-    cairo_perf_run (perf, "paint_source_solid", paint_source_solid);
-    cairo_perf_run (perf, "paint_source_solid_alpha", paint_source_solid_alpha);
-    cairo_perf_run (perf, "paint_over_surf_rgb24", paint_over_surface_rgb24);
-    cairo_perf_run (perf, "paint_over_surf_argb32", paint_over_surface_argb32);
-    cairo_perf_run (perf, "paint_source_surf_rgb24", paint_source_surface_rgb24);
-    cairo_perf_run (perf, "paint_source_surf_argb32", paint_source_surface_argb32);
+    set_source_surface (cr, CAIRO_CONTENT_COLOR_ALPHA, width, height);
+    cairo_perf_run (perf, "paint_source_surf_argb32", do_paint);
 }
diff-tree d0aae4dbcf6d3ca67a4a7b364fba80f719af2ac1 (from 4406ab1b9e8a618aae4d709a370d4ace0e9897e9)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 13:23:50 2006 -0700

    perf: Make cairo_t* available to perf functions

diff --git a/perf/README b/perf/README
index 31dfc2f..6965c3f 100644
--- a/perf/README
+++ b/perf/README
@@ -41,28 +41,27 @@ Here is the basic structure of a perform
     static cairo_perf_ticks_t
     do_my_new_test (cairo_t *cr, int width, int height)
     {
-	/* First do any setup for which the execution time should not
-	 * be measured. For example, this might include loading
-	 * images from disk, creating patterns, etc. */
-
 	cairo_perf_timer_start ();
 
-	/* Now make the real cairo calls to be measured */
+	/* Make the cairo calls to be measured */
 
 	cairo_perf_timer_stop ();
 
-	/* Finally, any cleanup */
-
-	/* Then return the time that elapsed. */
-
 	return cairo_perf_timer_elapsed ();
-     }
+    }
 
-     void
-     my_new_test (cairo_perf_t *perf)
-     {
+    void
+    my_new_test (cairo_perf_t *perf, cairo_t *cr, int width, int height)
+    {
+	/* First do any setup for which the execution time should not
+	 * be measured. For example, this might include loading
+	 * images from disk, creating patterns, etc. */
+
+	/* Then launch the actual performance testing. */
 	cairo_perf_run (perf, "my_new_test", do_my_new_test);
-     }
+
+	/* Finally, perform any cleanup from the setup above. */
+    }
 
 That's really all there is to writing a new test. The first function
 above is the one that does the real work and returns a timing
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index b2768c3..e786ab7 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -223,7 +223,7 @@ main (int argc, char *argv[])
 					       target->closure);
 
 		perf.cr = cairo_create (surface);
-		perf_case->run (&perf);
+		perf_case->run (&perf, perf.cr, perf.size, perf.size);
 
 		cairo_surface_destroy (surface);
 	    }
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 6b40ae8..5c5ec21 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -69,7 +69,7 @@ cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
 		cairo_perf_func_t	 perf_func);
 
-#define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf);
+#define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height);
 
 /* paint.c */
 CAIRO_PERF_DECL (paint);
diff --git a/perf/paint.c b/perf/paint.c
index 324f397..de28d3c 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -168,7 +168,7 @@ paint_source_surface_argb32 (cairo_t *cr
 }
 
 void
-paint (cairo_perf_t *perf)
+paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     cairo_perf_run (perf, "paint_over_solid", paint_over_solid);
     cairo_perf_run (perf, "paint_over_solid_alpha", paint_over_solid_alpha);
diff --git a/perf/tessellate.c b/perf/tessellate.c
index e8f3dd6..fc97db7 100644
--- a/perf/tessellate.c
+++ b/perf/tessellate.c
@@ -141,7 +141,7 @@ tessellate_256 (cairo_t *cr, int width, 
 }
 
 void
-tessellate (cairo_perf_t *perf)
+tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     cairo_perf_run (perf, "tessellate-16", tessellate_16);
     cairo_perf_run (perf, "tessellate-64", tessellate_64);
diff-tree 4406ab1b9e8a618aae4d709a370d4ace0e9897e9 (from 251bed86400f72a4ec90618d0d41566ab9969cfa)
Author: Carl Worth <cworth at cworth.org>
Date:   Wed Oct 4 12:55:54 2006 -0700

    perf: Move the per-size loop from cairo_perf_run to main
    
    The motivation here is to have the cairo_t context available
    to the perf funcs before they call into cairo_perf_run, (so
    that they can do one-time setup of source etc. for several
    runs).

diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index ef3ac32..b2768c3 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -32,9 +32,9 @@
 struct _cairo_perf {
     unsigned int iterations;
     cairo_boilerplate_target_t *target;
-    unsigned int min_size;
-    unsigned int max_size;
     unsigned int test_number;
+    unsigned int size;
+    cairo_t *cr;
 };
 
 typedef struct _cairo_perf_case {
@@ -147,52 +147,39 @@ cairo_perf_run (cairo_perf_t		*perf,
     static cairo_bool_t first_run = TRUE;
 
     unsigned int i;
-    unsigned int size;
-    cairo_surface_t *surface;
-    cairo_t *cr;
     cairo_perf_ticks_t *times;
     stats_t stats;
-    cairo_boilerplate_target_t *target = perf->target;
 
     times = xmalloc (perf->iterations * sizeof (cairo_perf_ticks_t));
 
-    for (size = perf->min_size; size <= perf->max_size; size *= 2) {
-	surface = (target->create_surface) (name,
-					    target->content,
-					    size, size,
-					    CAIRO_BOILERPLATE_MODE_PERF,
-					    &target->closure);
-	cairo_perf_timer_set_finalize (target->wait_for_rendering, target->closure);
-	cr = cairo_create (surface);
-	for (i =0; i < perf->iterations; i++) {
-	    cairo_perf_yield ();
-	    times[i] = (perf_func) (cr, size, size);
-	}
+    for (i =0; i < perf->iterations; i++) {
+	cairo_perf_yield ();
+	times[i] = (perf_func) (perf->cr, perf->size, perf->size);
+    }
 
-	qsort (times, perf->iterations,
-	       sizeof (cairo_perf_ticks_t), compare_cairo_perf_ticks);
+    qsort (times, perf->iterations,
+	   sizeof (cairo_perf_ticks_t), compare_cairo_perf_ticks);
 
-	/* Assume the slowest 15% are outliers, and ignore */
-	_compute_stats (times, .85 * perf->iterations, &stats);
+    /* Assume the slowest 15% are outliers, and ignore */
+    _compute_stats (times, .85 * perf->iterations, &stats);
 
-	if (first_run) {
-	    printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
-		    "backend", "content", "test-size", "mean ms",
-		    "std dev.", "iterations");
-	    first_run = FALSE;
-	}
+    if (first_run) {
+	printf ("[ # ] %8s-%-4s %27s %9s %5s %s\n",
+		"backend", "content", "test-size", "mean ms",
+		"std dev.", "iterations");
+	first_run = FALSE;
+    }
 
-	printf ("[%3d] %8s-%-4s %25s-%-3d ",
-		perf->test_number, target->name,
-		_content_to_string (target->content),
-		name, size);
-
-	printf ("%#9.3f %#5.2f%% % 5d\n",
-		(stats.mean * 1000.0) / cairo_perf_ticks_per_second (),
-		stats.std_dev * 100.0, perf->iterations);
+    printf ("[%3d] %8s-%-4s %25s-%-3d ",
+	    perf->test_number, perf->target->name,
+	    _content_to_string (perf->target->content),
+	    name, perf->size);
+
+    printf ("%#9.3f %#5.2f%% % 5d\n",
+	    (stats.mean * 1000.0) / cairo_perf_ticks_per_second (),
+	    stats.std_dev * 100.0, perf->iterations);
 
-	perf->test_number++;
-    }
+    perf->test_number++;
 }
 
 int
@@ -202,6 +189,8 @@ main (int argc, char *argv[])
     cairo_perf_case_t *perf_case;
     cairo_perf_t perf;
     const char *cairo_test_target = getenv ("CAIRO_TEST_TARGET");
+    cairo_boilerplate_target_t *target;
+    cairo_surface_t *surface;
 
     if (getenv("CAIRO_PERF_ITERATIONS"))
 	perf.iterations = strtol(getenv("CAIRO_PERF_ITERATIONS"), NULL, 0);
@@ -209,19 +198,35 @@ main (int argc, char *argv[])
 	perf.iterations = 100;
 
     for (i = 0; targets[i].name; i++) {
-	perf.target = &targets[i];
-	if (! target_is_measurable (perf.target))
+	perf.target = target = &targets[i];
+	perf.test_number = 0;
+
+	if (! target_is_measurable (target))
 	    continue;
-	if (cairo_test_target && ! strstr (cairo_test_target, perf.target->name))
+	if (cairo_test_target && ! strstr (cairo_test_target, target->name))
 	    continue;
 
-	perf.test_number = 0;
-
 	for (j = 0; perf_cases[j].run; j++) {
+
 	    perf_case = &perf_cases[j];
-	    perf.min_size = perf_case->min_size;
-	    perf.max_size = perf_case->max_size;
-	    perf_case->run (&perf);
+
+	    for (perf.size = perf_case->min_size;
+		 perf.size <= perf_case->max_size;
+		 perf.size *= 2)
+	    {
+		surface = (target->create_surface) (NULL,
+						    target->content,
+						    perf.size, perf.size,
+						    CAIRO_BOILERPLATE_MODE_PERF,
+						    &target->closure);
+		cairo_perf_timer_set_finalize (target->wait_for_rendering,
+					       target->closure);
+
+		perf.cr = cairo_create (surface);
+		perf_case->run (&perf);
+
+		cairo_surface_destroy (surface);
+	    }
 	}
     }
 
diff-tree 251bed86400f72a4ec90618d0d41566ab9969cfa (from 1e0e2075090c181dcd9f431833a8a9c2665d763e)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Oct 3 17:27:27 2006 -0700

    perf/paint: Make all sizes use a consistent number of iterations
    
    This effectively reverts the change made in:
    
    	3c407aa80a43e1724e732482ada5ad6718fe33ae
    
    The justification is that we want to be able to see the
    trends of increasing the image size while keeping the test
    the same. But changing the number of iterations in a size-
    specific way interferes with that. Also, the standard deviation
    is almost always better this way, (though it now varies more
    by size).
    
    And as a bonus, the total time required to run the suite is now
    less.

diff --git a/perf/paint.c b/perf/paint.c
index 10aacc0..324f397 100644
--- a/perf/paint.c
+++ b/perf/paint.c
@@ -25,29 +25,12 @@
 
 #include "cairo-perf.h"
 
-static int
-iters_for_size (int size)
-{
-    if (size <= 64)
-	return 8;
-    else if (size <= 128)
-	return 4;
-    else if (size <= 256)
-	return 2;
-    else
-	return 1;
-}
-
 static cairo_perf_ticks_t
 do_paint (cairo_t *cr, int size)
 {
-    int i;
-    int iters = iters_for_size (size);
-
     cairo_perf_timer_start ();
 
-    for (i=0; i < iters; i++)
-	cairo_paint (cr);
+    cairo_paint (cr);
 
     cairo_perf_timer_stop ();
 


More information about the cairo-commit mailing list