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 b99234b2..1fcf1480 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 16306377..2cbb24c5 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 34311b04..08509271 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 096986bc..f3c6f8d9 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 fcce0e03..8df78c64 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 2cef2b14..8e637a7d 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 11c03f75..d6a71ccb 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 e088e198..c422d6cc 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 0c2bca08..e72d44ad 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 00000000..594c46d5 --- /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 00000000..ae866021 --- /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 a0c47f77..1e654eb9 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 0d7af0c8..d6d17ab6 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 7def326e..3b5a1634 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 d7f50260..623eb6f4 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 5bc8d26f..e215eacc 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 00000000..2d014aca --- /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 07952271..d356c26d 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 74c67eee..5f088b29 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 a0266381..d1629177 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 e31d3010..b51acec5 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 9a81eee8..57931faf 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 7ba9f904..3ed5f8da 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 fa99b200..ba66a4af 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 b3a94585..a0d134c2 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 dc7cdf9f..f985d349 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 eb56e8b9..9d3fd643 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 f0339457..9aeb393d 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 79092e85..11a3ba73 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 d76b8400..ed30ae55 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 3c1f69ee..047e35c4 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 dc7e0a0f..2a59a45e 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 13260bb5..f236ef54 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 00000000..12b8f47b --- /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 6e823a8f..9d3ca115 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 891572b6..9228a4ef 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 59852492..1e432dd1 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 00000000..c6f5fadc --- /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 85d05801..87dbcb52 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 8d7dc527..4b295477 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 eb04154a..e749c062 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 38c8b86f..b6277fe6 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 bd2ca7b4..cdb31993 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 cc6f0204..99433bd6 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 d71549cc..41e327f1 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 88029f8c..f6e6f74a 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 a9beeeb1..0747e6e6 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 e6c27dab..14130914 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 cb0aeee6..ff22eebf 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 c4dccbfa..7d8b004b 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); |