[cairo-commit] 6 commits - boilerplate/cairo-boilerplate.c boilerplate/cairo-boilerplate-xlib.c boilerplate/cairo-boilerplate-xlib-private.h perf/cairo-perf.c perf/cairo-perf-diff perf/cairo-perf-graph perf/cairo-perf-graph-widget.c perf/cairo-perf-trace.c test/cairo-test-trace.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Jun 21 02:13:47 PDT 2009


 boilerplate/cairo-boilerplate-xlib-private.h |   11 +
 boilerplate/cairo-boilerplate-xlib.c         |   51 ++++++++
 boilerplate/cairo-boilerplate.c              |   14 +-
 perf/cairo-perf-diff                         |   63 ++++++----
 perf/cairo-perf-graph                        |    5 
 perf/cairo-perf-graph-widget.c               |  166 ++++++++++++++++++++++++---
 perf/cairo-perf-trace.c                      |    8 +
 perf/cairo-perf.c                            |    6 
 test/cairo-test-trace.c                      |  101 +++++++++++++---
 9 files changed, 367 insertions(+), 58 deletions(-)

New commits:
commit d0c1c9282164bffb76f7419873e93608dc6d9876
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 21 10:08:21 2009 +0100

    [boilerplate] Implement a reference xlib surface
    
    Create an xlib target that uses a separate display, specified by
    CAIRO_REFERENCE_DISPLAY, that can be used as a reference implementation
    for the normal display. So this can be used by cairo-trace-test to create
    a reference surface that mimics exactly the true surface, but if it
    targets an Xvfb display will be entirely rendered in software. If
    CAIRO_REFERENCE_DISPLAY is not set, the reference surface degrades into an
    xlib-fallback surface which is a close approximation (but still has
    behavioural differences).

diff --git a/boilerplate/cairo-boilerplate-xlib-private.h b/boilerplate/cairo-boilerplate-xlib-private.h
index 0bd911d..265ee97 100644
--- a/boilerplate/cairo-boilerplate-xlib-private.h
+++ b/boilerplate/cairo-boilerplate-xlib-private.h
@@ -41,6 +41,17 @@ _cairo_boilerplate_xlib_create_surface (const char		  *name,
 #endif
 
 cairo_surface_t *
+_cairo_boilerplate_xlib_reference_create_surface (const char			 *name,
+						 cairo_content_t		  content,
+						 int				  width,
+						 int				  height,
+						 int				  max_width,
+						 int				  max_height,
+						 cairo_boilerplate_mode_t	  mode,
+						 int				  id,
+						 void				**closure);
+
+cairo_surface_t *
 _cairo_boilerplate_xlib_fallback_create_surface (const char			 *name,
 						 cairo_content_t		  content,
 						 int				  width,
diff --git a/boilerplate/cairo-boilerplate-xlib.c b/boilerplate/cairo-boilerplate-xlib.c
index a4deeb7..03febe9 100644
--- a/boilerplate/cairo-boilerplate-xlib.c
+++ b/boilerplate/cairo-boilerplate-xlib.c
@@ -224,6 +224,57 @@ _cairo_boilerplate_xlib_create_surface (const char			 *name,
 
     return surface;
 }
+
+cairo_surface_t *
+_cairo_boilerplate_xlib_reference_create_surface (const char			 *name,
+						  cairo_content_t			  content,
+						  int				  width,
+						  int				  height,
+						  int				  max_width,
+						  int				  max_height,
+						  cairo_boilerplate_mode_t	  mode,
+						  int                               id,
+						  void				**closure)
+{
+    xlib_target_closure_t *xtc;
+    Display *dpy;
+    cairo_surface_t *surface;
+    const char *display;
+
+    display = getenv ("CAIRO_REFERENCE_DISPLAY");
+    if (display == NULL) {
+	return _cairo_boilerplate_xlib_fallback_create_surface (name, content,
+								width, height,
+								max_width,
+								max_height,
+								mode, id,
+								closure);
+    }
+
+    *closure = xtc = xcalloc (1, sizeof (xlib_target_closure_t));
+
+    if (width == 0)
+	width = 1;
+    if (height == 0)
+	height = 1;
+
+    xtc->dpy = dpy = XOpenDisplay (display);
+    if (xtc->dpy == NULL) {
+	free (xtc);
+	CAIRO_BOILERPLATE_DEBUG (("Failed to open display: %s\n", display));
+	return NULL;
+    }
+
+    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
+	surface = _cairo_boilerplate_xlib_test_create_surface (dpy, content, width, height, xtc);
+    else /* mode == CAIRO_BOILERPLATE_MODE_PERF */
+	surface = _cairo_boilerplate_xlib_perf_create_surface (dpy, content, width, height, xtc);
+
+    if (surface == NULL || cairo_surface_status (surface))
+	_cairo_boilerplate_xlib_cleanup (xtc);
+
+    return surface;
+}
 #endif
 
 /* The xlib-fallback target differs from the xlib target in two ways:
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 50a28f8..39a1a4a 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -552,7 +552,7 @@ static const cairo_boilerplate_target_t targets[] =
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
     {
-	"xlib", "xlib", NULL, "xlib-fallback",
+	"xlib", "xlib", NULL, "xlib-reference",
 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
 	_cairo_boilerplate_xlib_create_surface,
 	NULL, NULL,
@@ -562,7 +562,7 @@ static const cairo_boilerplate_target_t targets[] =
 	_cairo_boilerplate_xlib_synchronize
     },
     {
-	"xlib", "xlib", NULL, "xlib-fallback",
+	"xlib", "xlib", NULL, "xlib-reference",
 	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
 	_cairo_boilerplate_xlib_create_surface,
 	NULL, NULL,
@@ -571,6 +571,16 @@ static const cairo_boilerplate_target_t targets[] =
 	_cairo_boilerplate_xlib_cleanup,
 	_cairo_boilerplate_xlib_synchronize
     },
+    {
+	"xlib-reference", "xlib", NULL, NULL,
+	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_xlib_reference_create_surface,
+	NULL, NULL,
+	NULL, /* get_image */
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xlib_cleanup,
+	_cairo_boilerplate_xlib_synchronize
+    },
 #endif
 #if CAIRO_HAS_XLIB_SURFACE
     /* This is a fallback surface which uses xlib fallbacks instead of
commit d2244053dcca687a878b1008e3a8219f11d7bd0d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 21 08:58:08 2009 +0100

    [perf] Force rebuild if make fails
    
    The build system has a singular failure whereby if a backend disappears
    between on compile and the next, automake will fail to reconstruct the
    Makefiles - resulting in a broken build. Attempt to fix this by removing
    the build dir and recloning, which should work for any corrupt caches but
    obviously will fail again at a true build failure.

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index 718cdc5..413ac45 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -133,31 +133,9 @@ rev2perf_glob() {
     echo "$CAIRO_PERF_DIR/*-${perf_tree_sha}-${src_tree_sha}.perf"
 }
 
-# Usage: run_cairo_perf_if_not_cached <rev> <suffix>
-# The <rev> argument must be a valid git ref-spec that can
-# be resolved to a commit. The suffix is just something
-# unique so that build directories can be separated for
-# multiple calls to this function.
-run_cairo_perf_if_not_cached() {
-    rev=$1
-    build_dir="build-$2"
-
-    owd=`pwd`
-    sha=`rev2sha $rev`
-    perf=`rev2perf $rev`
-    glob=`rev2perf_glob $rev`
-    if [ -e $glob ] && [ "$force_cairo_perf" != "true" ]; then
-	return 0
-    fi
-    if [ ! -d $CAIRO_PERF_DIR ]; then
-	echo "Creating new perf cache in $CAIRO_PERF_DIR"
-	mkdir $CAIRO_PERF_DIR
-    fi
-
-    cd $CAIRO_DIR
-    boilerplate_files=`git ls-tree --name-only HEAD boilerplate/*`
-    perf_files=`git ls-tree --name-only HEAD perf/*`
-    cd $CAIRO_PERF_DIR
+build() {
+    build_dir=$1
+    sha=$2
 
     if [ ! -d $build_dir ]; then
 	git clone -s $CAIRO_DIR $build_dir
@@ -185,7 +163,40 @@ run_cairo_perf_if_not_cached() {
 	rsync $CAIRO_DIR/$file perf
     done
     cd perf;
-    make cairo-perf || exit 1
+    make cairo-perf
+}
+
+# Usage: run_cairo_perf_if_not_cached <rev> <suffix>
+# The <rev> argument must be a valid git ref-spec that can
+# be resolved to a commit. The suffix is just something
+# unique so that build directories can be separated for
+# multiple calls to this function.
+run_cairo_perf_if_not_cached() {
+    rev=$1
+    build_dir="build-$2"
+
+    owd=`pwd`
+    sha=`rev2sha $rev`
+    perf=`rev2perf $rev`
+    glob=`rev2perf_glob $rev`
+    if [ -e $glob ] && [ "$force_cairo_perf" != "true" ]; then
+	return 0
+    fi
+    if [ ! -d $CAIRO_PERF_DIR ]; then
+	echo "Creating new perf cache in $CAIRO_PERF_DIR"
+	mkdir $CAIRO_PERF_DIR
+    fi
+
+    cd $CAIRO_DIR
+    boilerplate_files=`git ls-tree --name-only HEAD boilerplate/*`
+    perf_files=`git ls-tree --name-only HEAD perf/*`
+    cd $CAIRO_PERF_DIR
+
+    build $build_dir $sha || {
+	rm -rf $build_dir
+	build $build_dir $sha || exit 1
+    }
+
     echo "Running \"cairo-perf $CAIRO_PERF_OPTIONS\" against $rev. Results will be cached in:"
     echo "$perf"
     (./cairo-perf $CAIRO_PERF_OPTIONS || echo "*** Performance test crashed") >> $perf
commit ef0d307d549b9cc7a98cdce2ee4bae40d0fd0bd1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Jun 21 08:43:55 2009 +0100

    [perf] Need to version surface types
    
    As cairo-perf-diff will execute the current cairo-perf against historical
    revisions, any introduced api must be protect in order to compile on old
    versions.

diff --git a/perf/cairo-perf-trace.c b/perf/cairo-perf-trace.c
index 6859a0d..512bfa2 100644
--- a/perf/cairo-perf-trace.c
+++ b/perf/cairo-perf-trace.c
@@ -30,6 +30,8 @@
 
 #define _GNU_SOURCE 1	/* for sched_getaffinity() and getline() */
 
+#include "../cairo-version.h" /* for the real version */
+
 #include "cairo-perf.h"
 #include "cairo-stats.h"
 
@@ -98,9 +100,15 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
+#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,1,2)
     case CAIRO_SURFACE_TYPE_OS2:
+#endif
+#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,9,3)
     case CAIRO_SURFACE_TYPE_QT:
+#endif
+#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,9,3)
     case CAIRO_INTERNAL_SURFACE_TYPE_NULL:
+#endif
 	return TRUE;
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 4965e57..40cc28a 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -28,6 +28,8 @@
 
 #define _GNU_SOURCE 1	/* for sched_getaffinity() */
 
+#include "../cairo-version.h" /* for the real version */
+
 #include "cairo-perf.h"
 #include "cairo-stats.h"
 
@@ -92,8 +94,12 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
+#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,1,2)
     case CAIRO_SURFACE_TYPE_OS2:
+#endif
+#if CAIRO_VERSION > CAIRO_VERSION_ENCODE(1,9,4)
     case CAIRO_SURFACE_TYPE_QT:
+#endif
 	return TRUE;
     case CAIRO_SURFACE_TYPE_PDF:
     case CAIRO_SURFACE_TYPE_PS:
commit 44b72ba6d7bdcc5f4e431af178bc7c22f13e88e0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 20 13:09:46 2009 +0100

    [perf] Add a non-build mode to graph
    
    Add --show to cairo-perf-graph just to graph perf files that currently
    exist and not build the missing cases.

diff --git a/perf/cairo-perf-graph b/perf/cairo-perf-graph
index aa05bf1..a167351 100755
--- a/perf/cairo-perf-graph
+++ b/perf/cairo-perf-graph
@@ -49,6 +49,7 @@ while true; do
     case $1 in
         -f|--force) force_cairo_perf="true";;
         -h|--html) html_output="true";;
+        -s|--show) show_only="true";;
         *) break;;
     esac
 
@@ -136,7 +137,7 @@ run_cairo_perf_if_not_cached() {
     sha=`rev2sha $rev`
     perf=`rev2perf $rev`
     glob=`rev2perf_glob $rev`
-    if [ -e $glob ] && [ "$force_cairo_perf" != "true" ]; then
+    if [ -e $glob ] && [ "$force_cairo_perf" != "true" ]  || [ -n "$show_only" ]; then
 	return 0
     fi
     if [ ! -d $CAIRO_PERF_DIR ]; then
@@ -198,7 +199,7 @@ revs=""
 for rev in `git rev-list --reverse $old..$new`; do
     run_cairo_perf_if_not_cached $rev rev
     perf=`rev2perf $rev`
-    [ -e $perf ] && revs="$revs $perf"
+    [ -e "$perf" ] && revs="$revs $perf"
 done
 
 exec $CAIRO_DIR/perf/cairo-perf-graph-files $revs
commit d4dd6fcf3a4e0d7426657592ebb3d65a2ae0bc4a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 20 13:08:50 2009 +0100

    [perf] Show speedup/slowdownn labels on graph
    
    Add labels show that it is clear which direction is faster on the graph.

diff --git a/perf/cairo-perf-graph-widget.c b/perf/cairo-perf-graph-widget.c
index 2bb48a4..85a5126 100644
--- a/perf/cairo-perf-graph-widget.c
+++ b/perf/cairo-perf-graph-widget.c
@@ -221,7 +221,104 @@ draw_hline (cairo_t *cr, const cairo_matrix_t *m, double y0, double xmin, double
     cairo_stroke (cr);
 }
 
-#define PAD 24
+static void
+draw_label (cairo_t *cr, const cairo_matrix_t *m,
+	    double y0, double xmin, double xmax)
+{
+    double x, y;
+    char buf[80];
+    cairo_text_extents_t extents;
+
+    snprintf (buf, sizeof (buf), "%.0fx", fabs (y0));
+    cairo_text_extents (cr, buf, &extents);
+
+    x = xmin; y = y0;
+    cairo_matrix_transform_point (m, &x, &y);
+    cairo_move_to (cr,
+		   x - extents.width - 4,
+		   y - (extents.height/2. + extents.y_bearing));
+    cairo_show_text (cr, buf);
+
+
+    snprintf (buf, sizeof (buf), "%.0fx", fabs (y0));
+    cairo_text_extents (cr, buf, &extents);
+
+    x = xmax; y = y0;
+    cairo_matrix_transform_point (m, &x, &y);
+    cairo_move_to (cr,
+		   x + 4,
+		   y - (extents.height/2. + extents.y_bearing));
+    cairo_show_text (cr, buf);
+}
+
+#define ALIGN_X(v) ((v)<<0)
+#define ALIGN_Y(v) ((v)<<2)
+static void
+draw_rotated_label (cairo_t *cr, const char *text,
+		    double x, double y, double angle,
+		    int align)
+{
+    cairo_text_extents_t extents;
+
+    cairo_text_extents (cr, text, &extents);
+
+    cairo_save (cr); {
+	cairo_translate (cr, x, y);
+	cairo_rotate (cr, angle);
+	switch (align) {
+	case ALIGN_X(0) | ALIGN_Y(0):
+	    cairo_move_to (cr,
+			   -extents.x_bearing,
+			   -extents.y_bearing);
+	    break;
+	case ALIGN_X(0) | ALIGN_Y(1):
+	    cairo_move_to (cr,
+			   -extents.x_bearing,
+			   - (extents.height/2. + extents.y_bearing));
+	    break;
+	case ALIGN_X(0) | ALIGN_Y(2):
+	    cairo_move_to (cr,
+			   -extents.x_bearing,
+			   - (extents.height + extents.y_bearing));
+	    break;
+
+	case ALIGN_X(1) | ALIGN_Y(0):
+	    cairo_move_to (cr,
+			   - (extents.width/2. + extents.x_bearing),
+			   -extents.y_bearing);
+	    break;
+	case ALIGN_X(1) | ALIGN_Y(1):
+	    cairo_move_to (cr,
+			   - (extents.width/2. + extents.x_bearing),
+			   - (extents.height/2. + extents.y_bearing));
+	    break;
+	case ALIGN_X(1) | ALIGN_Y(2):
+	    cairo_move_to (cr,
+			   - (extents.width/2. + extents.x_bearing),
+			   - (extents.height + extents.y_bearing));
+	    break;
+
+	case ALIGN_X(2) | ALIGN_Y(0):
+	    cairo_move_to (cr,
+			   - (extents.width + extents.x_bearing),
+			   -extents.y_bearing);
+	    break;
+	case ALIGN_X(2) | ALIGN_Y(1):
+	    cairo_move_to (cr,
+			   - (extents.width + extents.x_bearing),
+			   - (extents.height/2. + extents.y_bearing));
+	    break;
+	case ALIGN_X(2) | ALIGN_Y(2):
+	    cairo_move_to (cr,
+			   - (extents.width + extents.x_bearing),
+			   - (extents.height + extents.y_bearing));
+	    break;
+	}
+	cairo_show_text (cr, text);
+    } cairo_restore (cr);
+}
+
+#define PAD 36
 static void
 graph_view_draw (GraphView *self, cairo_t *cr)
 {
@@ -230,11 +327,18 @@ graph_view_draw (GraphView *self, cairo_t *cr)
     double range;
     int i;
 
-    range = ceil (self->ymax) - floor (self->ymin);
+    if (self->widget.allocation.width < 4 *PAD)
+	return;
+    if (self->widget.allocation.height < 3 *PAD)
+	return;
 
-    cairo_matrix_init_translate (&m, PAD, PAD);
-    cairo_matrix_scale (&m, (self->widget.allocation.width-2*PAD)/self->num_reports, (self->widget.allocation.height-2*PAD)/range);
-    cairo_matrix_translate (&m, 0,  - floor (self->ymin));
+    range = floor (self->ymax+1) - ceil (self->ymin-1);
+
+    cairo_matrix_init_translate (&m, PAD, self->widget.allocation.height - PAD);
+    cairo_matrix_scale (&m,
+			(self->widget.allocation.width-2*PAD)/(self->num_reports),
+			-(self->widget.allocation.height-2*PAD)/range);
+    cairo_matrix_translate (&m, 0,   floor (self->ymax+1));
 
     if (self->selected_report != -1) {
 	cairo_save (cr); {
@@ -256,16 +360,56 @@ graph_view_draw (GraphView *self, cairo_t *cr)
     }
 
     cairo_save (cr); {
-	cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
+	cairo_pattern_t *linear;
+	double x, y;
+
+	gdk_cairo_set_source_color (cr,
+				    &self->widget.style->fg[GTK_WIDGET_STATE (self)]);
 	cairo_set_line_width (cr, 2.);
-	draw_hline (cr, &m, 0, 0, self->num_reports-1);
+	draw_hline (cr, &m, 0, 0, self->num_reports);
 
 	cairo_set_line_width (cr, 1.);
 	cairo_set_dash (cr, NULL, 0, 0);
-	for (i = floor (self->ymin); i <= floor (self->ymax); i++) {
+
+	for (i = ceil (self->ymin-1); i <= floor (self->ymax+1); i++) {
 	    if (i != 0)
 		draw_hline (cr, &m, i, 0, self->num_reports);
 	}
+
+	cairo_set_font_size (cr, 11);
+
+	linear = cairo_pattern_create_linear (0, PAD, 0, self->widget.allocation.height-2*PAD);
+	cairo_pattern_add_color_stop_rgb (linear, 0, 0, 1, 0);
+	cairo_pattern_add_color_stop_rgb (linear, 1, 1, 0, 0);
+	cairo_set_source (cr, linear);
+	cairo_pattern_destroy (linear);
+
+	for (i = ceil (self->ymin-1); i <= floor (self->ymax+1); i++) {
+	    if (i != 0)
+		draw_label (cr, &m, i, 0, self->num_reports);
+	}
+
+	x = 0, y = floor (self->ymax+1);
+	cairo_matrix_transform_point (&m, &x, &y);
+	draw_rotated_label (cr, "Faster", x - 7, y + 14,
+			    270./360 * 2 * G_PI,
+			    ALIGN_X(2) | ALIGN_Y(1));
+	x = self->num_reports, y = floor (self->ymax+1);
+	cairo_matrix_transform_point (&m, &x, &y);
+	draw_rotated_label (cr, "Faster", x + 11, y + 14,
+			    270./360 * 2 * G_PI,
+			    ALIGN_X(2) | ALIGN_Y(1));
+
+	x = 0, y = ceil (self->ymin-1);
+	cairo_matrix_transform_point (&m, &x, &y);
+	draw_rotated_label (cr, "Slower", x - 7, y - 14,
+			    90./360 * 2 * G_PI,
+			    ALIGN_X(2) | ALIGN_Y(1));
+	x = self->num_reports, y = ceil (self->ymin-1);
+	cairo_matrix_transform_point (&m, &x, &y);
+	draw_rotated_label (cr, "Slower", x + 11, y - 14,
+			    90./360 * 2 * G_PI,
+			    ALIGN_X(2) | ALIGN_Y(1));
     } cairo_restore (cr);
 
     draw_baseline_performance (self->cases,
@@ -276,9 +420,8 @@ graph_view_draw (GraphView *self, cairo_t *cr)
 	cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
 	cairo_set_line_width (cr, 1.);
 	cairo_set_dash (cr, dash, 2, 0);
-	draw_hline (cr, &m, 0, 0, self->num_reports-1);
+	draw_hline (cr, &m, 0, 0, self->num_reports);
     } cairo_restore (cr);
-
 }
 
 static gboolean
@@ -288,9 +431,6 @@ graph_view_expose (GtkWidget *w, GdkEventExpose *ev)
     cairo_t *cr;
 
     cr = gdk_cairo_create (w->window);
-    gdk_cairo_region (cr, ev->region);
-    cairo_clip (cr);
-
     gdk_cairo_set_source_color (cr, &w->style->base[GTK_WIDGET_STATE (w)]);
     cairo_paint (cr);
 
commit b71b6ecb59bf83605bb2bb10e3f8acd7dd950242
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 19 21:21:02 2009 +0100

    [test] Fix the image compare
    
    Oh, it's a bad sign when I can't even correctly compare a bunch of pixels.

diff --git a/test/cairo-test-trace.c b/test/cairo-test-trace.c
index 5bf058e..4d415b8 100644
--- a/test/cairo-test-trace.c
+++ b/test/cairo-test-trace.c
@@ -570,10 +570,91 @@ matches_reference (struct slave *slave)
 	    return TRUE;
 	}
     } else {
-	return memcmp (cairo_image_surface_get_data (a),
-		       cairo_image_surface_get_data (b),
-		       cairo_image_surface_get_stride (a) *
-		       cairo_image_surface_get_stride (b));
+	int width, height, stride;
+	const uint8_t *aa, *bb;
+	int x, y;
+
+	width = cairo_image_surface_get_width (a);
+	height = cairo_image_surface_get_height (a);
+	stride = cairo_image_surface_get_stride (a);
+
+	aa = cairo_image_surface_get_data (a);
+	bb = cairo_image_surface_get_data (b);
+	switch (cairo_image_surface_get_format (a)) {
+	case CAIRO_FORMAT_ARGB32:
+	    for (y = 0; y < height; y++) {
+		const uint32_t *ua = (uint32_t *) aa;
+		const uint32_t *ub = (uint32_t *) bb;
+		for (x = 0; x < width; x++) {
+		    if (ua[x] != ub[x]) {
+			int channel;
+
+			for (channel = 0; channel < 4; channel++) {
+			    unsigned va, vb, diff;
+
+			    va = (ua[x] >> (channel*8)) & 0xff;
+			    vb = (ub[x] >> (channel*8)) & 0xff;
+			    diff = abs (va - vb);
+			    if (diff > slave->target->error_tolerance)
+				return FALSE;
+			}
+		    }
+		}
+		aa += stride;
+		bb += stride;
+	    }
+	    break;
+
+	case CAIRO_FORMAT_RGB24:
+	    for (y = 0; y < height; y++) {
+		const uint32_t *ua = (uint32_t *) aa;
+		const uint32_t *ub = (uint32_t *) bb;
+		for (x = 0; x < width; x++) {
+		    if ((ua[x] & 0x00ffffff) != (ub[x] & 0x00ffffff)) {
+			int channel;
+
+			for (channel = 0; channel < 3; channel++) {
+			    unsigned va, vb, diff;
+
+			    va = (ua[x] >> (channel*8)) & 0xff;
+			    vb = (ub[x] >> (channel*8)) & 0xff;
+			    diff = abs (va - vb);
+			    if (diff > slave->target->error_tolerance)
+				return FALSE;
+			}
+		    }
+		}
+		aa += stride;
+		bb += stride;
+	    }
+	    break;
+
+	case CAIRO_FORMAT_A8:
+	    for (y = 0; y < height; y++) {
+		for (x = 0; x < width; x++) {
+		    if (aa[x] != bb[x]) {
+			unsigned diff = abs (aa[x] - bb[x]);
+			if (diff > slave->target->error_tolerance)
+			    return FALSE;
+		    }
+		}
+		aa += stride;
+		bb += stride;
+	    }
+	    break;
+
+	case CAIRO_FORMAT_A1:
+	    width /= 8;
+	    for (y = 0; y < height; y++) {
+		if (memcmp (aa, bb, width))
+		    return FALSE;
+		aa += stride;
+		bb += stride;
+	    }
+	    break;
+	}
+
+	return TRUE;
     }
 }
 
@@ -582,9 +663,7 @@ check_images (struct slave *slaves, int num_slaves)
 {
     int n;
 
-    for (n = 1; n < num_slaves; n++) {
-	assert (slaves[n].image_ready == slaves[0].image_ready);
-
+    for (n = 0; n < num_slaves; n++) {
 	if (slaves[n].reference == NULL)
 	    continue;
 
@@ -939,14 +1018,6 @@ _test_trace (test_runner_t *test,
 
     /* spawn slave processes to run the trace */
     s = slaves = xcalloc (2*test->num_targets + 1, sizeof (struct slave));
-    s->pid = spawn_target (socket_path, shm_path, image, trace);
-    if (s->pid < 0)
-	goto cleanup;
-    s->target = image;
-    s->reference = NULL;
-    s->fd = -1;
-    s++;
-
     for (i = 0; i < test->num_targets; i++) {
 	pid_t slave;
 	const cairo_boilerplate_target_t *reference;


More information about the cairo-commit mailing list