From 0101a545793291d0fe76b765ba8392ade5faa1a1 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Tue, 30 Aug 2011 16:15:28 +0200 Subject: time: Add cairo_time_t type Add the cairo_time_t type (currently based on cairo_uint64_t) and use it in cairo-observer and in the perf suite. Fixes the build on MacOS X (for the src/ subdir) and Win32, whch failed because they don't provide clock_gettime: cairo-surface-observer.c:629: error: implicit declaration of function 'clock_gettime' cairo-surface-observer.c:629: warning: nested extern declaration of 'clock_gettime' cairo-surface-observer.c:629: error: 'CLOCK_MONOTONIC' undeclared (first use in this function) ... --- build/configure.ac.system | 7 +- configure.ac | 2 +- perf/Makefile.am | 1 - src/Makefile.sources | 2 + src/cairo-surface-observer-private.h | 13 ++- src/cairo-surface-observer.c | 169 ++++++++++++--------------- src/cairo-time-private.h | 93 +++++++++++++++ src/cairo-time.c | 215 +++++++++++++++++++++++++++++++++++ src/cairo-wideint-private.h | 12 ++ src/cairo-wideint.c | 16 +++ 10 files changed, 421 insertions(+), 109 deletions(-) create mode 100644 src/cairo-time-private.h create mode 100644 src/cairo-time.c diff --git a/build/configure.ac.system b/build/configure.ac.system index b405740d..10a2dca8 100644 --- a/build/configure.ac.system +++ b/build/configure.ac.system @@ -53,9 +53,7 @@ dnl ==================================================================== AC_CHECK_LIBM LIBS="$LIBS $LIBM" -AC_CHECK_LIB(rt, sched_yield, [RT_LIBS=-lrt], [RT_LIBS=]) -CAIROPERF_LIBS=$RT_LIBS -AC_SUBST(CAIROPERF_LIBS) +AC_CHECK_LIB(rt, sched_yield) has_shm_open= AC_CHECK_LIB(rt, shm_open, [ @@ -102,10 +100,7 @@ dnl check for mmap support AC_CHECK_HEADERS([sys/mman.h], [AC_CHECK_FUNCS([mmap])]) dnl check for clock_gettime() support -save_LIBS="$LIBS" -LIBS="$LIBS $RT_LIBS" AC_CHECK_HEADERS([time.h], [AC_CHECK_FUNCS([clock_gettime])]) -LIBS="$save_LIBS" dnl check for GNU-extensions to fenv AC_CHECK_HEADER(fenv.h, diff --git a/configure.ac b/configure.ac index c7c167e4..71f8bf3a 100644 --- a/configure.ac +++ b/configure.ac @@ -622,7 +622,7 @@ dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(mime, mime, always) CAIRO_ENABLE_SURFACE_BACKEND(recording, recording, always) -CAIRO_ENABLE_SURFACE_BACKEND(observer, observer, always, observer_LIBS=-lrt) +CAIRO_ENABLE_SURFACE_BACKEND(observer, observer, always) CAIRO_ENABLE_SURFACE_BACKEND(tee, tee, no) CAIRO_ENABLE_SURFACE_BACKEND(xml, xml, no, [ use_xml=$have_libz diff --git a/perf/Makefile.am b/perf/Makefile.am index 3ac60da5..4344b98c 100644 --- a/perf/Makefile.am +++ b/perf/Makefile.am @@ -48,7 +48,6 @@ cairo_perf_micro_DEPENDENCIES = \ libcairoperf_la_SOURCES = \ $(libcairoperf_sources) \ $(libcairoperf_headers) -libcairoperf_la_LIBADD = $(CAIROPERF_LIBS) cairo_analyse_trace_SOURCES = \ $(cairo_analyse_trace_sources) \ diff --git a/src/Makefile.sources b/src/Makefile.sources index 8f2d09e2..0b820f8f 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -106,6 +106,7 @@ cairo_private = \ cairo-surface-subsurface-private.h \ cairo-surface-snapshot-private.h \ cairo-surface-wrapper-private.h \ + cairo-time-private.h \ cairo-types-private.h \ cairo-user-font-private.h \ cairo-wideint-private.h \ @@ -192,6 +193,7 @@ cairo_sources = \ cairo-surface-subsurface.c \ cairo-surface-wrapper.c \ cairo-system.c \ + cairo-time.c \ cairo-tor-scan-converter.c \ cairo-toy-font-face.c \ cairo-traps.c \ diff --git a/src/cairo-surface-observer-private.h b/src/cairo-surface-observer-private.h index a846a1c2..61507b21 100644 --- a/src/cairo-surface-observer-private.h +++ b/src/cairo-surface-observer-private.h @@ -41,6 +41,7 @@ #include "cairo-device-private.h" #include "cairo-recording-surface-private.h" #include "cairo-surface-private.h" +#include "cairo-time-private.h" struct stat { double min, max, sum, sum_sq; @@ -89,7 +90,7 @@ struct _cairo_observation_record { double tolerance; int antialias; int clip; - double elapsed; + cairo_time_t elapsed; }; struct _cairo_observation { @@ -100,7 +101,7 @@ struct _cairo_observation { /* XXX put interesting stats here! */ struct paint { - double elapsed; + cairo_time_t elapsed; unsigned int count; struct extents extents; unsigned int operators[NUM_OPERATORS]; @@ -112,7 +113,7 @@ struct _cairo_observation { } paint; struct mask { - double elapsed; + cairo_time_t elapsed; unsigned int count; struct extents extents; unsigned int operators[NUM_OPERATORS]; @@ -125,7 +126,7 @@ struct _cairo_observation { } mask; struct fill { - double elapsed; + cairo_time_t elapsed; unsigned int count; struct extents extents; unsigned int operators[NUM_OPERATORS]; @@ -140,7 +141,7 @@ struct _cairo_observation { } fill; struct stroke { - double elapsed; + cairo_time_t elapsed; unsigned int count; struct extents extents; unsigned int operators[NUM_OPERATORS]; @@ -157,7 +158,7 @@ struct _cairo_observation { } stroke; struct glyphs { - double elapsed; + cairo_time_t elapsed; unsigned int count; struct extents extents; unsigned int operators[NUM_OPERATORS]; diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c index 92f26240..a0dcb2f5 100644 --- a/src/cairo-surface-observer.c +++ b/src/cairo-surface-observer.c @@ -487,7 +487,7 @@ record_paint (cairo_observation_record_t *r, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { record_target (r, target); @@ -512,7 +512,7 @@ record_mask (cairo_observation_record_t *r, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { record_target (r, target); @@ -540,7 +540,7 @@ record_fill (cairo_observation_record_t *r, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { record_target (r, target); @@ -570,7 +570,7 @@ record_stroke (cairo_observation_record_t *r, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { record_target (r, target); @@ -597,7 +597,7 @@ record_glyphs (cairo_observation_record_t *r, int num_glyphs, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { record_target (r, target); @@ -627,25 +627,6 @@ add_record (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } -static void -start_timer (struct timespec *ts) -{ - clock_gettime (CLOCK_MONOTONIC, ts); -} - -static double -stop_timer (const struct timespec *then) -{ - struct timespec now; - double elapsed; - - clock_gettime (CLOCK_MONOTONIC, &now); - - elapsed = now.tv_nsec - then->tv_nsec; - elapsed += 1e9 * (now.tv_sec - then->tv_sec); - return elapsed; -} - static void sync (cairo_surface_t *target, int x, int y) { @@ -674,7 +655,7 @@ add_record_paint (cairo_observation_t *log, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { cairo_observation_record_t record; cairo_int_status_t status; @@ -692,9 +673,9 @@ add_record_paint (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } - if (elapsed > log->paint.slowest.elapsed) + if (_cairo_time_gt (elapsed, log->paint.slowest.elapsed)) log->paint.slowest = record; - log->paint.elapsed += elapsed; + log->paint.elapsed = _cairo_time_add (log->paint.elapsed, elapsed); } static cairo_int_status_t @@ -708,8 +689,7 @@ _cairo_surface_observer_paint (void *abstract_surface, cairo_composite_rectangles_t composite; cairo_rectangle_int_t extents; cairo_int_status_t status; - struct timespec ts; - double elapsed; + cairo_time_t t; int x, y; /* XXX device locking */ @@ -741,7 +721,7 @@ _cairo_surface_observer_paint (void *abstract_surface, add_extents (&device->log.paint.extents, &composite); _cairo_composite_rectangles_fini (&composite); - start_timer (&ts); + t = _cairo_time_get (); status = _cairo_surface_paint (surface->target, op, source, clip); @@ -749,10 +729,10 @@ _cairo_surface_observer_paint (void *abstract_surface, return status; sync (surface->target, x, y); - elapsed = stop_timer (&ts); + t = _cairo_time_get_delta (t); - add_record_paint (&surface->log, surface->target, op, source, clip, elapsed); - add_record_paint (&device->log, surface->target, op, source, clip, elapsed); + add_record_paint (&surface->log, surface->target, op, source, clip, t); + add_record_paint (&device->log, surface->target, op, source, clip, t); return CAIRO_STATUS_SUCCESS; } @@ -764,7 +744,7 @@ add_record_mask (cairo_observation_t *log, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { cairo_observation_record_t record; cairo_int_status_t status; @@ -778,9 +758,9 @@ add_record_mask (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } - if (elapsed > log->mask.slowest.elapsed) + if (_cairo_time_gt (elapsed, log->mask.slowest.elapsed)) log->mask.slowest = record; - log->mask.elapsed += elapsed; + log->mask.elapsed = _cairo_time_add (log->mask.elapsed, elapsed); } static cairo_int_status_t @@ -795,8 +775,7 @@ _cairo_surface_observer_mask (void *abstract_surface, cairo_composite_rectangles_t composite; cairo_rectangle_int_t extents; cairo_int_status_t status; - struct timespec ts; - double elapsed; + cairo_time_t t; int x, y; surface->log.mask.count++; @@ -828,7 +807,7 @@ _cairo_surface_observer_mask (void *abstract_surface, add_extents (&device->log.mask.extents, &composite); _cairo_composite_rectangles_fini (&composite); - start_timer (&ts); + t = _cairo_time_get (); status = _cairo_surface_mask (surface->target, op, source, mask, clip); @@ -836,14 +815,14 @@ _cairo_surface_observer_mask (void *abstract_surface, return status; sync (surface->target, x, y); - elapsed = stop_timer (&ts); + t = _cairo_time_get_delta (t); add_record_mask (&surface->log, surface->target, op, source, mask, clip, - elapsed); + t); add_record_mask (&device->log, surface->target, op, source, mask, clip, - elapsed); + t); return CAIRO_STATUS_SUCCESS; } @@ -858,7 +837,7 @@ add_record_fill (cairo_observation_t *log, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { cairo_observation_record_t record; cairo_int_status_t status; @@ -878,9 +857,9 @@ add_record_fill (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } - if (elapsed > log->fill.slowest.elapsed) + if (_cairo_time_gt (elapsed, log->fill.slowest.elapsed)) log->fill.slowest = record; - log->fill.elapsed += elapsed; + log->fill.elapsed = _cairo_time_add (log->fill.elapsed, elapsed); } static cairo_int_status_t @@ -898,8 +877,7 @@ _cairo_surface_observer_fill (void *abstract_surface, cairo_composite_rectangles_t composite; cairo_rectangle_int_t extents; cairo_int_status_t status; - struct timespec ts; - double elapsed; + cairo_time_t t; int x, y; surface->log.fill.count++; @@ -935,7 +913,7 @@ _cairo_surface_observer_fill (void *abstract_surface, add_extents (&device->log.fill.extents, &composite); _cairo_composite_rectangles_fini (&composite); - start_timer (&ts); + t = _cairo_time_get (); status = _cairo_surface_fill (surface->target, op, source, path, fill_rule, tolerance, antialias, @@ -944,17 +922,17 @@ _cairo_surface_observer_fill (void *abstract_surface, return status; sync (surface->target, x, y); - elapsed = stop_timer (&ts); + t = _cairo_time_get_delta (t); add_record_fill (&surface->log, surface->target, op, source, path, fill_rule, tolerance, antialias, - clip, elapsed); + clip, t); add_record_fill (&device->log, surface->target, op, source, path, fill_rule, tolerance, antialias, - clip, elapsed); + clip, t); return CAIRO_STATUS_SUCCESS; } @@ -971,7 +949,7 @@ add_record_stroke (cairo_observation_t *log, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { cairo_observation_record_t record; cairo_int_status_t status; @@ -992,9 +970,9 @@ add_record_stroke (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } - if (elapsed > log->stroke.slowest.elapsed) + if (_cairo_time_gt (elapsed, log->stroke.slowest.elapsed)) log->stroke.slowest = record; - log->stroke.elapsed += elapsed; + log->stroke.elapsed = _cairo_time_add (log->stroke.elapsed, elapsed); } static cairo_int_status_t @@ -1014,8 +992,7 @@ _cairo_surface_observer_stroke (void *abstract_surface, cairo_composite_rectangles_t composite; cairo_rectangle_int_t extents; cairo_int_status_t status; - struct timespec ts; - double elapsed; + cairo_time_t t; int x, y; surface->log.stroke.count++; @@ -1054,7 +1031,7 @@ _cairo_surface_observer_stroke (void *abstract_surface, add_extents (&device->log.stroke.extents, &composite); _cairo_composite_rectangles_fini (&composite); - start_timer (&ts); + t = _cairo_time_get (); status = _cairo_surface_stroke (surface->target, op, source, path, style, ctm, ctm_inverse, @@ -1064,19 +1041,19 @@ _cairo_surface_observer_stroke (void *abstract_surface, return status; sync (surface->target, x, y); - elapsed = stop_timer (&ts); + t = _cairo_time_get_delta (t); add_record_stroke (&surface->log, surface->target, op, source, path, style, ctm,ctm_inverse, tolerance, antialias, - clip, elapsed); + clip, t); add_record_stroke (&device->log, surface->target, op, source, path, style, ctm,ctm_inverse, tolerance, antialias, - clip, elapsed); + clip, t); return CAIRO_STATUS_SUCCESS; } @@ -1090,7 +1067,7 @@ add_record_glyphs (cairo_observation_t *log, int num_glyphs, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip, - double elapsed) + cairo_time_t elapsed) { cairo_observation_record_t record; cairo_int_status_t status; @@ -1112,9 +1089,9 @@ add_record_glyphs (cairo_observation_t *log, assert (status == CAIRO_INT_STATUS_SUCCESS); } - if (elapsed > log->glyphs.slowest.elapsed) + if (_cairo_time_gt (elapsed, log->glyphs.slowest.elapsed)) log->glyphs.slowest = record; - log->glyphs.elapsed += elapsed; + log->glyphs.elapsed = _cairo_time_add (log->glyphs.elapsed, elapsed); } static cairo_int_status_t @@ -1133,8 +1110,7 @@ _cairo_surface_observer_glyphs (void *abstract_surface, cairo_rectangle_int_t extents; cairo_int_status_t status; cairo_glyph_t *dev_glyphs; - struct timespec ts; - double elapsed; + cairo_time_t t; int x, y; surface->log.glyphs.count++; @@ -1175,7 +1151,7 @@ _cairo_surface_observer_glyphs (void *abstract_surface, memcpy (dev_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t)); *remaining_glyphs = 0; - start_timer (&ts); + t = _cairo_time_get (); status = _cairo_surface_show_text_glyphs (surface->target, op, source, NULL, 0, dev_glyphs, num_glyphs, @@ -1187,17 +1163,17 @@ _cairo_surface_observer_glyphs (void *abstract_surface, return status; sync (surface->target, x, y); - elapsed = stop_timer (&ts); + t = _cairo_time_get_delta (t); add_record_glyphs (&surface->log, surface->target, op, source, glyphs, num_glyphs, scaled_font, - clip, elapsed); + clip, t); add_record_glyphs (&device->log, surface->target, op, source, glyphs, num_glyphs, scaled_font, - clip, elapsed); + clip, t); return CAIRO_STATUS_SUCCESS; } @@ -1620,13 +1596,14 @@ print_record (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, " antialias: %s\n", antialias_names[r->antialias]); _cairo_output_stream_printf (stream, " clip: %s\n", clip_names[r->clip]); - _cairo_output_stream_printf (stream, " elapsed: %f ns\n", r->elapsed); + _cairo_output_stream_printf (stream, " elapsed: %f ns\n", + _cairo_time_to_ns (r->elapsed)); } -static double percent (double a, double b) +static double percent (cairo_time_t a, cairo_time_t b) { /* Fake %.1f */ - return round (a*1000 / b) / 10; + return round (_cairo_time_to_s (a) * 1000 / _cairo_time_to_s (b)) / 10; } static cairo_bool_t @@ -1653,15 +1630,17 @@ replay_record (cairo_observation_t *log, return TRUE; } -static double -_cairo_observation_total_elapsed_ns (cairo_observation_t *log) +static cairo_time_t +_cairo_observation_total_elapsed (cairo_observation_t *log) { - double total = 0; - total += log->paint.elapsed; - total += log->mask.elapsed; - total += log->fill.elapsed; - total += log->stroke.elapsed; - total += log->glyphs.elapsed; + cairo_time_t total; + + total = log->paint.elapsed; + total = _cairo_time_add (total, log->mask.elapsed); + total = _cairo_time_add (total, log->fill.elapsed); + total = _cairo_time_add (total, log->stroke.elapsed); + total = _cairo_time_add (total, log->glyphs.elapsed); + return total; } @@ -1670,15 +1649,15 @@ _cairo_observation_print (cairo_output_stream_t *stream, cairo_observation_t *log) { cairo_device_t *script; - double total; + cairo_time_t total; script = _cairo_script_context_create_internal (stream); _cairo_script_context_attach_snapshots (script, FALSE); - total = _cairo_observation_total_elapsed_ns (log); + total = _cairo_observation_total_elapsed (log); _cairo_output_stream_printf (stream, "elapsed: %f\n", - total); + _cairo_time_to_ns (total)); _cairo_output_stream_printf (stream, "surfaces: %d\n", log->num_surfaces); _cairo_output_stream_printf (stream, "contexts: %d\n", @@ -1689,7 +1668,7 @@ _cairo_observation_print (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, "paint: count %d [no-op %d], elapsed %f [%f%%]\n", log->paint.count, log->paint.noop, - log->paint.elapsed, + _cairo_time_to_ns (log->paint.elapsed), percent (log->paint.elapsed, total)); if (log->paint.count) { print_extents (stream, &log->paint.extents); @@ -1709,7 +1688,7 @@ _cairo_observation_print (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, "mask: count %d [no-op %d], elapsed %f [%f%%]\n", log->mask.count, log->mask.noop, - log->mask.elapsed, + _cairo_time_to_ns (log->mask.elapsed), percent (log->mask.elapsed, total)); if (log->mask.count) { print_extents (stream, &log->mask.extents); @@ -1730,7 +1709,7 @@ _cairo_observation_print (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, "fill: count %d [no-op %d], elaspsed %f [%f%%]\n", log->fill.count, log->fill.noop, - log->fill.elapsed, + _cairo_time_to_ns (log->fill.elapsed), percent (log->fill.elapsed, total)); if (log->fill.count) { print_extents (stream, &log->fill.extents); @@ -1753,7 +1732,7 @@ _cairo_observation_print (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, "stroke: count %d [no-op %d], elapsed %f [%f%%]\n", log->stroke.count, log->stroke.noop, - log->stroke.elapsed, + _cairo_time_to_ns (log->stroke.elapsed), percent (log->stroke.elapsed, total)); if (log->stroke.count) { print_extents (stream, &log->stroke.extents); @@ -1777,7 +1756,7 @@ _cairo_observation_print (cairo_output_stream_t *stream, _cairo_output_stream_printf (stream, "glyphs: count %d [no-op %d], elasped %f [%f%%]\n", log->glyphs.count, log->glyphs.noop, - log->glyphs.elapsed, + _cairo_time_to_ns (log->glyphs.elapsed), percent (log->glyphs.elapsed, total)); if (log->glyphs.count) { print_extents (stream, &log->glyphs.extents); @@ -1831,7 +1810,7 @@ cairo_surface_observer_elapsed (cairo_surface_t *abstract_surface) return -1; surface = (cairo_surface_observer_t *) abstract_surface; - return _cairo_observation_total_elapsed_ns (&surface->log); + return _cairo_time_to_ns (_cairo_observation_total_elapsed (&surface->log)); } void @@ -1867,7 +1846,7 @@ cairo_device_observer_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return _cairo_observation_total_elapsed_ns (&device->log); + return _cairo_time_to_ns (_cairo_observation_total_elapsed (&device->log)); } double @@ -1882,7 +1861,7 @@ cairo_device_observer_paint_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return device->log.paint.elapsed; + return _cairo_time_to_ns (device->log.paint.elapsed); } double @@ -1897,7 +1876,7 @@ cairo_device_observer_mask_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return device->log.mask.elapsed; + return _cairo_time_to_ns (device->log.mask.elapsed); } double @@ -1912,7 +1891,7 @@ cairo_device_observer_fill_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return device->log.fill.elapsed; + return _cairo_time_to_ns (device->log.fill.elapsed); } double @@ -1927,7 +1906,7 @@ cairo_device_observer_stroke_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return device->log.stroke.elapsed; + return _cairo_time_to_ns (device->log.stroke.elapsed); } double @@ -1942,5 +1921,5 @@ cairo_device_observer_glyphs_elapsed (cairo_device_t *abstract_device) return -1; device = (cairo_device_observer_t *) abstract_device; - return device->log.glyphs.elapsed; + return _cairo_time_to_ns (device->log.glyphs.elapsed); } diff --git a/src/cairo-time-private.h b/src/cairo-time-private.h new file mode 100644 index 00000000..f7c48f38 --- /dev/null +++ b/src/cairo-time-private.h @@ -0,0 +1,93 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright (C) 2011 Andrea Canciani + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Authors: Andrea Canciani + * + */ + +#ifndef CAIRO_TIME_PRIVATE_H +#define CAIRO_TIME_PRIVATE_H + +#include "cairo-compiler-private.h" +#include "cairo-wideint-private.h" + +typedef cairo_uint64_t cairo_time_t; + +#define _cairo_time_add _cairo_uint64_add +#define _cairo_time_sub _cairo_uint64_sub +#define _cairo_time_gt _cairo_uint64_gt +#define _cairo_time_lt _cairo_uint64_lt + +#define _cairo_time_to_double _cairo_uint64_to_double +#define _cairo_time_from_double _cairo_double_to_uint64 + +cairo_private int +_cairo_time_cmp (const void *a, + const void *b); + +cairo_private double +_cairo_time_to_s (cairo_time_t t); + +cairo_private cairo_time_t +_cairo_time_from_s (double t); + +cairo_private cairo_time_t +_cairo_time_get (void); + +static cairo_always_inline cairo_time_t +_cairo_time_get_delta (cairo_time_t t) +{ + cairo_time_t now; + + now = _cairo_time_get (); + + return _cairo_time_sub (now, t); +} + +static cairo_always_inline double +_cairo_time_to_ns (cairo_time_t t) +{ + return 1.e9 * _cairo_time_to_s (t); +} + +static cairo_always_inline cairo_time_t +_cairo_time_max (cairo_time_t a, cairo_time_t b) +{ + if (_cairo_uint64_gt (a, b)) + return a; + else + return b; +} + +static cairo_always_inline cairo_time_t +_cairo_time_min (cairo_time_t a, cairo_time_t b) +{ + if (_cairo_uint64_lt (a, b)) + return a; + else + return b; +} + +#endif diff --git a/src/cairo-time.c b/src/cairo-time.c new file mode 100644 index 00000000..32749f5f --- /dev/null +++ b/src/cairo-time.c @@ -0,0 +1,215 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright (c) 2007 Netlabs + * Copyright (c) 2006 Mozilla Corporation + * Copyright (c) 2006 Red Hat, Inc. + * Copyright (c) 2011 Andrea Canciani + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of + * the authors not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. The authors make no representations about the + * suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Peter Weilbacher + * Vladimir Vukicevic + * Carl Worth + * Andrea Canciani + */ + +#include "cairoint.h" + +#include "cairo-time-private.h" + +#if HAVE_CLOCKGETTIME +#if defined(CLOCK_MONOTONIC_RAW) +#define CAIRO_CLOCK CLOCK_MONOTONIC_RAW +#elif defined(CLOCK_MONOTONIC) +#define CAIRO_CLOCK CLOCK_MONOTONIC +#endif +#endif + +#if defined(__APPLE__) +#include + +static cairo_always_inline double +_cairo_time_1s (void) +{ + mach_timebase_info_data_t freq; + + mach_timebase_info (&freq); + + return 1000000000. * freq.denom / freq.numer; +} + +cairo_time_t +_cairo_time_get (void) +{ + return mach_absolute_time (); +} + +#elif defined(__OS2__) +#define INCL_BASE +#include + +static cairo_always_inline double +_cairo_time_1s (void) +{ + ULONG freq; + + DosTmrQueryFreq (&freq); + + return freq; +} + +cairo_time_t +_cairo_time_get (void) +{ + QWORD t; + cairo_uint64_t r; + + DosTmrQueryTime (&t); + + r = _cairo_uint64_lsl (_cairo_uint32_to_uint64 (t.ulHi), 32); + r = _cairo_uint64_add (r, _cairo_uint32_to_uint64 (t.ulLo)); + + return r; +} + +#elif _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +static cairo_always_inline double +_cairo_time_1s (void) +{ + LARGE_INTEGER freq; + + QueryPerformanceFrequency (&freq); + + return freq.QuadPart; +} + +cairo_time_t +_cairo_time_get (void) +{ + LARGE_INTEGER t; + + QueryPerformanceCounter (&t); + + return t.QuadPart; +} + +#elif defined(CAIRO_CLOCK) +#include + +static cairo_always_inline double +_cairo_time_1s (void) +{ + return 1000000000; +} + +cairo_time_t +_cairo_time_get (void) +{ + struct timespec t; + cairo_time_t r; + + clock_gettime (CAIRO_CLOCK, &t); + + r = _cairo_double_to_uint64 (_cairo_time_1s ()); + r = _cairo_uint64_mul (r, _cairo_uint32_to_uint64 (t.tv_sec)); + r = _cairo_uint64_add (r, _cairo_uint32_to_uint64 (t.tv_nsec)); + + return r; +} + +#else +#include + +static cairo_always_inline double +_cairo_time_1s (void) +{ + return 1000000; +} + +cairo_time_t +_cairo_time_get (void) +{ + struct timeval t; + cairo_time_t r; + + gettimeofday (&t, NULL); + + r = _cairo_double_to_uint64 (_cairo_time_1s ()); + r = _cairo_uint64_mul (r, _cairo_uint32_to_uint64 (t.tv_sec)); + r = _cairo_uint64_add (r, _cairo_uint32_to_uint64 (t.tv_usec)); + + return r; +} + +#endif + +int +_cairo_time_cmp (const void *a, + const void *b) +{ + const cairo_time_t *ta, *tb; + + ta = a; + tb = b; + + if (_cairo_time_gt (*ta, *tb)) + return 1; + else if (_cairo_time_lt (*ta, *tb)) + return -1; + else + return 0; +} + +static double +_cairo_time_ticks_per_sec (void) +{ + static double ticks = 0; + + if (unlikely (ticks == 0)) + ticks = _cairo_time_1s (); + + return ticks; +} + +static double +_cairo_time_s_per_tick (void) +{ + static double s = 0; + + if (unlikely (s == 0)) + s = 1. / _cairo_time_ticks_per_sec (); + + return s; +} + +double +_cairo_time_to_s (cairo_time_t t) +{ + return _cairo_uint64_to_double (t) * _cairo_time_s_per_tick (); +} + +cairo_time_t +_cairo_time_from_s (double t) +{ + return _cairo_double_to_uint64 (t * _cairo_time_ticks_per_sec ()); +} diff --git a/src/cairo-wideint-private.h b/src/cairo-wideint-private.h index b9f8dae6..53d2546e 100644 --- a/src/cairo-wideint-private.h +++ b/src/cairo-wideint-private.h @@ -54,6 +54,8 @@ cairo_uquorem64_t I _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den); +cairo_uint64_t I _cairo_double_to_uint64 (double i); +double I _cairo_uint64_to_double (uint64_t i); cairo_uint64_t I _cairo_uint32_to_uint64 (uint32_t i); #define _cairo_uint64_to_uint32(a) ((a).lo) cairo_uint64_t I _cairo_uint64_add (cairo_uint64_t a, cairo_uint64_t b); @@ -103,6 +105,16 @@ _cairo_uint64_divrem (cairo_uint64_t num, cairo_uint64_t den) return qr; } +/* + * These need to be functions or gcc will complain when used on the + * result of a function: + * + * warning: cast from function call of type ‘#cairo_uint64_t’ to + * non-matching type ‘double’ + */ +static cairo_always_inline cairo_uint64_t I _cairo_double_to_uint64 (double i) { return i; } +static cairo_always_inline double I _cairo_uint64_to_double (cairo_uint64_t i) { return i; } + #define _cairo_uint32_to_uint64(i) ((uint64_t) (i)) #define _cairo_uint64_to_uint32(i) ((uint32_t) (i)) #define _cairo_uint64_add(a,b) ((a) + (b)) diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c index 78dedcdf..b6e22808 100644 --- a/src/cairo-wideint.c +++ b/src/cairo-wideint.c @@ -83,6 +83,22 @@ uint64_shift32 (cairo_uint64_t i) static const cairo_uint64_t uint64_carry32 = { 0, 1 }; +cairo_uint64_t +_cairo_double_to_uint64 (double i) +{ + cairo_uint64_t q; + + q.hi = i * (1. / 4294967296.); + q.lo = i - q.hi * 4294967296.; + return q; +} + +double +_cairo_uint64_to_double (cairo_uint64_t i) +{ + return i.hi * 4294967296. + i.lo; +} + cairo_uint64_t _cairo_uint32_to_uint64 (uint32_t i) { -- cgit v1.2.3