[cairo-commit] 6 commits - perf/cairo-perf.h perf/cairo-perf-micro.c perf/micro src/cairo-scaled-font.c src/cairo-types-private.h src/cairo-xcb-surface-render.c src/drm

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 30 07:28:46 PDT 2010


 perf/cairo-perf-micro.c            |   47 +++++++++------
 perf/cairo-perf.h                  |    9 ++
 perf/micro/box-outline.c           |    4 -
 perf/micro/cairo-perf-cover.c      |    5 -
 perf/micro/composite-checker.c     |    2 
 perf/micro/dragon.c                |   10 +--
 perf/micro/fill.c                  |    6 -
 perf/micro/glyphs.c                |  114 ++++++++++++++++++++++++++++++++++---
 perf/micro/intersections.c         |    8 +-
 perf/micro/long-dashed-lines.c     |    2 
 perf/micro/long-lines.c            |    8 +-
 perf/micro/mask.c                  |   18 ++---
 perf/micro/mosaic.c                |    8 +-
 perf/micro/paint-with-alpha.c      |    2 
 perf/micro/paint.c                 |    2 
 perf/micro/pattern_create_radial.c |    2 
 perf/micro/pythagoras-tree.c       |    2 
 perf/micro/rectangles.c            |    6 -
 perf/micro/rounded-rectangles.c    |    6 -
 perf/micro/spiral.c                |   28 ++++-----
 perf/micro/stroke.c                |    4 -
 perf/micro/subimage_copy.c         |    2 
 perf/micro/tessellate.c            |    6 -
 perf/micro/text.c                  |    2 
 perf/micro/twin.c                  |    2 
 perf/micro/unaligned-clip.c        |    2 
 perf/micro/world-map.c             |    2 
 perf/micro/zrusin.c                |    4 -
 src/cairo-scaled-font.c            |   73 ++++++-----------------
 src/cairo-types-private.h          |    1 
 src/cairo-xcb-surface-render.c     |   10 +++
 src/drm/cairo-drm-i915-shader.c    |   26 ++++----
 src/drm/cairo-drm-i915-spans.c     |    7 +-
 33 files changed, 266 insertions(+), 164 deletions(-)

New commits:
commit 5c4b6d520bc7ce7d5193a89bbda44b91f5eb0d4d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 30 15:26:42 2010 +0100

    xcb: Cache whether we have already check a glyph for size.
    
    Avoid repeated cairo_scaled_glyph_lookup() and checking of sizes if we
    have already seen this glyph in this run.

diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 0fc3cb4..c1e480c 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -3603,14 +3603,22 @@ _can_composite_glyphs (cairo_xcb_surface_t *dst,
 		       cairo_glyph_t *glyphs,
 		       int num_glyphs)
 {
+    unsigned long glyph_cache[64];
     cairo_status_t status;
     const int max_glyph_size = dst->connection->maximum_request_length - 64;
     int i;
 
+    memset (glyph_cache, 0, sizeof (glyph_cache));
+
     /* first scan for oversized glyphs, and fallback in that case */
     for (i = 0; i < num_glyphs; i++) {
 	cairo_scaled_glyph_t *scaled_glyph;
 	int width, height, len;
+	int g;
+
+	g = glyphs[i].index % ARRAY_LENGTH (glyph_cache);
+	if (glyph_cache[g] == glyphs[i].index)
+	    continue;
 
 	status = _cairo_scaled_glyph_lookup (scaled_font,
 					     glyphs[i].index,
@@ -3629,6 +3637,8 @@ _can_composite_glyphs (cairo_xcb_surface_t *dst,
 	len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, 32) * height;
 	if (len >= max_glyph_size)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	glyph_cache[g] = glyphs[i].index;
     }
 
     return CAIRO_STATUS_SUCCESS;
commit 1c76e3e9ad1437662bf91ed1d21c4bda8fd50fb4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 30 15:24:08 2010 +0100

    scaled-font: Optimize cairo_scaled_font_lookup()
    
    By tracking which fields of information are already available on the
    scaled_glyph we can more efficiently determine if we already have the
    requested fields. This reduces from about 6 conditionals to one, and
    reduces the function overhead by ~20% -- which has a measurable
    improvement on glyph benchmarks.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index c2ba407..70e8805 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2483,6 +2483,8 @@ _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
 
     scaled_glyph->x_advance = _cairo_lround (device_x_advance);
     scaled_glyph->y_advance = _cairo_lround (device_y_advance);
+
+    scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_METRICS;
 }
 
 void
@@ -2496,6 +2498,7 @@ _cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
     /* sanity check the backend glyph contents */
     _cairo_debug_check_image_surface_is_defined (&surface->base);
     scaled_glyph->surface = surface;
+    scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
 }
 
 void
@@ -2506,6 +2509,7 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
     if (scaled_glyph->path != NULL)
 	_cairo_path_fixed_destroy (scaled_glyph->path);
     scaled_glyph->path = path;
+    scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
 }
 
 void
@@ -2519,6 +2523,7 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
     }
 
     scaled_glyph->recording_surface = recording_surface;
+    scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
 }
 
 static cairo_bool_t
@@ -2645,6 +2650,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
     cairo_scaled_glyph_t	*scaled_glyph;
     cairo_scaled_glyph_info_t	 need_info;
 
+    *scaled_glyph_ret = NULL;
+
     if (unlikely (scaled_font->status))
 	return scaled_font->status;
 
@@ -2659,7 +2666,7 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
     if (scaled_glyph == NULL) {
 	status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph);
 	if (unlikely (status))
-	    goto CLEANUP;
+	    goto err;
 
 	memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t));
 	_cairo_scaled_glyph_set_index (scaled_glyph, index);
@@ -2671,14 +2678,14 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 						     info | CAIRO_SCALED_GLYPH_INFO_METRICS);
 	if (unlikely (status)) {
 	    _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
-	    goto CLEANUP;
+	    goto err;
 	}
 
 	status = _cairo_hash_table_insert (scaled_font->glyphs,
 					   &scaled_glyph->hash_entry);
 	if (unlikely (status)) {
 	    _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
-	    goto CLEANUP;
+	    goto err;
 	}
     }
 
@@ -2686,69 +2693,29 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
      * Check and see if the glyph, as provided,
      * already has the requested data and amend it if not
      */
-    need_info = 0;
-    if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
-	scaled_glyph->surface == NULL)
-    {
-	need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
-    }
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
-	scaled_glyph->path == NULL)
-    {
-	need_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
-    }
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) != 0 &&
-	scaled_glyph->recording_surface == NULL)
-    {
-	need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
-    }
-
+    need_info = info & ~scaled_glyph->has_info;
     if (need_info) {
 	status = scaled_font->backend->scaled_glyph_init (scaled_font,
 							  scaled_glyph,
 							  need_info);
 	if (unlikely (status))
-	    goto CLEANUP;
+	    goto err;
 
 	/* Don't trust the scaled_glyph_init() return value, the font
 	 * backend may not even know about some of the info.  For example,
 	 * no backend other than the user-fonts knows about recording-surface
 	 * glyph info. */
-
-	if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 &&
-	    scaled_glyph->surface == NULL)
-	{
-	    status = CAIRO_INT_STATUS_UNSUPPORTED;
-	    goto CLEANUP;
-	}
-
-	if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
-	    scaled_glyph->path == NULL)
-	{
-	    status = CAIRO_INT_STATUS_UNSUPPORTED;
-	    goto CLEANUP;
-	}
-
-	if ((info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) != 0 &&
-	    scaled_glyph->recording_surface == NULL)
-	{
-	    status = CAIRO_INT_STATUS_UNSUPPORTED;
-	    goto CLEANUP;
-	}
+	if (info & ~scaled_glyph->has_info)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-  CLEANUP:
-    if (unlikely (status)) {
-	/* It's not an error for the backend to not support the info we want. */
-	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
-	    status = _cairo_scaled_font_set_error (scaled_font, status);
-	*scaled_glyph_ret = NULL;
-    } else {
-	*scaled_glyph_ret = scaled_glyph;
-    }
+    *scaled_glyph_ret = scaled_glyph;
+    return CAIRO_STATUS_SUCCESS;
 
+err:
+    /* It's not an error for the backend to not support the info we want. */
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	status = _cairo_scaled_font_set_error (scaled_font, status);
     return status;
 }
 
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index f3d14b3..0b8f4db 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -415,6 +415,7 @@ typedef struct _cairo_scaled_glyph {
     int16_t                 x_advance;		/* device-space rounded X advance */
     int16_t                 y_advance;		/* device-space rounded Y advance */
 
+    unsigned int	    has_info;
     cairo_image_surface_t   *surface;		/* device-space image */
     cairo_path_fixed_t	    *path;		/* device-space outline */
     cairo_surface_t         *recording_surface;	/* device-space recording-surface */
commit d2ec151e490b227e7f3d6879bf7a893577dfefa5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 30 15:23:18 2010 +0100

    perf/micro: Exercise different sizes and antialising modes with glyphs

diff --git a/perf/micro/glyphs.c b/perf/micro/glyphs.c
index 0012e85..ae70a8e 100644
--- a/perf/micro/glyphs.c
+++ b/perf/micro/glyphs.c
@@ -28,17 +28,29 @@
 #include "cairo-perf.h"
 
 static cairo_perf_ticks_t
-do_glyphs (cairo_t *cr, int width, int height, int loops)
+do_glyphs (double font_size,
+	   cairo_antialias_t antialias,
+	   cairo_t *cr, int width, int height, int loops)
 {
     const char text[] = "the jay, pig, fox, zebra and my wolves quack";
     cairo_scaled_font_t *scaled_font;
     cairo_glyph_t *glyphs = NULL, *glyphs_copy;
     cairo_text_extents_t extents;
+    cairo_font_options_t *options;
     cairo_status_t status;
     double x, y;
     int num_glyphs, n;
 
-    cairo_set_font_size (cr, 9);
+    options = cairo_font_options_create ();
+    cairo_font_options_set_antialias (options, antialias);
+    cairo_set_font_options (cr, options);
+    cairo_font_options_destroy (options);
+
+    cairo_select_font_face (cr,
+			    "@cairo:",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size (cr, font_size);
     scaled_font = cairo_get_scaled_font (cr);
     status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
 					       text, -1,
@@ -71,15 +83,12 @@ do_glyphs (cairo_t *cr, int width, int height, int loops)
 		    glyphs_copy[n].y += y;
 		}
 		cairo_show_glyphs (cr, glyphs_copy, num_glyphs);
-		if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
-		    goto out;
 
 		x += extents.width;
 	    } while (x < width);
 	    y += extents.height;
 	} while (y < height);
     }
-out:
 
     cairo_perf_timer_stop ();
 
@@ -90,17 +99,29 @@ out:
 }
 
 static double
-count_glyphs (cairo_t *cr, int width, int height)
+count_glyphs (double font_size,
+	      cairo_antialias_t antialias,
+	      cairo_t *cr, int width, int height)
 {
     const char text[] = "the jay, pig, fox, zebra and my wolves quack";
     cairo_scaled_font_t *scaled_font;
     cairo_glyph_t *glyphs = NULL;
     cairo_text_extents_t extents;
+    cairo_font_options_t *options;
     cairo_status_t status;
     int num_glyphs;
     int glyphs_per_line, lines_per_loop;
 
-    cairo_set_font_size (cr, 9);
+    options = cairo_font_options_create ();
+    cairo_font_options_set_antialias (options, antialias);
+    cairo_set_font_options (cr, options);
+    cairo_font_options_destroy (options);
+
+    cairo_select_font_face (cr,
+			    "@cairo:",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_set_font_size (cr, font_size);
     scaled_font = cairo_get_scaled_font (cr);
     status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
 					       text, -1,
@@ -120,11 +141,59 @@ count_glyphs (cairo_t *cr, int width, int height)
     return glyphs_per_line * lines_per_loop / 1000.; /* kiloglyphs */
 }
 
+#define DECL(name,size, aa) \
+static cairo_perf_ticks_t \
+do_glyphs##name (cairo_t *cr, int width, int height, int loops) \
+{ \
+    return do_glyphs (size, aa, cr, width, height, loops); \
+} \
+\
+static double \
+count_glyphs##name (cairo_t *cr, int width, int height) \
+{ \
+    return count_glyphs (size, aa, cr, width, height); \
+}
+
+DECL(8, 8, CAIRO_ANTIALIAS_GRAY)
+DECL(10, 10, CAIRO_ANTIALIAS_GRAY)
+DECL(12, 12, CAIRO_ANTIALIAS_GRAY)
+DECL(16, 16, CAIRO_ANTIALIAS_GRAY)
+DECL(20, 20, CAIRO_ANTIALIAS_GRAY)
+DECL(24, 24, CAIRO_ANTIALIAS_GRAY)
+DECL(32, 32, CAIRO_ANTIALIAS_GRAY)
+DECL(40, 40, CAIRO_ANTIALIAS_GRAY)
+DECL(48, 48, CAIRO_ANTIALIAS_GRAY)
+
+DECL(8ca, 8, CAIRO_ANTIALIAS_SUBPIXEL)
+DECL(48ca, 48, CAIRO_ANTIALIAS_SUBPIXEL)
+
+DECL(8mono, 8, CAIRO_ANTIALIAS_NONE)
+DECL(48mono, 48, CAIRO_ANTIALIAS_NONE)
+
 void
 glyphs (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     if (! cairo_perf_can_run (perf, "glyphs", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "glyphs", do_glyphs, count_glyphs);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs8mono", do_glyphs8mono, count_glyphs8mono);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs8", do_glyphs8, count_glyphs8);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs8ca", do_glyphs8ca, count_glyphs8ca);
+
+    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+    cairo_set_source_rgb (cr, 0, 0, 0);
+
+    cairo_perf_run (perf, "glyphs8", do_glyphs8, count_glyphs8);
+    cairo_perf_run (perf, "glyphs10", do_glyphs10, count_glyphs10);
+    cairo_perf_run (perf, "glyphs12", do_glyphs12, count_glyphs12);
+    cairo_perf_run (perf, "glyphs16", do_glyphs16, count_glyphs16);
+    cairo_perf_run (perf, "glyphs20", do_glyphs20, count_glyphs20);
+    cairo_perf_run (perf, "glyphs24", do_glyphs24, count_glyphs24);
+    cairo_perf_run (perf, "glyphs32", do_glyphs32, count_glyphs32);
+    cairo_perf_run (perf, "glyphs40", do_glyphs40, count_glyphs40);
+    cairo_perf_run (perf, "glyphs48", do_glyphs48, count_glyphs48);
+
+    cairo_perf_cover_sources_and_operators (perf, "glyphs48mono", do_glyphs48mono, count_glyphs48mono);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs48", do_glyphs48, count_glyphs48);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs48ca", do_glyphs48ca, count_glyphs48ca);
 }
commit 72481acf0d1e8648c5d03ce51f84c639132475a9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 30 04:10:28 2010 +0100

    perf: Compute ops per second
    
    Provide a hook for the test to be able to compute the number of ops per
    second. For instance, the glyphs test uses it to report the number of
    kiloglyph per second Cairo is able to render.

diff --git a/perf/cairo-perf-micro.c b/perf/cairo-perf-micro.c
index ec40409..e8b2820 100644
--- a/perf/cairo-perf-micro.c
+++ b/perf/cairo-perf-micro.c
@@ -130,14 +130,16 @@ cairo_perf_calibrate (cairo_perf_t *perf,
     cairo_perf_ticks_t calibration0, calibration;
     unsigned loops, min_loops;
 
-    calibration0 = perf_func (perf->cr, perf->size, perf->size, 1);
+    min_loops = 1;
+    calibration0 = perf_func (perf->cr, perf->size, perf->size, min_loops);
     if (perf->fast_and_sloppy) {
 	calibration = calibration0;
     } else {
-	loops = cairo_perf_ticks_per_second () / 100 / calibration0;
-	if (loops < 3)
-	    loops = 3;
-	calibration = (calibration0 + perf_func (perf->cr, perf->size, perf->size, loops)) / (loops + 1);
+	calibration = 0.01 * cairo_perf_ticks_per_second ();
+	while (calibration0 < calibration) {
+	    min_loops *= 10;
+	    calibration0 = perf_func (perf->cr, perf->size, perf->size, min_loops);
+	}
     }
 
     /* XXX
@@ -151,7 +153,7 @@ cairo_perf_calibrate (cairo_perf_t *perf,
      * a more rigorous analysis of the synchronisation overhead,
      * that is to estimate the time for loop=0.
      */
-    loops = perf->ms_per_iteration * 0.001 * cairo_perf_ticks_per_second () / calibration;
+    loops = perf->ms_per_iteration * 0.001 * cairo_perf_ticks_per_second () * min_loops / calibration;
     min_loops = perf->fast_and_sloppy ? 1 : 10;
     if (loops < min_loops)
 	loops = min_loops;
@@ -162,7 +164,8 @@ cairo_perf_calibrate (cairo_perf_t *perf,
 void
 cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
-		cairo_perf_func_t	 perf_func)
+		cairo_perf_func_t	 perf_func,
+		cairo_count_func_t	 count_func)
 {
     static cairo_bool_t first_run = TRUE;
     unsigned int i, similar, has_similar;
@@ -256,8 +259,7 @@ cairo_perf_run (cairo_perf_t		*perf,
 		if (i > 0) {
 		    _cairo_stats_compute (&stats, times, i+1);
 
-		    if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV)
-		    {
+		    if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV) {
 			low_std_dev_count++;
 			if (low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT)
 			    break;
@@ -273,12 +275,23 @@ cairo_perf_run (cairo_perf_t		*perf,
 
 	if (perf->summary) {
 	    _cairo_stats_compute (&stats, times, i);
-	    fprintf (perf->summary,
-		     "%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
-		     (long long) stats.min_ticks,
-		     (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
-		     (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
-		     stats.std_dev * 100.0, stats.iterations);
+	    if (count_func != NULL) {
+		double count = count_func (perf->cr, perf->size, perf->size);
+		fprintf (perf->summary,
+			 "%10lld %#8.3f %#8.3f %#5.2f%% %3d: %.2f\n",
+			 (long long) stats.min_ticks,
+			 (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+			 (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+			 stats.std_dev * 100.0, stats.iterations,
+			 count * cairo_perf_ticks_per_second () / stats.min_ticks);
+	    } else {
+		fprintf (perf->summary,
+			 "%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
+			 (long long) stats.min_ticks,
+			 (stats.min_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+			 (stats.median_ticks * 1000.0) / cairo_perf_ticks_per_second (),
+			 stats.std_dev * 100.0, stats.iterations);
+	    }
 	    fflush (perf->summary);
 	}
 
@@ -517,8 +530,8 @@ const cairo_perf_case_t perf_cases[] = {
     { fill,   64, 512},
     { stroke, 64, 512},
     { text,   64, 512},
-    { glyphs,   64, 512},
-    { mask,  64, 512},
+    { glyphs, 64, 512},
+    { mask,   64, 512},
     { tessellate, 100, 100},
     { subimage_copy, 16, 512},
     { pattern_create_radial, 16, 16},
diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h
index 6d1741a..c4eeb16 100644
--- a/perf/cairo-perf.h
+++ b/perf/cairo-perf.h
@@ -99,6 +99,9 @@ typedef struct _cairo_perf {
 typedef cairo_perf_ticks_t
 (*cairo_perf_func_t) (cairo_t *cr, int width, int height, int loops);
 
+typedef double
+(*cairo_count_func_t) (cairo_t *cr, int width, int height);
+
 cairo_bool_t
 cairo_perf_can_run (cairo_perf_t	*perf,
 		    const char		*name,
@@ -107,12 +110,14 @@ cairo_perf_can_run (cairo_perf_t	*perf,
 void
 cairo_perf_run (cairo_perf_t		*perf,
 		const char		*name,
-		cairo_perf_func_t	 perf_func);
+		cairo_perf_func_t	 perf_func,
+		cairo_count_func_t	 count_func);
 
 void
 cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
 					const char		*name,
-					cairo_perf_func_t	 perf_func);
+					cairo_perf_func_t	 perf_func,
+					cairo_count_func_t	 count_func);
 
 /* reporter convenience routines */
 
diff --git a/perf/micro/box-outline.c b/perf/micro/box-outline.c
index e216b79..fe0719f 100644
--- a/perf/micro/box-outline.c
+++ b/perf/micro/box-outline.c
@@ -97,6 +97,6 @@ box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "box-outline", NULL))
 	return;
 
-    cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke);
-    cairo_perf_run (perf, "box-outline-fill", box_outline_fill);
+    cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke, NULL);
+    cairo_perf_run (perf, "box-outline-fill", box_outline_fill, NULL);
 }
diff --git a/perf/micro/cairo-perf-cover.c b/perf/micro/cairo-perf-cover.c
index 48f13a8..151a2e6 100644
--- a/perf/micro/cairo-perf-cover.c
+++ b/perf/micro/cairo-perf-cover.c
@@ -295,7 +295,8 @@ typedef void (*set_source_func_t) (cairo_t *cr, int width, int height);
 void
 cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
 					const char		*name,
-					cairo_perf_func_t	 perf_func)
+					cairo_perf_func_t	 perf_func,
+					cairo_count_func_t	 count_func)
 {
     unsigned int i, j;
     char *expanded_name;
@@ -332,7 +333,7 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t		*perf,
 
 	    xasprintf (&expanded_name, "%s_%s_%s",
 		       name, sources[i].name, operators[j].name);
-	    cairo_perf_run (perf, expanded_name, perf_func);
+	    cairo_perf_run (perf, expanded_name, perf_func, count_func);
 	    free (expanded_name);
 	}
     }
diff --git a/perf/micro/composite-checker.c b/perf/micro/composite-checker.c
index 0e61ec8..27dc364 100644
--- a/perf/micro/composite-checker.c
+++ b/perf/micro/composite-checker.c
@@ -107,7 +107,7 @@ composite_checker (cairo_perf_t *perf,
     cairo_pattern_set_filter (src_pattern, CAIRO_FILTER_NEAREST);
     cairo_surface_destroy (image);
 
-    cairo_perf_run (perf, "composite-checker", do_composite_checker);
+    cairo_perf_run (perf, "composite-checker", do_composite_checker, NULL);
 
     cairo_pattern_destroy (checkerboard);
     cairo_pattern_destroy (src_pattern);
diff --git a/perf/micro/dragon.c b/perf/micro/dragon.c
index eb8251c..78da5b2 100644
--- a/perf/micro/dragon.c
+++ b/perf/micro/dragon.c
@@ -241,9 +241,9 @@ dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "dragon", NULL))
 	return;
 
-    cairo_perf_run (perf, "dragon-solid", do_dragon_solid);
-    cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip);
-    cairo_perf_run (perf, "dragon-solid-unaligned-clip", do_dragon_solid_unaligned_clip);
-    cairo_perf_run (perf, "dragon-solid-circle-clip", do_dragon_solid_circle_clip);
-    cairo_perf_run (perf, "dragon", do_dragon);
+    cairo_perf_run (perf, "dragon-solid", do_dragon_solid, NULL);
+    cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip, NULL);
+    cairo_perf_run (perf, "dragon-solid-unaligned-clip", do_dragon_solid_unaligned_clip, NULL);
+    cairo_perf_run (perf, "dragon-solid-circle-clip", do_dragon_solid_circle_clip, NULL);
+    cairo_perf_run (perf, "dragon", do_dragon, NULL);
 }
diff --git a/perf/micro/fill.c b/perf/micro/fill.c
index c65a649..a11298f 100644
--- a/perf/micro/fill.c
+++ b/perf/micro/fill.c
@@ -113,7 +113,7 @@ fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "fill", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "fill", do_fill);
-    cairo_perf_cover_sources_and_operators (perf, "fill-annuli", do_fill_annuli);
-    cairo_perf_cover_sources_and_operators (perf, "fill-eo-noaa", do_fill_eo_noaa);
+    cairo_perf_cover_sources_and_operators (perf, "fill", do_fill, NULL);
+    cairo_perf_cover_sources_and_operators (perf, "fill-annuli", do_fill_annuli, NULL);
+    cairo_perf_cover_sources_and_operators (perf, "fill-eo-noaa", do_fill_eo_noaa, NULL);
 }
diff --git a/perf/micro/glyphs.c b/perf/micro/glyphs.c
index 25175d5..0012e85 100644
--- a/perf/micro/glyphs.c
+++ b/perf/micro/glyphs.c
@@ -57,11 +57,11 @@ do_glyphs (cairo_t *cr, int width, int height, int loops)
     cairo_scaled_font_glyph_extents (scaled_font,
 				     glyphs, num_glyphs,
 				     &extents);
-    y = 0;
 
     cairo_perf_timer_start ();
 
     while (loops--) {
+	y = 0;
 	do {
 	    x = 0;
 	    do {
@@ -89,11 +89,42 @@ out:
     return cairo_perf_timer_elapsed ();
 }
 
+static double
+count_glyphs (cairo_t *cr, int width, int height)
+{
+    const char text[] = "the jay, pig, fox, zebra and my wolves quack";
+    cairo_scaled_font_t *scaled_font;
+    cairo_glyph_t *glyphs = NULL;
+    cairo_text_extents_t extents;
+    cairo_status_t status;
+    int num_glyphs;
+    int glyphs_per_line, lines_per_loop;
+
+    cairo_set_font_size (cr, 9);
+    scaled_font = cairo_get_scaled_font (cr);
+    status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
+					       text, -1,
+					       &glyphs, &num_glyphs,
+					       NULL, NULL,
+					       NULL);
+    if (status)
+	return 0;
+
+    cairo_scaled_font_glyph_extents (scaled_font,
+				     glyphs, num_glyphs,
+				     &extents);
+    cairo_glyph_free (glyphs);
+
+    glyphs_per_line = num_glyphs * width / extents.width + 1;
+    lines_per_loop = height / extents.height + 1;
+    return glyphs_per_line * lines_per_loop / 1000.; /* kiloglyphs */
+}
+
 void
 glyphs (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 {
     if (! cairo_perf_can_run (perf, "glyphs", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "glyphs", do_glyphs);
+    cairo_perf_cover_sources_and_operators (perf, "glyphs", do_glyphs, count_glyphs);
 }
diff --git a/perf/micro/intersections.c b/perf/micro/intersections.c
index 0418ee3..8f55165 100644
--- a/perf/micro/intersections.c
+++ b/perf/micro/intersections.c
@@ -149,9 +149,9 @@ intersections (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "intersections", NULL))
 	return;
 
-    cairo_perf_run (perf, "intersections-nz-fill", random_nz);
-    cairo_perf_run (perf, "intersections-eo-fill", random_eo);
+    cairo_perf_run (perf, "intersections-nz-fill", random_nz, NULL);
+    cairo_perf_run (perf, "intersections-eo-fill", random_eo, NULL);
 
-    cairo_perf_run (perf, "intersections-nz-curve-fill", random_curve_nz);
-    cairo_perf_run (perf, "intersections-eo-curve-fill", random_curve_eo);
+    cairo_perf_run (perf, "intersections-nz-curve-fill", random_curve_nz, NULL);
+    cairo_perf_run (perf, "intersections-eo-curve-fill", random_curve_eo, NULL);
 }
diff --git a/perf/micro/long-dashed-lines.c b/perf/micro/long-dashed-lines.c
index c4de24f..74de158 100644
--- a/perf/micro/long-dashed-lines.c
+++ b/perf/micro/long-dashed-lines.c
@@ -67,5 +67,5 @@ long_dashed_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "long-dashed-lines", NULL))
 	return;
 
-    cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines);
+    cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines, NULL);
 }
diff --git a/perf/micro/long-lines.c b/perf/micro/long-lines.c
index 2b72879..577f17c 100644
--- a/perf/micro/long-lines.c
+++ b/perf/micro/long-lines.c
@@ -138,8 +138,8 @@ long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "long-lines", NULL))
 	return;
 
-    cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
-    cairo_perf_run (perf, "long-lines-uncropped-once", long_lines_uncropped_once);
-    cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
-    cairo_perf_run (perf, "long-lines-cropped-once", long_lines_cropped_once);
+    cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped, NULL);
+    cairo_perf_run (perf, "long-lines-uncropped-once", long_lines_uncropped_once, NULL);
+    cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped, NULL);
+    cairo_perf_run (perf, "long-lines-cropped-once", long_lines_cropped_once, NULL);
 }
diff --git a/perf/micro/mask.c b/perf/micro/mask.c
index 3050b44..840d43f 100644
--- a/perf/micro/mask.c
+++ b/perf/micro/mask.c
@@ -279,21 +279,21 @@ mask (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 	return;
 
     cairo_perf_cover_sources_and_operators (perf, "mask-solid",
-					    do_mask_solid);
+					    do_mask_solid, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-image",
-					    do_mask_image);
+					    do_mask_image, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-image-half",
-					    do_mask_image_half);
+					    do_mask_image_half, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-image-double",
-					    do_mask_image_double);
+					    do_mask_image_double, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-similar",
-					    do_mask_similar);
+					    do_mask_similar, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-similar-half",
-					    do_mask_similar_half);
+					    do_mask_similar_half, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-similar-double",
-					    do_mask_similar_double);
+					    do_mask_similar_double, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-linear",
-					    do_mask_linear);
+					    do_mask_linear, NULL);
     cairo_perf_cover_sources_and_operators (perf, "mask-radial",
-					    do_mask_radial);
+					    do_mask_radial, NULL);
 }
diff --git a/perf/micro/mosaic.c b/perf/micro/mosaic.c
index b762105..a63166c 100644
--- a/perf/micro/mosaic.c
+++ b/perf/micro/mosaic.c
@@ -166,8 +166,8 @@ mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "mosaic", NULL))
 	return;
 
-    cairo_perf_run (perf, "mosaic-fill-curves", mosaic_fill_curves);
-    cairo_perf_run (perf, "mosaic-fill-lines", mosaic_fill_lines);
-    cairo_perf_run (perf, "mosaic-tessellate-curves", mosaic_tessellate_curves);
-    cairo_perf_run (perf, "mosaic-tessellate-lines", mosaic_tessellate_lines);
+    cairo_perf_run (perf, "mosaic-fill-curves", mosaic_fill_curves, NULL);
+    cairo_perf_run (perf, "mosaic-fill-lines", mosaic_fill_lines, NULL);
+    cairo_perf_run (perf, "mosaic-tessellate-curves", mosaic_tessellate_curves, NULL);
+    cairo_perf_run (perf, "mosaic-tessellate-lines", mosaic_tessellate_lines, NULL);
 }
diff --git a/perf/micro/paint-with-alpha.c b/perf/micro/paint-with-alpha.c
index 5c23fe4..048cdb0 100644
--- a/perf/micro/paint-with-alpha.c
+++ b/perf/micro/paint-with-alpha.c
@@ -45,5 +45,5 @@ paint_with_alpha (cairo_perf_t *perf, cairo_t *cr, int width, int height)
 	return;
 
     cairo_perf_cover_sources_and_operators (perf, "paint-with-alpha",
-					    do_paint_with_alpha);
+					    do_paint_with_alpha, NULL);
 }
diff --git a/perf/micro/paint.c b/perf/micro/paint.c
index bdc014c..ce8cfd3 100644
--- a/perf/micro/paint.c
+++ b/perf/micro/paint.c
@@ -44,5 +44,5 @@ paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "paint", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "paint", do_paint);
+    cairo_perf_cover_sources_and_operators (perf, "paint", do_paint, NULL);
 }
diff --git a/perf/micro/pattern_create_radial.c b/perf/micro/pattern_create_radial.c
index 2959e74..7104c00 100644
--- a/perf/micro/pattern_create_radial.c
+++ b/perf/micro/pattern_create_radial.c
@@ -99,5 +99,5 @@ pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     }
 
     cairo_perf_run (perf, "pattern-create-radial",
-                          do_pattern_create_radial);
+                          do_pattern_create_radial, NULL);
 }
diff --git a/perf/micro/pythagoras-tree.c b/perf/micro/pythagoras-tree.c
index f2200c9..964d5c1 100644
--- a/perf/micro/pythagoras-tree.c
+++ b/perf/micro/pythagoras-tree.c
@@ -87,5 +87,5 @@ pythagoras_tree (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "pythagoras-tree", NULL))
 	return;
 
-    cairo_perf_run (perf, "pythagoras-tree", do_pythagoras_tree);
+    cairo_perf_run (perf, "pythagoras-tree", do_pythagoras_tree, NULL);
 }
diff --git a/perf/micro/rectangles.c b/perf/micro/rectangles.c
index 601a0c5..6bfbc65 100644
--- a/perf/micro/rectangles.c
+++ b/perf/micro/rectangles.c
@@ -112,7 +112,7 @@ rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
         rects[i].height = (rand () % (height / 10)) + 1;
     }
 
-    MODE (perf, "one-rectangle", do_rectangle);
-    MODE (perf, "rectangles", do_rectangles);
-    MODE (perf, "rectangles-once", do_rectangles_once);
+    MODE (perf, "one-rectangle", do_rectangle, NULL);
+    MODE (perf, "rectangles", do_rectangles, NULL);
+    MODE (perf, "rectangles-once", do_rectangles_once, NULL);
 }
diff --git a/perf/micro/rounded-rectangles.c b/perf/micro/rounded-rectangles.c
index 477abf2..4db62fc 100644
--- a/perf/micro/rounded-rectangles.c
+++ b/perf/micro/rounded-rectangles.c
@@ -135,7 +135,7 @@ rounded_rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
         rects[i].height = (rand () % (height / 10)) + 1;
     }
 
-    MODE (perf, "one-rounded-rectangle", do_rectangle);
-    MODE (perf, "rounded-rectangles", do_rectangles);
-    MODE (perf, "rounded-rectangles-once", do_rectangles_once);
+    MODE (perf, "one-rounded-rectangle", do_rectangle, NULL);
+    MODE (perf, "rounded-rectangles", do_rectangles, NULL);
+    MODE (perf, "rounded-rectangles-once", do_rectangles_once, NULL);
 }
diff --git a/perf/micro/spiral.c b/perf/micro/spiral.c
index 046351c..10bb918 100644
--- a/perf/micro/spiral.c
+++ b/perf/micro/spiral.c
@@ -332,18 +332,18 @@ spiral (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "spiral", NULL))
 	return;
 
-    cairo_perf_run (perf, "spiral-box-nonalign-evenodd-fill", draw_spiral_eo_na_box);
-    cairo_perf_run (perf, "spiral-box-nonalign-nonzero-fill", draw_spiral_nz_na_box);
-    cairo_perf_run (perf, "spiral-box-pixalign-evenodd-fill", draw_spiral_eo_pa_box);
-    cairo_perf_run (perf, "spiral-box-pixalign-nonzero-fill", draw_spiral_nz_pa_box);
-    cairo_perf_run (perf, "spiral-diag-nonalign-evenodd-fill", draw_spiral_eo_na_di);
-    cairo_perf_run (perf, "spiral-diag-nonalign-nonzero-fill", draw_spiral_nz_na_di);
-    cairo_perf_run (perf, "spiral-diag-pixalign-evenodd-fill", draw_spiral_eo_pa_di);
-    cairo_perf_run (perf, "spiral-diag-pixalign-nonzero-fill", draw_spiral_nz_pa_di);
-    cairo_perf_run (perf, "spiral-rect-nonalign-evenodd-fill", draw_spiral_eo_na_re);
-    cairo_perf_run (perf, "spiral-rect-nonalign-nonzero-fill", draw_spiral_nz_na_re);
-    cairo_perf_run (perf, "spiral-rect-pixalign-evenodd-fill", draw_spiral_eo_pa_re);
-    cairo_perf_run (perf, "spiral-rect-pixalign-nonzero-fill", draw_spiral_nz_pa_re);
-    cairo_perf_run (perf, "spiral-nonalign-stroke", draw_spiral_stroke_na);
-    cairo_perf_run (perf, "spiral-pixalign-stroke", draw_spiral_stroke_pa);
+    cairo_perf_run (perf, "spiral-box-nonalign-evenodd-fill", draw_spiral_eo_na_box, NULL);
+    cairo_perf_run (perf, "spiral-box-nonalign-nonzero-fill", draw_spiral_nz_na_box, NULL);
+    cairo_perf_run (perf, "spiral-box-pixalign-evenodd-fill", draw_spiral_eo_pa_box, NULL);
+    cairo_perf_run (perf, "spiral-box-pixalign-nonzero-fill", draw_spiral_nz_pa_box, NULL);
+    cairo_perf_run (perf, "spiral-diag-nonalign-evenodd-fill", draw_spiral_eo_na_di, NULL);
+    cairo_perf_run (perf, "spiral-diag-nonalign-nonzero-fill", draw_spiral_nz_na_di, NULL);
+    cairo_perf_run (perf, "spiral-diag-pixalign-evenodd-fill", draw_spiral_eo_pa_di, NULL);
+    cairo_perf_run (perf, "spiral-diag-pixalign-nonzero-fill", draw_spiral_nz_pa_di, NULL);
+    cairo_perf_run (perf, "spiral-rect-nonalign-evenodd-fill", draw_spiral_eo_na_re, NULL);
+    cairo_perf_run (perf, "spiral-rect-nonalign-nonzero-fill", draw_spiral_nz_na_re, NULL);
+    cairo_perf_run (perf, "spiral-rect-pixalign-evenodd-fill", draw_spiral_eo_pa_re, NULL);
+    cairo_perf_run (perf, "spiral-rect-pixalign-nonzero-fill", draw_spiral_nz_pa_re, NULL);
+    cairo_perf_run (perf, "spiral-nonalign-stroke", draw_spiral_stroke_na, NULL);
+    cairo_perf_run (perf, "spiral-pixalign-stroke", draw_spiral_stroke_pa, NULL);
 }
diff --git a/perf/micro/stroke.c b/perf/micro/stroke.c
index 660dce5..950fb48 100644
--- a/perf/micro/stroke.c
+++ b/perf/micro/stroke.c
@@ -92,6 +92,6 @@ stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "stroke", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke);
-    cairo_perf_cover_sources_and_operators (perf, "strokes", do_strokes);
+    cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke, NULL);
+    cairo_perf_cover_sources_and_operators (perf, "strokes", do_strokes, NULL);
 }
diff --git a/perf/micro/subimage_copy.c b/perf/micro/subimage_copy.c
index 0bfad80..8c70464 100644
--- a/perf/micro/subimage_copy.c
+++ b/perf/micro/subimage_copy.c
@@ -73,5 +73,5 @@ subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     cairo_set_source_surface (cr, image, 0, 0);
     cairo_surface_destroy (image);
 
-    cairo_perf_run (perf, "subimage-copy", do_subimage_copy);
+    cairo_perf_run (perf, "subimage-copy", do_subimage_copy, NULL);
 }
diff --git a/perf/micro/tessellate.c b/perf/micro/tessellate.c
index 9debc53..38effff 100644
--- a/perf/micro/tessellate.c
+++ b/perf/micro/tessellate.c
@@ -147,9 +147,9 @@ tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "tessellate", NULL))
 	return;
 
-    cairo_perf_run (perf, "tessellate-16", tessellate_16);
-    cairo_perf_run (perf, "tessellate-64", tessellate_64);
-    cairo_perf_run (perf, "tessellate-256", tessellate_256);
+    cairo_perf_run (perf, "tessellate-16", tessellate_16, NULL);
+    cairo_perf_run (perf, "tessellate-64", tessellate_64, NULL);
+    cairo_perf_run (perf, "tessellate-256", tessellate_256, NULL);
 }
 
 #if 0
diff --git a/perf/micro/text.c b/perf/micro/text.c
index 827bb88..190c3c2 100644
--- a/perf/micro/text.c
+++ b/perf/micro/text.c
@@ -62,5 +62,5 @@ text (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "text", NULL))
 	return;
 
-    cairo_perf_cover_sources_and_operators (perf, "text", do_text);
+    cairo_perf_cover_sources_and_operators (perf, "text", do_text, NULL);
 }
diff --git a/perf/micro/twin.c b/perf/micro/twin.c
index b2c37a2..2bc01ed 100644
--- a/perf/micro/twin.c
+++ b/perf/micro/twin.c
@@ -52,5 +52,5 @@ twin (cairo_perf_t *perf,
     if (! cairo_perf_can_run (perf, "twin", NULL))
 	return;
 
-    cairo_perf_run (perf, "twin", do_twin);
+    cairo_perf_run (perf, "twin", do_twin, NULL);
 }
diff --git a/perf/micro/unaligned-clip.c b/perf/micro/unaligned-clip.c
index 284c832..adc44fe 100644
--- a/perf/micro/unaligned-clip.c
+++ b/perf/micro/unaligned-clip.c
@@ -66,5 +66,5 @@ unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "unaligned-clip", NULL))
 	return;
 
-    cairo_perf_run (perf, "unaligned-clip", do_unaligned_clip);
+    cairo_perf_run (perf, "unaligned-clip", do_unaligned_clip, NULL);
 }
diff --git a/perf/micro/world-map.c b/perf/micro/world-map.c
index 2a45500..42b8da5 100644
--- a/perf/micro/world-map.c
+++ b/perf/micro/world-map.c
@@ -112,5 +112,5 @@ world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "world-map", NULL))
 	return;
 
-    cairo_perf_run (perf, "world-map", do_world_map);
+    cairo_perf_run (perf, "world-map", do_world_map, NULL);
 }
diff --git a/perf/micro/zrusin.c b/perf/micro/zrusin.c
index 24aff14..87c8da3 100644
--- a/perf/micro/zrusin.c
+++ b/perf/micro/zrusin.c
@@ -90,6 +90,6 @@ zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
     if (! cairo_perf_can_run (perf, "zrusin", NULL))
 	return;
 
-    cairo_perf_run (perf, "zrusin-another-tessellate", zrusin_another_tessellate);
-    cairo_perf_run (perf, "zrusin-another-fill", zrusin_another_fill);
+    cairo_perf_run (perf, "zrusin-another-tessellate", zrusin_another_tessellate, NULL);
+    cairo_perf_run (perf, "zrusin-another-fill", zrusin_another_fill, NULL);
 }
commit 2a98d0586c19fbb2b555f471895d73f253c4943b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 15 18:23:23 2010 +0000

    drm/i915: Avoid using another unpreserved temporary
    
    As we may load from a sampler, we can not use on of the unpreserved
    temporaries to store the intermediate colour result.

diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index 1435737..13f9d85 100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -925,18 +925,22 @@ i915_set_shader_program (i915_device_t *device,
 		} else {
 		    out_reg = FS_OC;
 		    if (shader->content == CAIRO_CONTENT_ALPHA)
-			out_reg = FS_U0;
+			out_reg = FS_R3;
 		    i915_fs_mov (out_reg,
 				 i915_fs_operand_reg_pure (mask_reg, source_pure));
 		    source_reg = out_reg;
 		}
 	    } else if (mask_reg) {
 		out_reg = FS_OC;
-		if (shader->content == CAIRO_CONTENT_ALPHA)
-		    out_reg = FS_U0;
-		i915_fs_mul (out_reg,
-			     i915_fs_operand_reg (source_reg),
-			     i915_fs_operand (mask_reg, W, W, W, W));
+		if ((shader->content & CAIRO_CONTENT_COLOR) == 0) {
+		    i915_fs_mul (out_reg,
+				 i915_fs_operand (source_reg, W, W, W, W),
+				 i915_fs_operand (mask_reg, W, W, W, W));
+		} else {
+		    i915_fs_mul (out_reg,
+				 i915_fs_operand_reg (source_reg),
+				 i915_fs_operand (mask_reg, W, W, W, W));
+		}
 
 		source_reg = out_reg;
 	    }
@@ -944,14 +948,14 @@ i915_set_shader_program (i915_device_t *device,
 	    /* (source OP dest)  LERP_clip dest */
 	    if (source_reg == ~0U) {
 		if (source_pure == 0) {
-		    i915_fs_mov (FS_U0,
+		    i915_fs_mov (FS_R3,
 				 i915_fs_operand (mask_reg, W, W, W, W));
 		} else {
-		    i915_fs_mov (FS_U0,
+		    i915_fs_mov (FS_R3,
 				 i915_fs_operand_impure (mask_reg, W, source_pure));
 		}
 	    } else {
-		i915_fs_mul (FS_U0,
+		i915_fs_mul (FS_R3,
 			     i915_fs_operand_reg (source_reg),
 			     i915_fs_operand (mask_reg, W, W, W, W));
 	    }
@@ -978,9 +982,9 @@ i915_set_shader_program (i915_device_t *device,
 
 	    source_reg = FS_OC;
 	    if (shader->content != CAIRO_CONTENT_COLOR_ALPHA)
-		source_reg = FS_U0;
+		source_reg = FS_R3;
 	    i915_fs_add (source_reg,
-			 i915_fs_operand_reg (FS_U0),
+			 i915_fs_operand_reg (FS_R3),
 			 i915_fs_operand_reg (mask_reg));
 	}
     }
commit 26f963557bf065fd25b9c4f6652a252735a0fb74
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 15 18:22:06 2010 +0000

    drm/i915: Normalize spans opacity value
    
    On the generic path I forgot to rescale the alpha value into [0,1].

diff --git a/src/drm/cairo-drm-i915-spans.c b/src/drm/cairo-drm-i915-spans.c
index 6ede4cc..3d32f49 100644
--- a/src/drm/cairo-drm-i915-spans.c
+++ b/src/drm/cairo-drm-i915-spans.c
@@ -249,6 +249,7 @@ i915_span_generic (i915_spans_t *spans,
 {
     double s, t;
     float *vertices;
+    float a = alpha / 255.;
 
     /* Each vertex is:
      *   2 vertex coordinates
@@ -277,7 +278,7 @@ i915_span_generic (i915_spans_t *spans,
 	*vertices++ = texcoord_2d_16 (s, t);
 	break;
     }
-    *vertices++ = alpha;
+    *vertices++ = a;
     if (spans->need_clip_surface) {
 	s = x1, t = y1;
 	cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);
@@ -307,7 +308,7 @@ i915_span_generic (i915_spans_t *spans,
 	*vertices++ = texcoord_2d_16 (s, t);
 	break;
     }
-    *vertices++ = alpha;
+    *vertices++ = a;
     if (spans->need_clip_surface) {
 	s = x0, t = y1;
 	cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);
@@ -337,7 +338,7 @@ i915_span_generic (i915_spans_t *spans,
 	*vertices++ = texcoord_2d_16 (s, t);
 	break;
     }
-    *vertices++ = alpha;
+    *vertices++ = a;
     if (spans->need_clip_surface) {
 	s = x0, t = y0;
 	cairo_matrix_transform_point (&spans->shader.clip.base.matrix, &s, &t);


More information about the cairo-commit mailing list