[cairo-commit] 3 commits - configure.ac src/cairo-clip-polygon.c src/cairo-clip-private.h src/cairo-surface-observer.c src/cairo-surface-observer-private.h
Chris Wilson
ickle at kemper.freedesktop.org
Thu Aug 18 06:16:11 PDT 2011
configure.ac | 2
src/cairo-clip-polygon.c | 17
src/cairo-clip-private.h | 3
src/cairo-surface-observer-private.h | 31 +
src/cairo-surface-observer.c | 654 ++++++++++++++++++++++++++++-------
5 files changed, 582 insertions(+), 125 deletions(-)
New commits:
commit 2f020c4ade1d26a01605cd908bdaa983e7fe1106
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 18 14:10:20 2011 +0100
obsever: include the operation timings
Seeing the relative amounts of time spent in each operation and the
slowest one of each, gives further insight into the peculiarities of a
trace. And hopefully point out areas of improvement.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/configure.ac b/configure.ac
index 71f8bf3..c7c167e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -622,7 +622,7 @@ dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(mime, mime, always)
CAIRO_ENABLE_SURFACE_BACKEND(recording, recording, always)
-CAIRO_ENABLE_SURFACE_BACKEND(observer, observer, always)
+CAIRO_ENABLE_SURFACE_BACKEND(observer, observer, always, observer_LIBS=-lrt)
CAIRO_ENABLE_SURFACE_BACKEND(tee, tee, no)
CAIRO_ENABLE_SURFACE_BACKEND(xml, xml, no, [
use_xml=$have_libz
diff --git a/src/cairo-surface-observer-private.h b/src/cairo-surface-observer-private.h
index ed05f96..9e18868 100644
--- a/src/cairo-surface-observer-private.h
+++ b/src/cairo-surface-observer-private.h
@@ -70,8 +70,22 @@ struct clip {
};
typedef struct _cairo_observation cairo_observation_t;
+typedef struct _cairo_observation_record cairo_observation_record_t;
typedef struct _cairo_device_observer cairo_device_observer_t;
+struct _cairo_observation_record {
+ cairo_operator_t op;
+ int source;
+ int mask;
+ int num_glyphs;
+ int path;
+ int fill_rule;
+ double tolerance;
+ int antialias;
+ int clip;
+ double elapsed;
+};
+
struct _cairo_observation {
int num_surfaces;
int num_contexts;
@@ -80,15 +94,19 @@ struct _cairo_observation {
/* XXX put interesting stats here! */
struct paint {
+ double elapsed;
unsigned int count;
struct extents extents;
unsigned int operators[NUM_OPERATORS];
struct pattern source;
struct clip clip;
unsigned int noop;
+
+ cairo_observation_record_t slowest;
} paint;
struct mask {
+ double elapsed;
unsigned int count;
struct extents extents;
unsigned int operators[NUM_OPERATORS];
@@ -96,9 +114,12 @@ struct _cairo_observation {
struct pattern mask;
struct clip clip;
unsigned int noop;
+
+ cairo_observation_record_t slowest;
} mask;
struct fill {
+ double elapsed;
unsigned int count;
struct extents extents;
unsigned int operators[NUM_OPERATORS];
@@ -108,9 +129,12 @@ struct _cairo_observation {
unsigned int fill_rule[NUM_FILL_RULE];
struct clip clip;
unsigned int noop;
+
+ cairo_observation_record_t slowest;
} fill;
struct stroke {
+ double elapsed;
unsigned int count;
struct extents extents;
unsigned int operators[NUM_OPERATORS];
@@ -122,15 +146,20 @@ struct _cairo_observation {
struct stat line_width;
struct clip clip;
unsigned int noop;
+
+ cairo_observation_record_t slowest;
} stroke;
struct glyphs {
+ double elapsed;
unsigned int count;
struct extents extents;
unsigned int operators[NUM_OPERATORS];
struct pattern source;
struct clip clip;
unsigned int noop;
+
+ cairo_observation_record_t slowest;
} glyphs;
};
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index a9b5537..06be2c2 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -128,18 +128,17 @@ get_pattern_surface (const cairo_pattern_t *pattern)
return ((cairo_surface_pattern_t *)pattern)->surface;
}
-static void
-add_pattern (struct pattern *stats,
- const cairo_pattern_t *source,
- const cairo_surface_t *target)
+static int
+classify_pattern (const cairo_pattern_t *pattern,
+ const cairo_surface_t *target)
{
int classify;
- switch (source->type) {
+ switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SURFACE:
- if (get_pattern_surface (source)->type == target->type)
+ if (get_pattern_surface (pattern)->type == target->type)
classify = 0;
- else if (get_pattern_surface (source)->type == CAIRO_SURFACE_TYPE_RECORDING)
+ else if (get_pattern_surface (pattern)->type == CAIRO_SURFACE_TYPE_RECORDING)
classify = 1;
else
classify = 2;
@@ -158,13 +157,20 @@ add_pattern (struct pattern *stats,
classify = 6;
break;
}
- stats->type[classify]++;
+ return classify;
}
static void
-add_path (struct path *stats,
- const cairo_path_fixed_t *path,
- cairo_bool_t is_fill)
+add_pattern (struct pattern *stats,
+ const cairo_pattern_t *pattern,
+ const cairo_surface_t *target)
+{
+ stats->type[classify_pattern(pattern, target)]++;
+}
+
+static int
+classify_path (const cairo_path_fixed_t *path,
+ cairo_bool_t is_fill)
{
int classify;
@@ -182,12 +188,20 @@ add_path (struct path *stats,
if (classify == 1 && ! path->fill_maybe_region)
classify = 2;
classify = 3 + path->has_curve_to != 0;
- stats->type[classify]++;
+
+ return classify;
}
static void
-add_clip (struct clip *stats,
- const cairo_clip_t *clip)
+add_path (struct path *stats,
+ const cairo_path_fixed_t *path,
+ cairo_bool_t is_fill)
+{
+ stats->type[classify_path(path, is_fill)]++;
+}
+
+static int
+classify_clip (const cairo_clip_t *clip)
{
int classify;
@@ -204,7 +218,14 @@ add_clip (struct clip *stats,
else
classify = 5;
- stats->type[classify]++;
+ return classify;
+}
+
+static void
+add_clip (struct clip *stats,
+ const cairo_clip_t *clip)
+{
+ stats->type[classify_clip (clip)]++;
}
static void
@@ -407,6 +428,161 @@ _cairo_surface_observer_unmap_image (void *abstract_surface,
return surface->target->backend->unmap_image (surface->target, image);
}
+static void
+record_paint (cairo_observation_record_t *r,
+ cairo_surface_t *target,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_clip_t *clip,
+ double elapsed)
+{
+ r->op = op;
+ r->source = classify_pattern (source, target);
+ r->mask = -1;
+ r->num_glyphs = -1;
+ r->path = -1;
+ r->fill_rule = -1;
+ r->tolerance = -1;
+ r->antialias = -1;
+ r->clip = classify_clip (clip);
+ r->elapsed = elapsed;
+}
+
+static void
+record_mask (cairo_observation_record_t *r,
+ cairo_surface_t *target,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ const cairo_clip_t *clip,
+ double elapsed)
+{
+ r->op = op;
+ r->source = classify_pattern (source, target);
+ r->mask = classify_pattern (mask, target);
+ r->num_glyphs = -1;
+ r->path = -1;
+ r->fill_rule = -1;
+ r->tolerance = -1;
+ r->antialias = -1;
+ r->clip = classify_clip (clip);
+ r->elapsed = elapsed;
+}
+
+static void
+record_fill (cairo_observation_record_t *r,
+ cairo_surface_t *target,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ const cairo_clip_t *clip,
+ double elapsed)
+{
+ r->op = op;
+ r->source = classify_pattern (source, target);
+ r->mask = -1;
+ r->num_glyphs = -1;
+ r->path = classify_path (path, TRUE);
+ r->fill_rule = fill_rule;
+ r->tolerance = tolerance;
+ r->antialias = antialias;
+ r->clip = classify_clip (clip);
+ r->elapsed = elapsed;
+}
+
+static void
+record_stroke (cairo_observation_record_t *r,
+ cairo_surface_t *target,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_path_fixed_t *path,
+ const cairo_stroke_style_t *style,
+ const cairo_matrix_t *ctm,
+ const cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias,
+ const cairo_clip_t *clip,
+ double elapsed)
+{
+ r->op = op;
+ r->source = classify_pattern (source, target);
+ r->mask = -1;
+ r->num_glyphs = -1;
+ r->path = classify_path (path, FALSE);
+ r->fill_rule = -1;
+ r->tolerance = tolerance;
+ r->antialias = antialias;
+ r->clip = classify_clip (clip);
+ r->elapsed = elapsed;
+}
+
+static void
+record_glyphs (cairo_observation_record_t *r,
+ cairo_surface_t *target,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ const cairo_clip_t *clip,
+ double elapsed)
+{
+ r->op = op;
+ r->source = classify_pattern (source, target);
+ r->mask = -1;
+ r->path = -1;
+ r->num_glyphs = num_glyphs;
+ r->fill_rule = -1;
+ r->tolerance = -1;
+ r->antialias = -1;
+ r->clip = classify_clip (clip);
+ r->elapsed = elapsed;
+}
+
+static void
+start_timer (struct timespec *ts)
+{
+ clock_gettime (CLOCK_MONOTONIC, ts);
+}
+
+static double
+stop_timer (const struct timespec *then)
+{
+ struct timespec now;
+ double elapsed;
+
+ clock_gettime (CLOCK_MONOTONIC, &now);
+
+ elapsed = now.tv_nsec - then->tv_nsec;
+ elapsed += 1e9 * (now.tv_sec - then->tv_sec);
+ return elapsed;
+}
+
+static void
+sync (cairo_surface_t *target, int x, int y)
+{
+ cairo_rectangle_t extents;
+
+ extents.x = x;
+ extents.y = y;
+ extents.width = 1;
+ extents.height = 1;
+
+ cairo_surface_unmap_image (target,
+ cairo_surface_map_to_image (target,
+ &extents));
+}
+
+static void
+midpt (const cairo_composite_rectangles_t *extents, int *x, int *y)
+{
+ *x = extents->bounded.x + extents->bounded.width / 2;
+ *y = extents->bounded.y + extents->bounded.height / 2;
+}
+
static cairo_int_status_t
_cairo_surface_observer_paint (void *abstract_surface,
cairo_operator_t op,
@@ -418,6 +594,9 @@ _cairo_surface_observer_paint (void *abstract_surface,
cairo_composite_rectangles_t composite;
cairo_rectangle_int_t extents;
cairo_int_status_t status;
+ struct timespec ts;
+ double elapsed;
+ int x, y;
/* XXX device locking */
@@ -442,14 +621,33 @@ _cairo_surface_observer_paint (void *abstract_surface,
return status;
}
+ midpt (&composite, &x, &y);
+
add_extents (&surface->log.paint.extents, &composite);
add_extents (&device->log.paint.extents, &composite);
_cairo_composite_rectangles_fini (&composite);
- /* XXX time? */
- return _cairo_surface_paint (surface->target,
- op, source,
- clip);
+ start_timer (&ts);
+ status = _cairo_surface_paint (surface->target,
+ op, source,
+ clip);
+ if (unlikely (status))
+ return status;
+
+ sync (surface->target, x, y);
+ elapsed = stop_timer (&ts);
+
+ if (elapsed > surface->log.paint.slowest.elapsed)
+ record_paint (&surface->log.paint.slowest,
+ surface->target, op, source, clip, elapsed);
+ surface->log.paint.elapsed += elapsed;
+
+ if (elapsed > device->log.paint.slowest.elapsed)
+ record_paint (&device->log.paint.slowest,
+ surface->target, op, source, clip, elapsed);
+ device->log.paint.elapsed += elapsed;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -464,6 +662,9 @@ _cairo_surface_observer_mask (void *abstract_surface,
cairo_composite_rectangles_t composite;
cairo_rectangle_int_t extents;
cairo_int_status_t status;
+ struct timespec ts;
+ double elapsed;
+ int x, y;
surface->log.mask.count++;
surface->log.mask.operators[op]++;
@@ -488,13 +689,33 @@ _cairo_surface_observer_mask (void *abstract_surface,
return status;
}
+ midpt (&composite, &x, &y);
+
add_extents (&surface->log.mask.extents, &composite);
add_extents (&device->log.mask.extents, &composite);
_cairo_composite_rectangles_fini (&composite);
- return _cairo_surface_mask (surface->target,
- op, source, mask,
- clip);
+ start_timer (&ts);
+ status = _cairo_surface_mask (surface->target,
+ op, source, mask,
+ clip);
+ if (unlikely (status))
+ return status;
+
+ sync (surface->target, x, y);
+ elapsed = stop_timer (&ts);
+
+ if (elapsed > surface->log.mask.slowest.elapsed)
+ record_mask (&surface->log.mask.slowest,
+ surface->target, op, source, mask, clip, elapsed);
+ surface->log.mask.elapsed += elapsed;
+
+ if (elapsed > device->log.mask.slowest.elapsed)
+ record_mask (&device->log.mask.slowest,
+ surface->target, op, source, mask, clip, elapsed);
+ device->log.mask.elapsed += elapsed;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -512,6 +733,9 @@ _cairo_surface_observer_fill (void *abstract_surface,
cairo_composite_rectangles_t composite;
cairo_rectangle_int_t extents;
cairo_int_status_t status;
+ struct timespec ts;
+ double elapsed;
+ int x, y;
surface->log.fill.count++;
surface->log.fill.operators[op]++;
@@ -540,14 +764,38 @@ _cairo_surface_observer_fill (void *abstract_surface,
return status;
}
+ midpt (&composite, &x, &y);
+
add_extents (&surface->log.fill.extents, &composite);
add_extents (&device->log.fill.extents, &composite);
_cairo_composite_rectangles_fini (&composite);
- return _cairo_surface_fill (surface->target,
- op, source, path,
- fill_rule, tolerance, antialias,
- clip);
+ start_timer (&ts);
+ status = _cairo_surface_fill (surface->target,
+ op, source, path,
+ fill_rule, tolerance, antialias,
+ clip);
+ if (unlikely (status))
+ return status;
+
+ sync (surface->target, x, y);
+ elapsed = stop_timer (&ts);
+
+ if (elapsed > surface->log.fill.slowest.elapsed)
+ record_fill (&surface->log.fill.slowest,
+ surface->target, op, source, path,
+ fill_rule, tolerance, antialias,
+ clip, elapsed);
+ surface->log.fill.elapsed += elapsed;
+
+ if (elapsed > device->log.fill.slowest.elapsed)
+ record_fill (&device->log.fill.slowest,
+ surface->target, op, source, path,
+ fill_rule, tolerance, antialias,
+ clip, elapsed);
+ device->log.fill.elapsed += elapsed;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -567,6 +815,9 @@ _cairo_surface_observer_stroke (void *abstract_surface,
cairo_composite_rectangles_t composite;
cairo_rectangle_int_t extents;
cairo_int_status_t status;
+ struct timespec ts;
+ double elapsed;
+ int x, y;
surface->log.stroke.count++;
surface->log.stroke.operators[op]++;
@@ -598,15 +849,41 @@ _cairo_surface_observer_stroke (void *abstract_surface,
return status;
}
+ midpt (&composite, &x, &y);
+
add_extents (&surface->log.stroke.extents, &composite);
add_extents (&device->log.stroke.extents, &composite);
_cairo_composite_rectangles_fini (&composite);
- return _cairo_surface_stroke (surface->target,
+ start_timer (&ts);
+ status = _cairo_surface_stroke (surface->target,
op, source, path,
style, ctm, ctm_inverse,
tolerance, antialias,
clip);
+ if (unlikely (status))
+ return status;
+
+ sync (surface->target, x, y);
+ elapsed = stop_timer (&ts);
+
+ if (elapsed > surface->log.stroke.slowest.elapsed)
+ record_stroke (&surface->log.stroke.slowest,
+ surface->target, op, source, path,
+ style, ctm,ctm_inverse,
+ tolerance, antialias,
+ clip, elapsed);
+ surface->log.stroke.elapsed += elapsed;
+
+ if (elapsed > device->log.stroke.slowest.elapsed)
+ record_stroke (&device->log.stroke.slowest,
+ surface->target, op, source, path,
+ style, ctm, ctm_inverse,
+ tolerance, antialias,
+ clip, elapsed);
+ device->log.stroke.elapsed += elapsed;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -624,6 +901,9 @@ _cairo_surface_observer_glyphs (void *abstract_surface,
cairo_composite_rectangles_t composite;
cairo_rectangle_int_t extents;
cairo_int_status_t status;
+ struct timespec ts;
+ double elapsed;
+ int x, y;
surface->log.glyphs.count++;
surface->log.glyphs.operators[op]++;
@@ -649,17 +929,41 @@ _cairo_surface_observer_glyphs (void *abstract_surface,
return status;
}
+ midpt (&composite, &x, &y);
+
add_extents (&surface->log.glyphs.extents, &composite);
add_extents (&device->log.glyphs.extents, &composite);
_cairo_composite_rectangles_fini (&composite);
*remaining_glyphs = 0;
- return _cairo_surface_show_text_glyphs (surface->target, op, source,
+ start_timer (&ts);
+ status = _cairo_surface_show_text_glyphs (surface->target, op, source,
NULL, 0,
glyphs, num_glyphs,
NULL, 0, 0,
scaled_font,
clip);
+ if (unlikely (status))
+ return status;
+
+ sync (surface->target, x, y);
+ elapsed = stop_timer (&ts);
+
+ if (elapsed > surface->log.glyphs.slowest.elapsed)
+ record_glyphs (&surface->log.glyphs.slowest,
+ surface->target, op, source,
+ glyphs, num_glyphs, scaled_font,
+ clip, elapsed);
+ surface->log.glyphs.elapsed += elapsed;
+
+ if (elapsed > device->log.glyphs.slowest.elapsed)
+ record_glyphs (&device->log.glyphs.slowest,
+ surface->target, op, source,
+ glyphs, num_glyphs, scaled_font,
+ clip, elapsed);
+ device->log.glyphs.elapsed += elapsed;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@@ -907,145 +1211,190 @@ print_array (cairo_output_stream_t *stream,
i < j -1 ? "," : "");
}
+static const char *operator_names[] = {
+ "CLEAR", /* CAIRO_OPERATOR_CLEAR */
+
+ "SOURCE", /* CAIRO_OPERATOR_SOURCE */
+ "OVER", /* CAIRO_OPERATOR_OVER */
+ "IN", /* CAIRO_OPERATOR_IN */
+ "OUT", /* CAIRO_OPERATOR_OUT */
+ "ATOP", /* CAIRO_OPERATOR_ATOP */
+
+ "DEST", /* CAIRO_OPERATOR_DEST */
+ "DEST_OVER", /* CAIRO_OPERATOR_DEST_OVER */
+ "DEST_IN", /* CAIRO_OPERATOR_DEST_IN */
+ "DEST_OUT", /* CAIRO_OPERATOR_DEST_OUT */
+ "DEST_ATOP", /* CAIRO_OPERATOR_DEST_ATOP */
+
+ "XOR", /* CAIRO_OPERATOR_XOR */
+ "ADD", /* CAIRO_OPERATOR_ADD */
+ "SATURATE", /* CAIRO_OPERATOR_SATURATE */
+
+ "MULTIPLY", /* CAIRO_OPERATOR_MULTIPLY */
+ "SCREEN", /* CAIRO_OPERATOR_SCREEN */
+ "OVERLAY", /* CAIRO_OPERATOR_OVERLAY */
+ "DARKEN", /* CAIRO_OPERATOR_DARKEN */
+ "LIGHTEN", /* CAIRO_OPERATOR_LIGHTEN */
+ "DODGE", /* CAIRO_OPERATOR_COLOR_DODGE */
+ "BURN", /* CAIRO_OPERATOR_COLOR_BURN */
+ "HARD_LIGHT", /* CAIRO_OPERATOR_HARD_LIGHT */
+ "SOFT_LIGHT", /* CAIRO_OPERATOR_SOFT_LIGHT */
+ "DIFFERENCE", /* CAIRO_OPERATOR_DIFFERENCE */
+ "EXCLUSION", /* CAIRO_OPERATOR_EXCLUSION */
+ "HSL_HUE", /* CAIRO_OPERATOR_HSL_HUE */
+ "HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */
+ "HSL_COLOR", /* CAIRO_OPERATOR_HSL_COLOR */
+ "HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */
+};
static void
print_operators (cairo_output_stream_t *stream, unsigned int *array)
{
- static const char *names[] = {
- "CLEAR", /* CAIRO_OPERATOR_CLEAR */
-
- "SOURCE", /* CAIRO_OPERATOR_SOURCE */
- "OVER", /* CAIRO_OPERATOR_OVER */
- "IN", /* CAIRO_OPERATOR_IN */
- "OUT", /* CAIRO_OPERATOR_OUT */
- "ATOP", /* CAIRO_OPERATOR_ATOP */
-
- "DEST", /* CAIRO_OPERATOR_DEST */
- "DEST_OVER", /* CAIRO_OPERATOR_DEST_OVER */
- "DEST_IN", /* CAIRO_OPERATOR_DEST_IN */
- "DEST_OUT", /* CAIRO_OPERATOR_DEST_OUT */
- "DEST_ATOP", /* CAIRO_OPERATOR_DEST_ATOP */
-
- "XOR", /* CAIRO_OPERATOR_XOR */
- "ADD", /* CAIRO_OPERATOR_ADD */
- "SATURATE", /* CAIRO_OPERATOR_SATURATE */
-
- "MULTIPLY", /* CAIRO_OPERATOR_MULTIPLY */
- "SCREEN", /* CAIRO_OPERATOR_SCREEN */
- "OVERLAY", /* CAIRO_OPERATOR_OVERLAY */
- "DARKEN", /* CAIRO_OPERATOR_DARKEN */
- "LIGHTEN", /* CAIRO_OPERATOR_LIGHTEN */
- "DODGE", /* CAIRO_OPERATOR_COLOR_DODGE */
- "BURN", /* CAIRO_OPERATOR_COLOR_BURN */
- "HARD_LIGHT", /* CAIRO_OPERATOR_HARD_LIGHT */
- "SOFT_LIGHT", /* CAIRO_OPERATOR_SOFT_LIGHT */
- "DIFFERENCE", /* CAIRO_OPERATOR_DIFFERENCE */
- "EXCLUSION", /* CAIRO_OPERATOR_EXCLUSION */
- "HSL_HUE", /* CAIRO_OPERATOR_HSL_HUE */
- "HSL_SATURATION", /* CAIRO_OPERATOR_HSL_SATURATION */
- "HSL_COLOR", /* CAIRO_OPERATOR_HSL_COLOR */
- "HSL_LUMINOSITY" /* CAIRO_OPERATOR_HSL_LUMINOSITY */
- };
-
_cairo_output_stream_printf (stream, " op:");
- print_array (stream, array, names, NUM_OPERATORS);
+ print_array (stream, array, operator_names, NUM_OPERATORS);
_cairo_output_stream_printf (stream, "\n");
}
+static const char *fill_rule_names[] = {
+ "non-zero",
+ "even-odd",
+};
+static void
+print_fill_rule (cairo_output_stream_t *stream, unsigned int *array)
+{
+ _cairo_output_stream_printf (stream, " fill rule:");
+ print_array (stream, array, fill_rule_names, ARRAY_LENGTH(fill_rule_names));
+ _cairo_output_stream_printf (stream, "\n");
+}
+
+static const char *cap_names[] = {
+ "butt", /* CAIRO_LINE_CAP_BUTT */
+ "round", /* CAIRO_LINE_CAP_ROUND */
+ "square" /* CAIRO_LINE_CAP_SQUARE */
+};
static void
print_line_caps (cairo_output_stream_t *stream, unsigned int *array)
{
- static const char *names[] = {
- "butt", /* CAIRO_LINE_CAP_BUTT */
- "round", /* CAIRO_LINE_CAP_ROUND */
- "square" /* CAIRO_LINE_CAP_SQUARE */
- };
_cairo_output_stream_printf (stream, " caps:");
- print_array (stream, array, names, NUM_CAPS);
+ print_array (stream, array, cap_names, NUM_CAPS);
_cairo_output_stream_printf (stream, "\n");
}
+static const char *join_names[] = {
+ "miter", /* CAIRO_LINE_JOIN_MITER */
+ "round", /* CAIRO_LINE_JOIN_ROUND */
+ "bevel", /* CAIRO_LINE_JOIN_BEVEL */
+};
static void
print_line_joins (cairo_output_stream_t *stream, unsigned int *array)
{
- static const char *names[] = {
- "miter", /* CAIRO_LINE_JOIN_MITER */
- "round", /* CAIRO_LINE_JOIN_ROUND */
- "bevel", /* CAIRO_LINE_JOIN_BEVEL */
- };
_cairo_output_stream_printf (stream, " joins:");
- print_array (stream, array, names, NUM_JOINS);
+ print_array (stream, array, join_names, NUM_JOINS);
_cairo_output_stream_printf (stream, "\n");
}
+static const char *antialias_names[] = {
+ "default",
+ "none",
+ "gray",
+ "subpixel"
+};
static void
print_antialias (cairo_output_stream_t *stream, unsigned int *array)
{
- static const char *names[] = {
- "default",
- "none",
- "gray",
- "subpixel"
- };
_cairo_output_stream_printf (stream, " antialias:");
- print_array (stream, array, names, NUM_ANTIALIAS);
+ print_array (stream, array, antialias_names, NUM_ANTIALIAS);
_cairo_output_stream_printf (stream, "\n");
}
+static const char *pattern_names[] = {
+ "native",
+ "record",
+ "other surface",
+ "solid",
+ "linear",
+ "radial",
+ "mesh"
+};
static void
print_pattern (cairo_output_stream_t *stream,
const char *name,
const struct pattern *p)
{
- static const char *names[] = {
- "native",
- "record",
- "other surface",
- "solid",
- "linear",
- "radial",
- "mesh"
- };
_cairo_output_stream_printf (stream, " %s:", name);
- print_array (stream, p->type, names, ARRAY_LENGTH (names));
+ print_array (stream, p->type, pattern_names, ARRAY_LENGTH (pattern_names));
_cairo_output_stream_printf (stream, "\n");
}
+static const char *path_names[] = {
+ "empty",
+ "pixel-aligned",
+ "rectliinear",
+ "straight",
+ "curved",
+};
static void
print_path (cairo_output_stream_t *stream,
const struct path *p)
{
- static const char *names[] = {
- "empty",
- "pixel-aligned",
- "rectliinear",
- "straight",
- "curved",
- };
_cairo_output_stream_printf (stream, " path:");
- print_array (stream, p->type, names, ARRAY_LENGTH (names));
+ print_array (stream, p->type, path_names, ARRAY_LENGTH (path_names));
_cairo_output_stream_printf (stream, "\n");
}
+static const char *clip_names[] = {
+ "none",
+ "region",
+ "boxes",
+ "single path",
+ "polygon",
+ "general",
+};
static void
print_clip (cairo_output_stream_t *stream, const struct clip *c)
{
- static const char *names[] = {
- "none",
- "region",
- "boxes",
- "single path",
- "polygon",
- "general",
- };
_cairo_output_stream_printf (stream, " clip:");
- print_array (stream, c->type, names, ARRAY_LENGTH (names));
+ print_array (stream, c->type, clip_names, ARRAY_LENGTH (clip_names));
_cairo_output_stream_printf (stream, "\n");
}
static void
+print_record (cairo_output_stream_t *stream,
+ cairo_observation_record_t *r)
+{
+ _cairo_output_stream_printf (stream, " op: %s\n", operator_names[r->op]);
+ _cairo_output_stream_printf (stream, " source: %s\n",
+ pattern_names[r->source]);
+ if (r->mask != -1)
+ _cairo_output_stream_printf (stream, " mask: %s\n",
+ pattern_names[r->mask]);
+ if (r->num_glyphs != -1)
+ _cairo_output_stream_printf (stream, " num_glyphs: %d\n",
+ r->num_glyphs);
+ if (r->path != -1)
+ _cairo_output_stream_printf (stream, " path: %s\n",
+ path_names[r->path]);
+ if (r->fill_rule != -1)
+ _cairo_output_stream_printf (stream, " fill rule: %s\n",
+ fill_rule_names[r->fill_rule]);
+ if (r->antialias != -1)
+ _cairo_output_stream_printf (stream, " antialias: %s\n",
+ antialias_names[r->antialias]);
+ _cairo_output_stream_printf (stream, " clip: %s\n", clip_names[r->clip]);
+ _cairo_output_stream_printf (stream, " elapsed: %f ns\n", r->elapsed);
+}
+
+static double percent (double a, double b)
+{
+ /* Fake %.1f */
+ return round (a*1000 / b) / 10;
+}
+
+static void
_cairo_observation_print (cairo_output_stream_t *stream,
- cairo_observation_t *log)
+ cairo_observation_t *log)
{
+ double total;
+
_cairo_output_stream_printf (stream, "surfaces: %d\n",
log->num_surfaces);
_cairo_output_stream_printf (stream, "contexts: %d\n",
@@ -1053,38 +1402,75 @@ _cairo_observation_print (cairo_output_stream_t *stream,
_cairo_output_stream_printf (stream, "sources acquired: %d\n",
log->num_sources_acquired);
- _cairo_output_stream_printf (stream, "paint: count %d [no-op %d]\n",
- log->paint.count, log->paint.noop);
+ total = 0;
+ total += log->paint.elapsed;
+ total += log->mask.elapsed;
+ total += log->fill.elapsed;
+ total += log->stroke.elapsed;
+ total += log->glyphs.elapsed;
+
+ _cairo_output_stream_printf (stream, "paint: count %d [no-op %d], elapsed %f [%f%%]\n",
+ log->paint.count, log->paint.noop,
+ log->paint.elapsed,
+ percent (log->paint.elapsed, total));
if (log->paint.count) {
print_extents (stream, &log->paint.extents);
print_operators (stream, log->paint.operators);
print_pattern (stream, "source", &log->paint.source);
print_clip (stream, &log->paint.clip);
+
+ _cairo_output_stream_printf (stream, "slowest paint: %f%%\n",
+ percent (log->paint.slowest.elapsed,
+ log->paint.elapsed));
+ print_record (stream, &log->paint.slowest);
+
+ _cairo_output_stream_printf (stream, "\n");
}
- _cairo_output_stream_printf (stream, "mask: count %d [no-op %d]\n",
- log->mask.count, log->mask.noop);
+ _cairo_output_stream_printf (stream, "mask: count %d [no-op %d], elapsed %f [%f%%]\n",
+ log->mask.count, log->mask.noop,
+ log->mask.elapsed,
+ percent (log->mask.elapsed, total));
if (log->mask.count) {
print_extents (stream, &log->mask.extents);
print_operators (stream, log->mask.operators);
print_pattern (stream, "source", &log->mask.source);
print_pattern (stream, "mask", &log->mask.mask);
print_clip (stream, &log->mask.clip);
+
+ _cairo_output_stream_printf (stream, "slowest mask: %f%%\n",
+ percent (log->mask.slowest.elapsed,
+ log->mask.elapsed));
+ print_record (stream, &log->mask.slowest);
+
+ _cairo_output_stream_printf (stream, "\n");
}
- _cairo_output_stream_printf (stream, "fill: count %d [no-op %d]\n",
- log->fill.count, log->fill.noop);
+ _cairo_output_stream_printf (stream, "fill: count %d [no-op %d], elaspsed %f [%f%%]\n",
+ log->fill.count, log->fill.noop,
+ log->fill.elapsed,
+ percent (log->fill.elapsed, total));
if (log->fill.count) {
print_extents (stream, &log->fill.extents);
print_operators (stream, log->fill.operators);
print_pattern (stream, "source", &log->fill.source);
print_path (stream, &log->fill.path);
+ print_fill_rule (stream, log->fill.fill_rule);
print_antialias (stream, log->fill.antialias);
print_clip (stream, &log->fill.clip);
+
+ _cairo_output_stream_printf (stream, "slowest fill: %f%%\n",
+ percent (log->fill.slowest.elapsed,
+ log->fill.elapsed));
+ print_record (stream, &log->fill.slowest);
+
+ _cairo_output_stream_printf (stream, "\n");
}
- _cairo_output_stream_printf (stream, "stroke: count %d [no-op %d]\n",
- log->stroke.count, log->stroke.noop);
+ _cairo_output_stream_printf (stream, "stroke: count %d [no-op %d], elapsed %f [%f%%]\n",
+ log->stroke.count, log->stroke.noop,
+ log->stroke.elapsed,
+ percent (log->stroke.elapsed, total));
if (log->stroke.count) {
print_extents (stream, &log->stroke.extents);
print_operators (stream, log->stroke.operators);
@@ -1094,15 +1480,31 @@ _cairo_observation_print (cairo_output_stream_t *stream,
print_line_caps (stream, log->stroke.caps);
print_line_joins (stream, log->stroke.joins);
print_clip (stream, &log->stroke.clip);
+
+ _cairo_output_stream_printf (stream, "slowest stroke: %f%%\n",
+ percent (log->stroke.slowest.elapsed,
+ log->stroke.elapsed));
+ print_record (stream, &log->stroke.slowest);
+
+ _cairo_output_stream_printf (stream, "\n");
}
- _cairo_output_stream_printf (stream, "glyphs: count %d [no-op %d]\n",
- log->glyphs.count, log->glyphs.noop);
+ _cairo_output_stream_printf (stream, "glyphs: count %d [no-op %d], elasped %f [%f%%]\n",
+ log->glyphs.count, log->glyphs.noop,
+ log->glyphs.elapsed,
+ percent (log->glyphs.elapsed, total));
if (log->glyphs.count) {
print_extents (stream, &log->glyphs.extents);
print_operators (stream, log->glyphs.operators);
print_pattern (stream, "source", &log->glyphs.source);
print_clip (stream, &log->glyphs.clip);
+
+ _cairo_output_stream_printf (stream, "slowest glyphs: %f%%\n",
+ percent (log->glyphs.slowest.elapsed,
+ log->glyphs.elapsed));
+ print_record (stream, &log->glyphs.slowest);
+
+ _cairo_output_stream_printf (stream, "\n");
}
}
commit 4d5502503c2c6f3c04cf21750ba71caafecf06d8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 18 12:41:20 2011 +0100
observer: put a comma between array items when printing
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 4baf709..a9b5537 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -902,8 +902,9 @@ print_array (cairo_output_stream_t *stream,
sort_order (order, j, (void *)array);
for (i = 0; i < j; i++)
- _cairo_output_stream_printf (stream, " %d %s",
- array[order[i]], names[order[i]]);
+ _cairo_output_stream_printf (stream, " %d %s%s",
+ array[order[i]], names[order[i]],
+ i < j -1 ? "," : "");
}
static void
commit d03b0057b2865b2d51f80d874f030e52ee0c4aca
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 18 12:37:57 2011 +0100
observer: further classify general clips
A clip with only a single path or can be reduced to a single polygon are
easier to handle than a clip containing a mixture of paths (typically
ANTIALIAS_NONE vs ANTIALIAS_DEFAULT).
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-clip-polygon.c b/src/cairo-clip-polygon.c
index 19da15d..0e1968d 100644
--- a/src/cairo-clip-polygon.c
+++ b/src/cairo-clip-polygon.c
@@ -125,3 +125,20 @@ _cairo_clip_get_polygon (const cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
+
+cairo_bool_t
+_cairo_clip_is_polygon (const cairo_clip_t *clip)
+{
+ if (_cairo_clip_is_all_clipped (clip))
+ return TRUE;
+
+ /* If there is no clip, we need an infinite polygon */
+ if (clip == NULL)
+ return FALSE;
+
+ if (clip->path == NULL)
+ return TRUE;
+
+ /* check that residual is all of the same type/tolerance */
+ return can_convert_to_polygon (clip);
+}
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index f2cfd63..3ebcb0e 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -204,6 +204,9 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
cairo_private cairo_rectangle_list_t *
_cairo_rectangle_list_create_in_error (cairo_status_t status);
+cairo_private cairo_bool_t
+_cairo_clip_is_polygon (const cairo_clip_t *clip);
+
cairo_private cairo_int_status_t
_cairo_clip_get_polygon (const cairo_clip_t *clip,
cairo_polygon_t *polygon,
diff --git a/src/cairo-surface-observer-private.h b/src/cairo-surface-observer-private.h
index 7383a73..ed05f96 100644
--- a/src/cairo-surface-observer-private.h
+++ b/src/cairo-surface-observer-private.h
@@ -66,7 +66,7 @@ struct path {
};
struct clip {
- unsigned int type[4]; /* none, region, boxes, general */
+ unsigned int type[6]; /* none, region, boxes, single path, polygon, general */
};
typedef struct _cairo_observation cairo_observation_t;
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 3bd9682..4baf709 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -197,11 +197,14 @@ add_clip (struct clip *stats,
classify = 1;
else if (clip->path == NULL)
classify = 2;
- else
+ else if (clip->path->prev == NULL)
classify = 3;
+ else if (_cairo_clip_is_polygon (clip))
+ classify = 4;
+ else
+ classify = 5;
stats->type[classify]++;
-
}
static void
@@ -1029,7 +1032,9 @@ print_clip (cairo_output_stream_t *stream, const struct clip *c)
"none",
"region",
"boxes",
- "general path",
+ "single path",
+ "polygon",
+ "general",
};
_cairo_output_stream_printf (stream, " clip:");
print_array (stream, c->type, names, ARRAY_LENGTH (names));
More information about the cairo-commit
mailing list