diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-07-30 17:28:21 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-09-12 08:29:48 +0100 |
commit | af9fbd176b145f042408ef5391eef2a51d7531f8 (patch) | |
tree | 5f75d1087d4325a013af6f0a4204a666fb4ca4f0 /perf | |
parent | 0540bf384aed344899417d3b0313bd6704679c1c (diff) |
Introduce a new compositor architecture
Having spent the last dev cycle looking at how we could specialize the
compositors for various backends, we once again look for the
commonalities in order to reduce the duplication. In part this is
motivated by the idea that spans is a good interface for both the
existent GL backend and pixman, and so they deserve a dedicated
compositor. xcb/xlib target an identical rendering system and so they
should be using the same compositor, and it should be possible to run
that same compositor locally against pixman to generate reference tests.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
P.S. This brings massive upheaval (read breakage) I've tried delaying in
order to fix as many things as possible but now this one patch does far,
far, far too much. Apologies in advance for breaking your favourite
backend, but trust me in that the end result will be much better. :)
Diffstat (limited to 'perf')
50 files changed, 1321 insertions, 236 deletions
diff --git a/perf/Makefile.sources b/perf/Makefile.sources index b99234b27..1fcf14809 100644 --- a/perf/Makefile.sources +++ b/perf/Makefile.sources @@ -1,5 +1,6 @@ libcairoperf_sources = \ - cairo-perf.c \ + cairo-perf.c \ + cairo-perf-report.c \ cairo-stats.c \ $(NULL) diff --git a/perf/cairo-perf-compare-backends.c b/perf/cairo-perf-compare-backends.c index 163063774..2cbb24c5d 100644 --- a/perf/cairo-perf-compare-backends.c +++ b/perf/cairo-perf-compare-backends.c @@ -73,7 +73,7 @@ print_change_bar (double change, double max_change, int use_utf) { - int units_per_cell = (int) ceil (max_change / CHANGE_BAR_WIDTH); + int units_per_cell = ceil (max_change / CHANGE_BAR_WIDTH); static char const *ascii_boxes[8] = { "****","***" ,"***", "**", "**", "*", "*", "" @@ -369,7 +369,7 @@ main (int argc, if (args.num_filenames) { reports = xcalloc (args.num_filenames, sizeof (cairo_perf_report_t)); for (i = 0; i < args.num_filenames; i++) { - cairo_perf_report_load (&reports[i], args.filenames[i], + cairo_perf_report_load (&reports[i], args.filenames[i], i, test_report_cmp_name); printf ("loaded: %s, %d tests\n", args.filenames[i], reports[i].tests_count); @@ -377,7 +377,7 @@ main (int argc, } else { args.num_filenames = 1; reports = xcalloc (args.num_filenames, sizeof (cairo_perf_report_t)); - cairo_perf_report_load (&reports[0], NULL, test_report_cmp_name); + cairo_perf_report_load (&reports[0], NULL, 0, test_report_cmp_name); } cairo_perf_reports_compare (reports, args.num_filenames, &args.options); diff --git a/perf/cairo-perf-diff-files.c b/perf/cairo-perf-diff-files.c index 34311b044..08509271f 100644 --- a/perf/cairo-perf-diff-files.c +++ b/perf/cairo-perf-diff-files.c @@ -161,16 +161,14 @@ test_diff_print_binary (test_diff_t *diff, else printf ("%5s %26s", diff->tests[0]->backend, diff->tests[0]->name); - if (diff->tests[0]->size) { - printf (" %6.2f (%.2f %4.2f%%) -> %6.2f (%.2f %4.2f%%): %5.2fx ", - diff->tests[0]->stats.min_ticks / diff->tests[0]->stats.ticks_per_ms, - diff->tests[0]->stats.median_ticks / diff->tests[0]->stats.ticks_per_ms, - diff->tests[0]->stats.std_dev * 100, - diff->tests[1]->stats.min_ticks / diff->tests[1]->stats.ticks_per_ms, - diff->tests[1]->stats.median_ticks / diff->tests[1]->stats.ticks_per_ms, - diff->tests[1]->stats.std_dev * 100, - fabs (diff->change)); - } + printf (" %6.2f (%.2f %4.2f%%) -> %6.2f (%.2f %4.2f%%): %5.2fx ", + diff->tests[0]->stats.min_ticks / diff->tests[0]->stats.ticks_per_ms, + diff->tests[0]->stats.median_ticks / diff->tests[0]->stats.ticks_per_ms, + diff->tests[0]->stats.std_dev * 100, + diff->tests[1]->stats.min_ticks / diff->tests[1]->stats.ticks_per_ms, + diff->tests[1]->stats.median_ticks / diff->tests[1]->stats.ticks_per_ms, + diff->tests[1]->stats.std_dev * 100, + fabs (diff->change)); if (diff->change > 1.0) printf ("speedup\n"); @@ -191,24 +189,32 @@ test_diff_print_multi (test_diff_t *diff, double test_time; double change; - printf ("%s (backend: %s-%s, size: %d)\n", - diff->tests[0]->name, - diff->tests[0]->backend, - diff->tests[0]->content, - diff->tests[0]->size); + if (diff->tests[0]->size) { + printf ("%s (backend: %s-%s, size: %d)\n", + diff->tests[0]->name, + diff->tests[0]->backend, + diff->tests[0]->content, + diff->tests[0]->size); + } else { + printf ("%s (backend: %s)\n", + diff->tests[0]->name, + diff->tests[0]->backend); + } for (i = 0; i < diff->num_tests; i++) { test_time = diff->tests[i]->stats.min_ticks; if (! options->use_ticks) test_time /= diff->tests[i]->stats.ticks_per_ms; change = diff->max / test_time; - printf ("%8s %6.2f: %5.2fx ", - diff->tests[i]->configuration, + printf ("[%d] %6.2f: %5.2fx ", + diff->tests[i]->fileno, diff->tests[i]->stats.min_ticks / diff->tests[i]->stats.ticks_per_ms, change); if (options->print_change_bars) print_change_bar (change, max_change, options->use_utf); + else + printf("\n"); } printf("\n"); @@ -476,8 +482,11 @@ main (int argc, reports = xmalloc (args.num_filenames * sizeof (cairo_perf_report_t)); - for (i = 0; i < args.num_filenames; i++ ) - cairo_perf_report_load (&reports[i], args.filenames[i], NULL); + for (i = 0; i < args.num_filenames; i++ ) { + cairo_perf_report_load (&reports[i], args.filenames[i], i, NULL); + printf ("[%d] %s\n", i, args.filenames[i]); + } + printf ("\n"); cairo_perf_reports_compare (reports, args.num_filenames, &args.options); diff --git a/perf/cairo-perf-micro.c b/perf/cairo-perf-micro.c index 096986bcd..f3c6f8d9d 100644 --- a/perf/cairo-perf-micro.c +++ b/perf/cairo-perf-micro.c @@ -50,12 +50,13 @@ #define CAIRO_PERF_ITERATIONS_DEFAULT 100 #define CAIRO_PERF_LOW_STD_DEV 0.03 -#define CAIRO_PERF_STABLE_STD_DEV_COUNT 5 -#define CAIRO_PERF_ITERATION_MS_DEFAULT 2000 +#define CAIRO_PERF_STABLE_STD_DEV_COUNT 5 +#define CAIRO_PERF_ITERATION_MS_DEFAULT 2000 #define CAIRO_PERF_ITERATION_MS_FAST 5 typedef struct _cairo_perf_case { - CAIRO_PERF_DECL (*run); + CAIRO_PERF_RUN_DECL (*run); + cairo_bool_t (*enabled) (cairo_perf_t *perf); unsigned int min_size; unsigned int max_size; } cairo_perf_case_t; @@ -251,7 +252,7 @@ cairo_perf_run (cairo_perf_t *perf, cairo_boilerplate_content (perf->target->content)); else cairo_save (perf->cr); - times[i] = perf_func (perf->cr, perf->size, perf->size, loops) / loops; + times[i] = perf_func (perf->cr, perf->size, perf->size, loops) ; if (similar) cairo_pattern_destroy (cairo_pop_group (perf->cr)); else @@ -263,7 +264,7 @@ cairo_perf_run (cairo_perf_t *perf, _content_to_string (perf->target->content, similar), name, perf->size, _cairo_time_to_double (_cairo_time_from_s (1.)) / 1000.); - printf (" %lld", (long long) times[i]); + printf (" %lld", (long long) (times[i] / (double) loops)); } else if (! perf->exact_iterations) { if (i > 0) { _cairo_stats_compute (&stats, times, i+1); @@ -287,18 +288,18 @@ cairo_perf_run (cairo_perf_t *perf, 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, - _cairo_time_to_s (stats.min_ticks) * 1000.0, - _cairo_time_to_s (stats.median_ticks) * 1000.0, + "%10lld/%d %#8.3f %#8.3f %#5.2f%% %3d: %.2f\n", + (long long) stats.min_ticks, loops, + _cairo_time_to_s (stats.min_ticks) * 1000.0 / loops, + _cairo_time_to_s (stats.median_ticks) * 1000.0 / loops, stats.std_dev * 100.0, stats.iterations, count / _cairo_time_to_s (stats.min_ticks)); } else { fprintf (perf->summary, - "%10lld %#8.3f %#8.3f %#5.2f%% %3d\n", - (long long) stats.min_ticks, - _cairo_time_to_s (stats.min_ticks) * 1000.0, - _cairo_time_to_s (stats.median_ticks) * 1000.0, + "%10lld/%d %#8.3f %#8.3f %#5.2f%% %3d\n", + (long long) stats.min_ticks, loops, + _cairo_time_to_s (stats.min_ticks) * 1000.0 / loops, + _cairo_time_to_s (stats.median_ticks) * 1000.0 / loops, stats.std_dev * 100.0, stats.iterations); } fflush (perf->summary); @@ -491,6 +492,9 @@ main (int argc, for (j = 0; perf_cases[j].run; j++) { const cairo_perf_case_t *perf_case = &perf_cases[j]; + if (! perf_case->enabled (&perf)) + continue; + for (perf.size = perf_case->min_size; perf.size <= perf_case->max_size; perf.size *= 2) @@ -536,42 +540,48 @@ main (int argc, return 0; } +#define FUNC(f) f, f##_enabled const cairo_perf_case_t perf_cases[] = { - { paint, 64, 512}, - { paint_with_alpha, 64, 512}, - { fill, 64, 512}, - { stroke, 64, 512}, - { text, 64, 512}, - { glyphs, 64, 512}, - { mask, 64, 512}, - { line, 32, 512}, - { curve, 32, 512}, - { disjoint, 64, 512}, - { hatching, 64, 512}, - { tessellate, 100, 100}, - { subimage_copy, 16, 512}, - { hash_table, 16, 16}, - { pattern_create_radial, 16, 16}, - { zrusin, 415, 415}, - { world_map, 800, 800}, - { box_outline, 100, 100}, - { mosaic, 800, 800 }, - { long_lines, 100, 100}, - { unaligned_clip, 100, 100}, - { rectangles, 512, 512}, - { rounded_rectangles, 512, 512}, - { long_dashed_lines, 512, 512}, - { composite_checker, 16, 512}, - { twin, 800, 800}, - { dragon, 1024, 1024 }, - { pythagoras_tree, 768, 768 }, - { intersections, 512, 512 }, - { many_strokes, 32, 512 }, - { wide_strokes, 32, 512 }, - { many_fills, 32, 512 }, - { wide_fills, 32, 512 }, - { many_curves, 32, 512 }, - { spiral, 512, 512 }, - { wave, 500, 500 }, + { FUNC(pixel), 1, 1 }, + { FUNC(paint), 64, 512}, + { FUNC(paint_with_alpha), 64, 512}, + { FUNC(fill), 64, 512}, + { FUNC(stroke), 64, 512}, + { FUNC(text), 64, 512}, + { FUNC(glyphs), 64, 512}, + { FUNC(mask), 64, 512}, + { FUNC(line), 32, 512}, + { FUNC(a1_line), 32, 512}, + { FUNC(curve), 32, 512}, + { FUNC(a1_curve), 32, 512}, + { FUNC(disjoint), 64, 512}, + { FUNC(hatching), 64, 512}, + { FUNC(tessellate), 100, 100}, + { FUNC(subimage_copy), 16, 512}, + { FUNC(hash_table), 16, 16}, + { FUNC(pattern_create_radial), 16, 16}, + { FUNC(zrusin), 415, 415}, + { FUNC(world_map), 800, 800}, + { FUNC(box_outline), 100, 100}, + { FUNC(mosaic), 800, 800 }, + { FUNC(long_lines), 100, 100}, + { FUNC(unaligned_clip), 100, 100}, + { FUNC(rectangles), 512, 512}, + { FUNC(rounded_rectangles), 512, 512}, + { FUNC(long_dashed_lines), 512, 512}, + { FUNC(composite_checker), 16, 512}, + { FUNC(twin), 800, 800}, + { FUNC(dragon), 1024, 1024 }, + { FUNC(sierpinski), 32, 1024 }, + { FUNC(pythagoras_tree), 768, 768 }, + { FUNC(intersections), 512, 512 }, + { FUNC(many_strokes), 32, 512 }, + { FUNC(wide_strokes), 32, 512 }, + { FUNC(many_fills), 32, 512 }, + { FUNC(wide_fills), 32, 512 }, + { FUNC(many_curves), 32, 512 }, + { FUNC(spiral), 512, 512 }, + { FUNC(wave), 500, 500 }, + { FUNC(fill_clip), 16, 512 }, { NULL } }; diff --git a/perf/cairo-perf-report.c b/perf/cairo-perf-report.c index fcce0e035..8df78c647 100644 --- a/perf/cairo-perf-report.c +++ b/perf/cairo-perf-report.c @@ -110,6 +110,7 @@ do { \ static test_report_status_t test_report_parse (test_report_t *report, + int fileno, char *line, char *configuration) { @@ -137,6 +138,7 @@ test_report_parse (test_report_t *report, skip_space (); + report->fileno = fileno; report->configuration = configuration; parse_string (report->backend); end = strrchr (report->backend, '.'); @@ -369,7 +371,7 @@ cairo_perf_report_sort_and_compute_stats (cairo_perf_report_t *report, void cairo_perf_report_load (cairo_perf_report_t *report, - const char *filename, + const char *filename, int id, int (*cmp) (const void *, const void *)) { FILE *file; @@ -401,6 +403,7 @@ cairo_perf_report_load (cairo_perf_report_t *report, report->tests_size = 16; report->tests = xmalloc (report->tests_size * sizeof (test_report_t)); report->tests_count = 0; + report->fileno = id; if (filename == NULL) { file = stdin; @@ -425,7 +428,7 @@ cairo_perf_report_load (cairo_perf_report_t *report, break; status = test_report_parse (&report->tests[report->tests_count], - line, report->configuration); + id, line, report->configuration); if (status == TEST_REPORT_STATUS_ERROR) fprintf (stderr, "Ignoring unrecognized line %d of %s:\n%s", line_number, filename, line); diff --git a/perf/cairo-perf-trace.c b/perf/cairo-perf-trace.c index 2cef2b14c..8e637a7d2 100644 --- a/perf/cairo-perf-trace.c +++ b/perf/cairo-perf-trace.c @@ -79,7 +79,7 @@ basename_no_ext (char *path) name = basename (path); - dot = strchr (name, '.'); + dot = strrchr (name, '.'); if (dot) *dot = '\0'; @@ -108,6 +108,7 @@ struct trace { void *closure; cairo_surface_t *surface; cairo_bool_t observe; + int tile_size; }; cairo_bool_t @@ -132,7 +133,7 @@ cairo_perf_can_run (cairo_perf_t *perf, return TRUE; copy = xstrdup (name); - dot = strchr (copy, '.'); + dot = strrchr (copy, '.'); if (dot != NULL) *dot = '\0'; @@ -435,6 +436,7 @@ parse_options (cairo_perf_t *perf, perf->raw = FALSE; perf->observe = FALSE; perf->list_only = FALSE; + perf->tile_size = 0; perf->names = NULL; perf->num_names = 0; perf->summary = stdout; @@ -443,7 +445,7 @@ parse_options (cairo_perf_t *perf, perf->num_exclude_names = 0; while (1) { - c = _cairo_getopt (argc, argv, "i:x:lsrvc"); + c = _cairo_getopt (argc, argv, "t:i:x:lsrvc"); if (c == -1) break; @@ -457,6 +459,14 @@ parse_options (cairo_perf_t *perf, exit (1); } break; + case 't': + perf->tile_size = strtoul (optarg, &end, 10); + if (*end != '\0') { + fprintf (stderr, "Invalid argument for -t (not an integer): %s\n", + optarg); + exit (1); + } + break; case 'l': perf->list_only = TRUE; break; @@ -489,6 +499,11 @@ parse_options (cairo_perf_t *perf, } } + if (perf->observe && perf->tile_size) { + fprintf (stderr, "Can't mix observer and tiling. Sorry.\n"); + exit (1); + } + if (verbose && perf->summary == NULL) perf->summary = stderr; #if HAVE_UNISTD_H @@ -536,6 +551,79 @@ have_trace_filenames (cairo_perf_t *perf) } static void +_tiling_surface_finish (cairo_surface_t *observer, + cairo_surface_t *target, + void *closure) +{ + struct trace *args = closure; + cairo_surface_t *surface; + cairo_content_t content; + cairo_rectangle_t r; + int width, height; + int x, y, w, h; + + cairo_recording_surface_get_extents (target, &r); + w = r.width; + h = r.height; + + content = cairo_surface_get_content (target); + + for (y = 0; y < h; y += args->tile_size) { + height = args->tile_size; + if (y + height > h) + height = h - y; + + for (x = 0; x < w; x += args->tile_size) { + cairo_t *cr; + + width = args->tile_size; + if (x + width > w) + width = w - x; + + /* XXX to correctly observe the playback we would need + * to replay the target onto the observer directly. + */ + surface = args->target->create_similar (args->surface, + content, width, height); + + cr = cairo_create (surface); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface (cr, target, -x, -y); + cairo_paint (cr); + cairo_destroy (cr); + + cairo_surface_destroy (surface); + } + } +} + +static cairo_surface_t * +_tiling_surface_create (void *closure, + cairo_content_t content, + double width, + double height, + long uid) +{ + cairo_rectangle_t r; + cairo_surface_t *surface, *observer; + + r.x = r.y = 0; + r.width = width; + r.height = height; + + surface = cairo_recording_surface_create (content, &r); + observer = cairo_surface_create_observer (surface, + CAIRO_SURFACE_OBSERVER_NORMAL); + cairo_surface_destroy (surface); + + cairo_surface_observer_add_finish_callback (observer, + _tiling_surface_finish, + closure); + + return observer; +} + +static void cairo_perf_trace (cairo_perf_t *perf, const cairo_boilerplate_target_t *target, const char *trace) @@ -549,7 +637,7 @@ cairo_perf_trace (cairo_perf_t *perf, char *trace_cpy, *name; const cairo_script_interpreter_hooks_t hooks = { &args, - _similar_surface_create, + perf->tile_size ? _tiling_surface_create : _similar_surface_create, NULL, /* surface_destroy */ _context_create, NULL, /* context_destroy */ @@ -557,6 +645,7 @@ cairo_perf_trace (cairo_perf_t *perf, NULL /* copy_page */ }; + args.tile_size = perf->tile_size; args.observe = perf->observe; trace_cpy = xstrdup (trace); @@ -648,26 +737,30 @@ cairo_perf_trace (cairo_perf_t *perf, } cairo_script_interpreter_run (csi, trace); + line_no = cairo_script_interpreter_get_line_number (csi); + + /* Finish before querying timings in case we are using an intermediate + * target and so need to destroy all surfaces before rendering + * commences. + */ + cairo_script_interpreter_finish (csi); if (perf->observe) { cairo_device_t *observer = cairo_surface_get_device (args.surface); - times[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_elapsed (observer)); - paint[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_paint_elapsed (observer)); - mask[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_mask_elapsed (observer)); - stroke[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_stroke_elapsed (observer)); - fill[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_fill_elapsed (observer)); - glyphs[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_glyphs_elapsed (observer)); + times[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_elapsed (observer)); + paint[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_paint_elapsed (observer)); + mask[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_mask_elapsed (observer)); + stroke[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_stroke_elapsed (observer)); + fill[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_fill_elapsed (observer)); + glyphs[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_glyphs_elapsed (observer)); } else { clear_surface (args.surface); /* queue a write to the sync'ed surface */ cairo_perf_timer_stop (); times[i] = cairo_perf_timer_elapsed (); } - cairo_script_interpreter_finish (csi); scache_clear (); - line_no = cairo_script_interpreter_get_line_number (csi); - cairo_surface_destroy (args.surface); if (target->cleanup) @@ -766,28 +859,28 @@ cairo_perf_trace (cairo_perf_t *perf, fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - _cairo_stats_compute (&stats, paint, i+1); + _cairo_stats_compute (&stats, paint, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - _cairo_stats_compute (&stats, mask, i+1); + _cairo_stats_compute (&stats, mask, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - _cairo_stats_compute (&stats, fill, i+1); + _cairo_stats_compute (&stats, fill, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - _cairo_stats_compute (&stats, stroke, i+1); + _cairo_stats_compute (&stats, stroke, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); - _cairo_stats_compute (&stats, glyphs, i+1); + _cairo_stats_compute (&stats, glyphs, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); fprintf (perf->summary, - " %5d\n", i+1); + " %5d\n", i); } else { fprintf (perf->summary, "%#8.3f %#8.3f %#6.2f%% %4d/%d\n", @@ -807,11 +900,6 @@ out: perf->test_number++; free (trace_cpy); - - cairo_debug_reset_static_data (); -#if HAVE_FCFINI - FcFini (); -#endif } static void diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h index 11c03f750..d6a71ccb5 100644 --- a/perf/cairo-perf.h +++ b/perf/cairo-perf.h @@ -83,6 +83,8 @@ typedef struct _cairo_perf { double ms_per_iteration; cairo_bool_t fast_and_sloppy; + unsigned int tile_size; + /* Stuff used internally */ cairo_time_t *times; const cairo_boilerplate_target_t **targets; @@ -121,6 +123,7 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t *perf, typedef struct _test_report { int id; + int fileno; const char *configuration; char *backend; char *content; @@ -149,6 +152,7 @@ typedef struct _test_diff { typedef struct _cairo_perf_report { char *configuration; const char *name; + int fileno; test_report_t *tests; int tests_size; int tests_count; @@ -162,7 +166,7 @@ typedef enum { void cairo_perf_report_load (cairo_perf_report_t *report, - const char *filename, + const char *filename, int id, int (*cmp) (const void *, const void *)); void @@ -177,7 +181,10 @@ int test_report_cmp_name (const void *a, const void *b); -#define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height) +#define CAIRO_PERF_ENABLED_DECL(func) cairo_bool_t (func ## _enabled) (cairo_perf_t *perf) +#define CAIRO_PERF_RUN_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height) + +#define CAIRO_PERF_DECL(func) CAIRO_PERF_RUN_DECL(func); CAIRO_PERF_ENABLED_DECL(func) CAIRO_PERF_DECL (fill); CAIRO_PERF_DECL (paint); @@ -214,6 +221,11 @@ CAIRO_PERF_DECL (many_fills); CAIRO_PERF_DECL (wide_fills); CAIRO_PERF_DECL (many_curves); CAIRO_PERF_DECL (curve); +CAIRO_PERF_DECL (a1_curve); CAIRO_PERF_DECL (line); +CAIRO_PERF_DECL (a1_line); +CAIRO_PERF_DECL (pixel); +CAIRO_PERF_DECL (sierpinski); +CAIRO_PERF_DECL (fill_clip); #endif diff --git a/perf/cairo-stats.c b/perf/cairo-stats.c index e088e198f..c422d6cc6 100644 --- a/perf/cairo-stats.c +++ b/perf/cairo-stats.c @@ -25,16 +25,25 @@ #include "cairo-stats.h" +#include <assert.h> + void _cairo_stats_compute (cairo_stats_t *stats, cairo_time_t *values, int num_values) { - int i; - cairo_time_t sumtime; - double sum, mean, delta, q1, q3, iqr; - double outlier_min, outlier_max; - int min_valid, num_valid; + cairo_time_t sum, mean, delta, q1, q3, iqr; + cairo_time_t outlier_min, outlier_max; + int i, min_valid, num_valid; + + assert (num_values > 0); + + if (num_values == 1) { + stats->min_ticks = stats->median_ticks = values[0]; + stats->std_dev = 0; + stats->iterations = 1; + return; + } /* First, identify any outliers, using the definition of "mild * outliers" from: @@ -48,44 +57,35 @@ _cairo_stats_compute (cairo_stats_t *stats, */ qsort (values, num_values, sizeof (cairo_time_t), _cairo_time_cmp); - q1 = _cairo_time_to_s (values[(1*num_values)/4]); - q3 = _cairo_time_to_s (values[(3*num_values)/4]); + q1 = values[1*num_values/4]; + q3 = values[3*num_values/4]; + /* XXX assumes we have native uint64_t */ iqr = q3 - q1; + outlier_min = q1 - 3 * iqr / 2; + outlier_max = q3 + 3 * iqr / 2; - outlier_min = _cairo_time_from_s (q1 - 1.5 * iqr); - outlier_max = _cairo_time_from_s (q3 + 1.5 * iqr); - - min_valid = 0; - while (min_valid < num_values && - _cairo_time_to_s (values[min_valid]) < outlier_min) - { - min_valid++; - } + for (i = 0; i < num_values && values[i] < outlier_min; i++) + ; + min_valid = i; - i = min_valid; - num_valid = 0; - while (i + num_valid < num_values && - _cairo_time_to_s (values[i+num_valid]) <= outlier_max) - { - num_valid++; - } + for (i = 0; i < num_values && values[i] <= outlier_max; i++) + ; + num_valid = i - min_valid; + assert(num_valid); stats->iterations = num_valid; stats->min_ticks = values[min_valid]; - - sumtime = _cairo_time_from_s (0); - for (i = min_valid; i < min_valid + num_valid; i++) { - sumtime = _cairo_time_add (sumtime, values[i]); - stats->min_ticks = _cairo_time_min (stats->min_ticks, values[i]); - } - - mean = _cairo_time_to_s (sumtime) / num_valid; stats->median_ticks = values[min_valid + num_valid / 2]; - sum = 0.0; + sum = 0; + for (i = min_valid; i < min_valid + num_valid; i++) + sum = _cairo_time_add (sum, values[i]); + mean = sum / num_valid; + + sum = 0; for (i = min_valid; i < min_valid + num_valid; i++) { - delta = _cairo_time_to_s (values[i]) - mean; + delta = values[i] - mean; sum += delta * delta; } diff --git a/perf/micro/Makefile.sources b/perf/micro/Makefile.sources index 0c2bca08a..e72d44ad9 100644 --- a/perf/micro/Makefile.sources +++ b/perf/micro/Makefile.sources @@ -7,6 +7,7 @@ libcairo_perf_micro_sources = \ hatching.c \ hash-table.c \ line.c \ + a1-line.c \ long-lines.c \ mosaic.c \ paint.c \ @@ -35,7 +36,11 @@ libcairo_perf_micro_sources = \ wide-fills.c \ many-curves.c \ curve.c \ + a1-curve.c \ spiral.c \ + pixel.c \ + sierpinski.c \ + fill-clip.c \ $(NULL) libcairo_perf_micro_headers = \ diff --git a/perf/micro/a1-curve.c b/perf/micro/a1-curve.c new file mode 100644 index 000000000..594c46d5c --- /dev/null +++ b/perf/micro/a1-curve.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairo-perf.h" + +static uint32_t state; + +static double +uniform_random (double minval, double maxval) +{ + static uint32_t const poly = 0x9a795537U; + uint32_t n = 32; + while (n-->0) + state = 2*state < state ? (2*state ^ poly) : 2*state; + return minval + state * (maxval - minval) / 4294967296.0; +} + +static cairo_time_t +do_curve_stroke (cairo_t *cr, int width, int height, int loops) +{ + state = 0xc0ffee; + cairo_set_line_width (cr, 2.); + cairo_perf_timer_start (); + + while (loops--) { + double x1 = uniform_random (0, width); + double x2 = uniform_random (0, width); + double x3 = uniform_random (0, width); + double y1 = uniform_random (0, height); + double y2 = uniform_random (0, height); + double y3 = uniform_random (0, height); + cairo_move_to (cr, uniform_random (0, width), uniform_random (0, height)); + cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); + cairo_stroke(cr); + } + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +do_curve_fill (cairo_t *cr, int width, int height, int loops) +{ + state = 0xc0ffee; + cairo_perf_timer_start (); + + while (loops--) { + double x0 = uniform_random (0, width); + double x1 = uniform_random (0, width); + double x2 = uniform_random (0, width); + double x3 = uniform_random (0, width); + double xm = uniform_random (0, width); + double xn = uniform_random (0, width); + double y0 = uniform_random (0, height); + double y1 = uniform_random (0, height); + double y2 = uniform_random (0, height); + double y3 = uniform_random (0, height); + double ym = uniform_random (0, height); + double yn = uniform_random (0, height); + + cairo_move_to (cr, xm, ym); + cairo_curve_to (cr, x1, y1, x2, y2, xn, yn); + cairo_curve_to (cr, x3, y3, x0, y0, xm, ym); + cairo_close_path (cr); + + cairo_fill(cr); + } + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +cairo_bool_t +a1_curve_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "a1-curve", NULL); +} + +void +a1_curve (cairo_perf_t *perf, cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 1., 1., 1.); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + + cairo_perf_run (perf, "a1-curve-stroked", do_curve_stroke, NULL); + cairo_perf_run (perf, "a1-curve-filled", do_curve_fill, NULL); +} diff --git a/perf/micro/a1-line.c b/perf/micro/a1-line.c new file mode 100644 index 000000000..ae8660212 --- /dev/null +++ b/perf/micro/a1-line.c @@ -0,0 +1,223 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairo-perf.h" + +static cairo_time_t +horizontal (cairo_t *cr, int width, int height, int loops) +{ + double h = height/2 + .5; + + cairo_move_to (cr, 0, h); + cairo_line_to (cr, width, h); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +horizontal_hair (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + return horizontal (cr, width, height, loops); +} + +static cairo_time_t +horizontal_wide (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 5.); + return horizontal (cr, width, height, loops); +} + +static cairo_time_t +nearly_horizontal (cairo_t *cr, int width, int height, int loops) +{ + double h = height/2; + + cairo_move_to (cr, 0, h); + cairo_line_to (cr, width, h+1); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +nearly_horizontal_hair (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + return nearly_horizontal (cr, width, height, loops); +} + +static cairo_time_t +nearly_horizontal_wide (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 5.); + return nearly_horizontal (cr, width, height, loops); +} + + +static cairo_time_t +vertical (cairo_t *cr, int width, int height, int loops) +{ + double w = width/2 + .5; + + cairo_move_to (cr, w, 0); + cairo_line_to (cr, w, height); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +vertical_hair (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + return vertical (cr, width, height, loops); +} + +static cairo_time_t +vertical_wide (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 5.); + return vertical (cr, width, height, loops); +} + +static cairo_time_t +nearly_vertical (cairo_t *cr, int width, int height, int loops) +{ + double w = width/2; + + cairo_move_to (cr, w, 0); + cairo_line_to (cr, w+1, height); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +nearly_vertical_hair (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + return nearly_vertical (cr, width, height, loops); +} + +static cairo_time_t +nearly_vertical_wide (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 5.); + return nearly_vertical (cr, width, height, loops); +} + + +static cairo_time_t +diagonal (cairo_t *cr, int width, int height, int loops) +{ + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, width, height); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +diagonal_hair (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + return diagonal (cr, width, height, loops); +} + +static cairo_time_t +diagonal_wide (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 5.); + return diagonal (cr, width, height, loops); +} + +cairo_bool_t +a1_line_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "a1-line", NULL); +} + +void +a1_line (cairo_perf_t *perf, cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 1., 1., 1.); + cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); + + cairo_perf_run (perf, "a1-line-hh", horizontal_hair, NULL); + cairo_perf_run (perf, "a1-line-hw", horizontal_wide, NULL); + cairo_perf_run (perf, "a1-line-nhh", nearly_horizontal_hair, NULL); + cairo_perf_run (perf, "a1-line-nhw", nearly_horizontal_wide, NULL); + + cairo_perf_run (perf, "a1-line-vh", vertical_hair, NULL); + cairo_perf_run (perf, "a1-line-vw", vertical_wide, NULL); + cairo_perf_run (perf, "a1-line-nvh", nearly_vertical_hair, NULL); + cairo_perf_run (perf, "a1-line-nvw", nearly_vertical_wide, NULL); + + cairo_perf_run (perf, "a1-line-dh", diagonal_hair, NULL); + cairo_perf_run (perf, "a1-line-dw", diagonal_wide, NULL); +} diff --git a/perf/micro/box-outline.c b/perf/micro/box-outline.c index a0c47f779..1e654eb95 100644 --- a/perf/micro/box-outline.c +++ b/perf/micro/box-outline.c @@ -65,6 +65,55 @@ box_outline_stroke (cairo_t *cr, int width, int height, int loops) } static cairo_time_t +box_outline_alpha_stroke (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ + cairo_paint (cr); + + cairo_rectangle (cr, + 1.5, 1.5, + width - 3, height - 3); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba (cr, 1, 0, 0, .5); /* red */ + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +box_outline_aa_stroke (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ + cairo_paint (cr); + + cairo_translate (cr, .5, .5); + cairo_rectangle (cr, + 1.5, 1.5, + width - 3, height - 3); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 1, 0, 0); /* red */ + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t box_outline_fill (cairo_t *cr, int width, int height, int loops) { cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ @@ -91,12 +140,76 @@ box_outline_fill (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +static cairo_time_t +box_outline_alpha_fill (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ + cairo_paint (cr); + + cairo_rectangle (cr, + 1.0, 1.0, + width - 2, height - 2); + cairo_rectangle (cr, + 2.0, 2.0, + width - 4, height - 4); + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_source_rgba (cr, 0, 1, 0, .5); /* green */ + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +box_outline_aa_fill (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ + cairo_paint (cr); + + cairo_translate (cr, .5, .5); + cairo_rectangle (cr, + 1.0, 1.0, + width - 2, height - 2); + cairo_rectangle (cr, + 2.0, 2.0, + width - 4, height - 4); + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_source_rgb (cr, 0, 1, 0); /* green */ + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + + return cairo_perf_timer_elapsed (); +} + +cairo_bool_t +box_outline_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "box-outline", NULL); +} + void 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, NULL); cairo_perf_run (perf, "box-outline-fill", box_outline_fill, NULL); + + cairo_perf_run (perf, "box-outline-alpha-stroke", box_outline_alpha_stroke, NULL); + cairo_perf_run (perf, "box-outline-alpha-fill", box_outline_alpha_fill, NULL); + + cairo_perf_run (perf, "box-outline-aa-stroke", box_outline_aa_stroke, NULL); + cairo_perf_run (perf, "box-outline-aa-fill", box_outline_aa_fill, NULL); } diff --git a/perf/micro/composite-checker.c b/perf/micro/composite-checker.c index 0d7af0c87..d6d17ab63 100644 --- a/perf/micro/composite-checker.c +++ b/perf/micro/composite-checker.c @@ -75,6 +75,12 @@ do_composite_checker (cairo_t *cr, return cairo_perf_timer_elapsed (); } +cairo_bool_t +composite_checker_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "composite-checker", NULL); +} + void composite_checker (cairo_perf_t *perf, cairo_t *cr, @@ -83,9 +89,6 @@ composite_checker (cairo_perf_t *perf, { cairo_surface_t *image; - if (! cairo_perf_can_run (perf, "composite-checker", NULL)) - return; - /* Create the checker pattern. We don't actually need to draw * anything on it since that wouldn't affect performance. */ diff --git a/perf/micro/curve.c b/perf/micro/curve.c index 7def326e6..3b5a16342 100644 --- a/perf/micro/curve.c +++ b/perf/micro/curve.c @@ -95,12 +95,15 @@ do_curve_fill (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +curve_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "curve", NULL); +} + void curve (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "curve", NULL)) - return; - cairo_set_source_rgb (cr, 1., 1., 1.); cairo_perf_run (perf, "curve-stroked", do_curve_stroke, NULL); diff --git a/perf/micro/disjoint.c b/perf/micro/disjoint.c index d7f502608..623eb6f48 100644 --- a/perf/micro/disjoint.c +++ b/perf/micro/disjoint.c @@ -85,6 +85,12 @@ draw (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +disjoint_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "disjoint", NULL); +} + void disjoint (cairo_perf_t *perf, cairo_t *cr, int width, int height) { diff --git a/perf/micro/dragon.c b/perf/micro/dragon.c index 5bc8d26f8..e215eaccc 100644 --- a/perf/micro/dragon.c +++ b/perf/micro/dragon.c @@ -265,12 +265,15 @@ do_dragon_solid_circle_clip (cairo_t *cr, int width, int height, int loops) return do_dragon_solid (cr, width, height, loops); } +cairo_bool_t +dragon_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "dragon", NULL); +} + void 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, NULL); cairo_perf_run (perf, "dragon-unaligned-solid", do_dragon_solid_unaligned, NULL); cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip, NULL); diff --git a/perf/micro/fill-clip.c b/perf/micro/fill-clip.c new file mode 100644 index 000000000..2d014aca8 --- /dev/null +++ b/perf/micro/fill-clip.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Chris Wilson <chris@chris-wilson.co.uk> + */ + +/* Compares the overhead for WebKit's drawRect() */ + +#include "cairo-perf.h" + +#include <pixman.h> + +static cairo_time_t +clip_paint (cairo_t *cr, int width, int height, int loops) +{ + int x = width/4, w = width/2; + int y = height/4, h = height/2; + + cairo_perf_timer_start (); + + while (loops--) { + cairo_reset_clip (cr); + cairo_rectangle (cr, x, y, w, h); + cairo_clip (cr); + cairo_paint (cr); + } + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +rect_fill (cairo_t *cr, int width, int height, int loops) +{ + int x = width/4, w = width/2; + int y = height/4, h = height/2; + + cairo_perf_timer_start (); + + while (loops--) { + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + } + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +direct (cairo_t *cr, int width, int height, int loops) +{ + int x = width/4, w = width/2; + int y = height/4, h = height/2; + cairo_surface_t *surface, *image; + uint8_t *data; + int stride, bpp; + + + surface = cairo_get_target (cr); + image = cairo_surface_map_to_image (surface, NULL); + data = cairo_image_surface_get_data (image); + stride = cairo_image_surface_get_stride (image); + + switch (cairo_image_surface_get_format (image)) { + default: + case CAIRO_FORMAT_INVALID: + case CAIRO_FORMAT_A1: bpp = 0; break; + case CAIRO_FORMAT_A8: bpp = 8; break; + case CAIRO_FORMAT_RGB16_565: bpp = 16; break; + case CAIRO_FORMAT_RGB24: + case CAIRO_FORMAT_RGB30: + case CAIRO_FORMAT_ARGB32: bpp = 32; break; + } + + cairo_perf_timer_start (); + + while (loops--) { + pixman_fill ((uint32_t *)data, stride / sizeof(uint32_t), bpp, + x, y, w, h, + -1); + } + + cairo_perf_timer_stop (); + + cairo_surface_unmap_image (surface, image); + + return cairo_perf_timer_elapsed (); +} + +cairo_bool_t +fill_clip_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "fillclip", NULL); +} + +void +fill_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 1., 1., 1.); + + cairo_perf_run (perf, "fillclip-clip", clip_paint, NULL); + cairo_perf_run (perf, "fillclip-fill", rect_fill, NULL); + cairo_perf_run (perf, "fillclip-direct", direct, NULL); +} diff --git a/perf/micro/fill.c b/perf/micro/fill.c index 079522718..d356c26d5 100644 --- a/perf/micro/fill.c +++ b/perf/micro/fill.c @@ -107,12 +107,15 @@ do_fill_eo_noaa (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +fill_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "fill", NULL); +} + void 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, 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 74c67eeeb..5f088b29e 100644 --- a/perf/micro/glyphs.c +++ b/perf/micro/glyphs.c @@ -170,12 +170,15 @@ DECL(48ca, 48, CAIRO_ANTIALIAS_SUBPIXEL) DECL(8mono, 8, CAIRO_ANTIALIAS_NONE) DECL(48mono, 48, CAIRO_ANTIALIAS_NONE) +cairo_bool_t +glyphs_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "glyphs", NULL); +} + 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, "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); diff --git a/perf/micro/hash-table.c b/perf/micro/hash-table.c index a02663813..d16291770 100644 --- a/perf/micro/hash-table.c +++ b/perf/micro/hash-table.c @@ -101,12 +101,15 @@ do_hash_table (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +hash_table_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "hash-table", NULL); +} + void hash_table (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "hash-table", NULL)) - return; - cairo_perf_cover_sources_and_operators (perf, "hash-table", do_hash_table, NULL); } diff --git a/perf/micro/hatching.c b/perf/micro/hatching.c index e31d30101..b51acec5d 100644 --- a/perf/micro/hatching.c +++ b/perf/micro/hatching.c @@ -170,12 +170,15 @@ F(clip_alpha_aligned_mono, clip_alpha, aligned, mono) F(clip_alpha_misaligned_mono, clip_alpha, misaligned, mono) F(clip_alpha_rotated_mono, clip_alpha, rotated, mono) +cairo_bool_t +hatching_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "hatching", NULL); +} + void hatching (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "hatching", NULL)) - return; - cairo_perf_run (perf, "hatching-aligned-aa", draw_aligned_aa, NULL); cairo_perf_run (perf, "hatching-misaligned-aa", draw_misaligned_aa, NULL); cairo_perf_run (perf, "hatching-rotated-aa", draw_rotated_aa, NULL); diff --git a/perf/micro/intersections.c b/perf/micro/intersections.c index 9a81eee85..57931faf8 100644 --- a/perf/micro/intersections.c +++ b/perf/micro/intersections.c @@ -143,12 +143,15 @@ random_curve_nz (cairo_t *cr, int width, int height, int loops) return draw_random_curve (cr, CAIRO_FILL_RULE_WINDING, width, height, loops); } +cairo_bool_t +intersections_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "intersections", NULL); +} + void 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, NULL); cairo_perf_run (perf, "intersections-eo-fill", random_eo, NULL); diff --git a/perf/micro/line.c b/perf/micro/line.c index 7ba9f9048..3ed5f8dac 100644 --- a/perf/micro/line.c +++ b/perf/micro/line.c @@ -196,12 +196,15 @@ diagonal_wide (cairo_t *cr, int width, int height, int loops) return diagonal (cr, width, height, loops); } +cairo_bool_t +line_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "line", NULL); +} + void line (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "line", NULL)) - return; - cairo_set_source_rgb (cr, 1., 1., 1.); cairo_perf_run (perf, "line-hh", horizontal_hair, NULL); diff --git a/perf/micro/long-dashed-lines.c b/perf/micro/long-dashed-lines.c index fa99b2008..ba66a4af4 100644 --- a/perf/micro/long-dashed-lines.c +++ b/perf/micro/long-dashed-lines.c @@ -61,11 +61,14 @@ do_long_dashed_lines (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +long_dashed_lines_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "long-dashed-lines", NULL); +} + void 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, NULL); } diff --git a/perf/micro/long-lines.c b/perf/micro/long-lines.c index b3a945855..a0d134c2d 100644 --- a/perf/micro/long-lines.c +++ b/perf/micro/long-lines.c @@ -132,12 +132,15 @@ long_lines_cropped_once (cairo_t *cr, int width, int height, int loops) return do_long_lines (cr, width, height, loops, LONG_LINES_CROPPED | LONG_LINES_ONCE); } +cairo_bool_t +long_lines_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "long-lines", NULL); +} + void 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, 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); diff --git a/perf/micro/many-curves.c b/perf/micro/many-curves.c index dc7cdf9fe..f985d349a 100644 --- a/perf/micro/many-curves.c +++ b/perf/micro/many-curves.c @@ -118,12 +118,15 @@ do_many_curves_filled (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +many_curves_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "many-curves", NULL); +} + void many_curves (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "many-curves", NULL)) - return; - cairo_set_source_rgb (cr, 1., 1., 1.); cairo_perf_run (perf, "many-curves-hair-stroked", do_many_curves_hair_stroked, NULL); diff --git a/perf/micro/many-fills.c b/perf/micro/many-fills.c index eb56e8b92..9d3fd6435 100644 --- a/perf/micro/many-fills.c +++ b/perf/micro/many-fills.c @@ -170,12 +170,15 @@ do_many_fills (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +many_fills_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "many-fills", NULL); +} + void many_fills (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "many-fills", NULL)) - return; - cairo_perf_run (perf, "many-fills-halign", do_many_fills_ha, NULL); cairo_perf_run (perf, "many-fills-valign", do_many_fills_va, NULL); cairo_perf_run (perf, "many-fills-horizontal", do_many_fills_h, NULL); diff --git a/perf/micro/many-strokes.c b/perf/micro/many-strokes.c index f0339457b..9aeb393de 100644 --- a/perf/micro/many-strokes.c +++ b/perf/micro/many-strokes.c @@ -45,7 +45,7 @@ do_many_strokes_ha (cairo_t *cr, int width, int height, int loops) state = 0xc0ffee; for (count = 0; count < 1000; count++) { - double h = floor (uniform_random (0, height)); + double h = floor (uniform_random (0, height)) + .5; cairo_move_to (cr, floor (uniform_random (0, width)), h); cairo_line_to (cr, ceil (uniform_random (0, width)), h); } @@ -97,7 +97,7 @@ do_many_strokes_va (cairo_t *cr, int width, int height, int loops) state = 0xc0ffee; for (count = 0; count < 1000; count++) { - double v = floor (uniform_random (0, width)); + double v = floor (uniform_random (0, width)) + .5; cairo_move_to (cr, v, floor (uniform_random (0, height))); cairo_line_to (cr, v, ceil (uniform_random (0, height))); } @@ -169,12 +169,15 @@ do_many_strokes (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +many_strokes_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "many-strokes", NULL); +} + void many_strokes (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "many-strokes", NULL)) - return; - cairo_perf_run (perf, "many-strokes-halign", do_many_strokes_ha, NULL); cairo_perf_run (perf, "many-strokes-valign", do_many_strokes_va, NULL); cairo_perf_run (perf, "many-strokes-horizontal", do_many_strokes_h, NULL); diff --git a/perf/micro/mask.c b/perf/micro/mask.c index 79092e855..11a3ba730 100644 --- a/perf/micro/mask.c +++ b/perf/micro/mask.c @@ -272,6 +272,12 @@ do_mask_radial (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +mask_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "mask", NULL); +} + void mask (cairo_perf_t *perf, cairo_t *cr, int width, int height) { diff --git a/perf/micro/mosaic.c b/perf/micro/mosaic.c index d76b84002..ed30ae555 100644 --- a/perf/micro/mosaic.c +++ b/perf/micro/mosaic.c @@ -160,12 +160,15 @@ mosaic_tessellate_curves (cairo_t *cr, int width, int height, int loops) return mosaic_perform (cr, MOSAIC_TESSELLATE | MOSAIC_CURVE_TO, width, height, loops); } +cairo_bool_t +mosaic_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "mosaic", NULL); +} + void 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, NULL); cairo_perf_run (perf, "mosaic-fill-lines", mosaic_fill_lines, NULL); cairo_perf_run (perf, "mosaic-tessellate-curves", mosaic_tessellate_curves, NULL); diff --git a/perf/micro/paint-with-alpha.c b/perf/micro/paint-with-alpha.c index 3c1f69ee6..047e35c43 100644 --- a/perf/micro/paint-with-alpha.c +++ b/perf/micro/paint-with-alpha.c @@ -44,12 +44,15 @@ count_paint_with_alpha (cairo_t *cr, int width, int height) return width * height / 1e6; /* Mpix/s */ } +cairo_bool_t +paint_with_alpha_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "paint-with-alpha", NULL); +} + void paint_with_alpha (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "paint-with-alpha", NULL)) - return; - cairo_perf_cover_sources_and_operators (perf, "paint-with-alpha", do_paint_with_alpha, count_paint_with_alpha); diff --git a/perf/micro/paint.c b/perf/micro/paint.c index dc7e0a0fd..2a59a45e0 100644 --- a/perf/micro/paint.c +++ b/perf/micro/paint.c @@ -44,11 +44,14 @@ count_paint (cairo_t *cr, int width, int height) return width * height / 1e6; /* Mpix/s */ } +cairo_bool_t +paint_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "paint", NULL); +} + void 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, count_paint); } diff --git a/perf/micro/pattern_create_radial.c b/perf/micro/pattern_create_radial.c index 13260bb57..f236ef548 100644 --- a/perf/micro/pattern_create_radial.c +++ b/perf/micro/pattern_create_radial.c @@ -79,14 +79,17 @@ do_pattern_create_radial (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +pattern_create_radial_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "pattern-create-radial", NULL); +} + void pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height) { int i; - if (! cairo_perf_can_run (perf, "pattern-create-radial", NULL)) - return; - srand (time (0)); for (i = 0; i < RADIALS_COUNT; i++) { diff --git a/perf/micro/pixel.c b/perf/micro/pixel.c new file mode 100644 index 000000000..12b8f47b2 --- /dev/null +++ b/perf/micro/pixel.c @@ -0,0 +1,177 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Chris Wilson <chris@chris-wilson.co.uk> + */ + +/* Measure the overhead in setting a single pixel */ + +#include "cairo-perf.h" + +static cairo_time_t +pixel_paint (cairo_t *cr, int width, int height, int loops) +{ + cairo_perf_timer_start (); + + while (loops--) + cairo_paint (cr); + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_mask (cairo_t *cr, int width, int height, int loops) +{ + cairo_surface_t *mask; + cairo_t *cr2; + + mask = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_ALPHA, + 1, 1); + cr2 = cairo_create (mask); + cairo_set_source_rgb (cr2, 1,1,1); + cairo_paint (cr2); + cairo_destroy (cr2); + + cairo_perf_timer_start (); + + while (loops--) + cairo_mask_surface (cr, mask, 0, 0); + + cairo_perf_timer_stop (); + + cairo_surface_destroy (mask); + + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_rectangle (cairo_t *cr, int width, int height, int loops) +{ + cairo_new_path (cr); + cairo_rectangle (cr, 0, 0, 1, 1); + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_subrectangle (cairo_t *cr, int width, int height, int loops) +{ + cairo_new_path (cr); + cairo_rectangle (cr, 0.1, 0.1, .8, .8); + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_triangle (cairo_t *cr, int width, int height, int loops) +{ + cairo_new_path (cr); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, 1, 1); + cairo_line_to (cr, 0, 1); + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_circle (cairo_t *cr, int width, int height, int loops) +{ + cairo_new_path (cr); + cairo_arc (cr, 0.5, 0.5, 0.5, 0, 2 * M_PI); + + cairo_perf_timer_start (); + + while (loops--) + cairo_fill_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + return cairo_perf_timer_elapsed (); +} + +static cairo_time_t +pixel_stroke (cairo_t *cr, int width, int height, int loops) +{ + cairo_set_line_width (cr, 1.); + cairo_new_path (cr); + cairo_move_to (cr, 0, 0.5); + cairo_line_to (cr, 1, 0.5); + + cairo_perf_timer_start (); + + while (loops--) + cairo_stroke_preserve (cr); + + cairo_perf_timer_stop (); + + cairo_new_path (cr); + return cairo_perf_timer_elapsed (); +} + +cairo_bool_t +pixel_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "pixel", NULL); +} + +void +pixel (cairo_perf_t *perf, cairo_t *cr, int width, int height) +{ + cairo_set_source_rgb (cr, 1., 1., 1.); + + cairo_perf_run (perf, "pixel-paint", pixel_paint, NULL); + cairo_perf_run (perf, "pixel-mask", pixel_mask, NULL); + cairo_perf_run (perf, "pixel-rectangle", pixel_rectangle, NULL); + cairo_perf_run (perf, "pixel-subrectangle", pixel_subrectangle, NULL); + cairo_perf_run (perf, "pixel-triangle", pixel_triangle, NULL); + cairo_perf_run (perf, "pixel-circle", pixel_circle, NULL); + cairo_perf_run (perf, "pixel-stroke", pixel_stroke, NULL); +} diff --git a/perf/micro/pythagoras-tree.c b/perf/micro/pythagoras-tree.c index 6e823a8f6..9d3ca1155 100644 --- a/perf/micro/pythagoras-tree.c +++ b/perf/micro/pythagoras-tree.c @@ -82,11 +82,14 @@ do_pythagoras_tree (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +pythagoras_tree_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "pythagoras-tree", NULL); +} + void 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, NULL); } diff --git a/perf/micro/rectangles.c b/perf/micro/rectangles.c index 891572b60..9228a4efa 100644 --- a/perf/micro/rectangles.c +++ b/perf/micro/rectangles.c @@ -95,14 +95,17 @@ do_rectangle (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +rectangles_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "rectangles", NULL); +} + void rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height) { int i; - if (! cairo_perf_can_run (perf, "rectangles", NULL)) - return; - srand (8478232); for (i = 0; i < RECTANGLE_COUNT; i++) { diff --git a/perf/micro/rounded-rectangles.c b/perf/micro/rounded-rectangles.c index 598524925..1e432dd1f 100644 --- a/perf/micro/rounded-rectangles.c +++ b/perf/micro/rounded-rectangles.c @@ -119,14 +119,17 @@ do_rectangles_once (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +rounded_rectangles_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "rounded-rectangles", NULL); +} + void rounded_rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height) { int i; - if (! cairo_perf_can_run (perf, "rounded-rectangles", NULL)) - return; - srand (8478232); for (i = 0; i < RECTANGLE_COUNT; i++) { rects[i].x = rand () % width; diff --git a/perf/micro/sierpinski.c b/perf/micro/sierpinski.c new file mode 100644 index 000000000..c6f5fadc2 --- /dev/null +++ b/perf/micro/sierpinski.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairo-perf.h" + +static const double m_1_sqrt_3 = 0.577359269; + +static void +T (cairo_t *cr, int size) +{ + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, size, 0); + cairo_line_to (cr, size/2, size*m_1_sqrt_3); + + size /= 2; + if (size >= 4) { + T (cr, size); + cairo_save (cr); { + cairo_translate (cr, size, 0); + T (cr, size); + } cairo_restore (cr); + cairo_save (cr); { + cairo_translate (cr, size/2, size*m_1_sqrt_3); + T (cr, size); + } cairo_restore (cr); + } +} + +static cairo_time_t +draw (cairo_t *cr, int width, int height, int loops) +{ + int t_height = height/2; + int t_width = t_height / m_1_sqrt_3; + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_set_line_width (cr, 1.); + + cairo_perf_timer_start (); + + while (loops--) { + cairo_save (cr); + T (cr, t_width); + + cairo_translate (cr, 0, height); + cairo_scale (cr, 1, -1); + + T (cr, t_width); + + cairo_stroke (cr); + cairo_restore (cr); + } + + cairo_perf_timer_stop (); + + return cairo_perf_timer_elapsed (); +} + +cairo_bool_t +sierpinski_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "sierpinski", NULL); +} + +void +sierpinski (cairo_perf_t *perf, cairo_t *cr, int width, int height) +{ + cairo_perf_run (perf, "sierpinski", draw, NULL); +} diff --git a/perf/micro/spiral.c b/perf/micro/spiral.c index 85d058018..87dbcb529 100644 --- a/perf/micro/spiral.c +++ b/perf/micro/spiral.c @@ -326,12 +326,15 @@ draw_spiral_stroke_na (cairo_t *cr, int width, int height, int loops) width, height, loops); } +cairo_bool_t +spiral_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "spiral", NULL); +} + void 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, 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); diff --git a/perf/micro/stroke.c b/perf/micro/stroke.c index 8d7dc5274..4b2954770 100644 --- a/perf/micro/stroke.c +++ b/perf/micro/stroke.c @@ -86,12 +86,15 @@ do_strokes (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +stroke_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "stroke", NULL); +} + void 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, 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 eb04154a1..e749c062f 100644 --- a/perf/micro/subimage_copy.c +++ b/perf/micro/subimage_copy.c @@ -52,15 +52,18 @@ do_subimage_copy (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +subimage_copy_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "subimage-copy", NULL); +} + void subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height) { cairo_surface_t *image; cairo_t *cr2; - if (! cairo_perf_can_run (perf, "subimage-copy", NULL)) - return; - cairo_set_source_rgb (cr, 0, 0, 1); /* blue */ cairo_paint (cr); diff --git a/perf/micro/tessellate.c b/perf/micro/tessellate.c index 38c8b86fd..b6277fe63 100644 --- a/perf/micro/tessellate.c +++ b/perf/micro/tessellate.c @@ -141,12 +141,15 @@ tessellate_256 (cairo_t *cr, int width, int height, int loops) return do_tessellate (cr, 256, loops); } +cairo_bool_t +tessellate_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "tessellate", NULL); +} + void 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, NULL); cairo_perf_run (perf, "tessellate-64", tessellate_64, NULL); cairo_perf_run (perf, "tessellate-256", tessellate_256, NULL); diff --git a/perf/micro/text.c b/perf/micro/text.c index bd2ca7b4c..cdb319936 100644 --- a/perf/micro/text.c +++ b/perf/micro/text.c @@ -56,11 +56,14 @@ do_text (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +text_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "text", NULL); +} + void 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, NULL); } diff --git a/perf/micro/twin.c b/perf/micro/twin.c index cc6f02044..99433bd65 100644 --- a/perf/micro/twin.c +++ b/perf/micro/twin.c @@ -43,14 +43,17 @@ do_twin (cairo_t *cr, return cairo_perf_timer_elapsed (); } +cairo_bool_t +twin_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "twin", NULL); +} + void twin (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "twin", NULL)) - return; - cairo_perf_run (perf, "twin", do_twin, NULL); } diff --git a/perf/micro/unaligned-clip.c b/perf/micro/unaligned-clip.c index d71549cc2..41e327f1e 100644 --- a/perf/micro/unaligned-clip.c +++ b/perf/micro/unaligned-clip.c @@ -60,11 +60,14 @@ do_unaligned_clip (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +unaligned_clip_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "unaligned-clip", NULL); +} + void 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, NULL); } diff --git a/perf/micro/wave.c b/perf/micro/wave.c index 88029f8cb..f6e6f74a3 100644 --- a/perf/micro/wave.c +++ b/perf/micro/wave.c @@ -102,11 +102,14 @@ do_wave (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +wave_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "wave", NULL); +} + void wave (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "wave", NULL)) - return; - cairo_perf_run (perf, "wave", do_wave, NULL); } diff --git a/perf/micro/wide-fills.c b/perf/micro/wide-fills.c index a9beeeb1f..0747e6e67 100644 --- a/perf/micro/wide-fills.c +++ b/perf/micro/wide-fills.c @@ -170,12 +170,15 @@ do_wide_fills (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +wide_fills_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "wide-fills", NULL); +} + void wide_fills (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "wide-fills", NULL)) - return; - cairo_perf_run (perf, "wide-fills-halign", do_wide_fills_ha, NULL); cairo_perf_run (perf, "wide-fills-valign", do_wide_fills_va, NULL); cairo_perf_run (perf, "wide-fills-horizontal", do_wide_fills_h, NULL); diff --git a/perf/micro/wide-strokes.c b/perf/micro/wide-strokes.c index e6c27dabb..141309148 100644 --- a/perf/micro/wide-strokes.c +++ b/perf/micro/wide-strokes.c @@ -169,12 +169,15 @@ do_wide_strokes (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +wide_strokes_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "wide-strokes", NULL); +} + void wide_strokes (cairo_perf_t *perf, cairo_t *cr, int width, int height) { - if (! cairo_perf_can_run (perf, "wide-strokes", NULL)) - return; - cairo_set_source_rgb (cr, 1., 1., 1.); cairo_perf_run (perf, "wide-strokes-halign", do_wide_strokes_ha, NULL); diff --git a/perf/micro/world-map.c b/perf/micro/world-map.c index cb0aeee6b..ff22eebf3 100644 --- a/perf/micro/world-map.c +++ b/perf/micro/world-map.c @@ -134,12 +134,15 @@ do_world_map_both (cairo_t *cr, int width, int height, int loops) return do_world_map (cr, width, height, loops, FILL | STROKE); } +cairo_bool_t +world_map_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "world-map", NULL); +} + void 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-stroke", do_world_map_stroke, NULL); cairo_perf_run (perf, "world-map-fill", do_world_map_fill, NULL); cairo_perf_run (perf, "world-map", do_world_map_both, NULL); diff --git a/perf/micro/zrusin.c b/perf/micro/zrusin.c index c4dccbfa1..7d8b004bf 100644 --- a/perf/micro/zrusin.c +++ b/perf/micro/zrusin.c @@ -84,11 +84,15 @@ zrusin_another_fill (cairo_t *cr, int width, int height, int loops) return cairo_perf_timer_elapsed (); } +cairo_bool_t +zrusin_enabled (cairo_perf_t *perf) +{ + return cairo_perf_can_run (perf, "zrusin", NULL); +} + void 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, NULL); cairo_perf_run (perf, "zrusin-another-fill", zrusin_another_fill, NULL); |