macos: support ARM/PowerPC time conversion for DisplayLink times

When converting DisplayLink frame presentation times, we need to take into
account the arch-specific types. This tracks changes in GNOME/GLib!1566 so
that precision is not lost.
This commit is contained in:
Christian Hergert
2020-07-27 12:49:57 -07:00
parent c6c9ca6009
commit 0243736003
2 changed files with 42 additions and 43 deletions

View File

@@ -28,7 +28,7 @@
#include "gdkmacoseventsource-private.h"
static gint64 host_to_frame_clock_time (gint64 host_time);
static gint64 host_to_frame_clock_time (gint64 val);
static gboolean
gdk_display_link_source_prepare (GSource *source,
@@ -203,52 +203,40 @@ gdk_display_link_source_new (void)
}
static gint64
host_to_frame_clock_time (gint64 host_time)
host_to_frame_clock_time (gint64 val)
{
static mach_timebase_info_data_t timebase_info;
/* NOTE: Code adapted from GLib's g_get_monotonic_time(). */
/*
* NOTE:
*
* This code is taken from GLib to match g_get_monotonic_time().
*/
if (G_UNLIKELY (timebase_info.denom == 0))
mach_timebase_info_data_t timebase_info;
/* we get nanoseconds from mach_absolute_time() using timebase_info */
mach_timebase_info (&timebase_info);
if (timebase_info.numer != timebase_info.denom)
{
/* This is a fraction that we must use to scale
* mach_absolute_time() by in order to reach nanoseconds.
*
* We've only ever observed this to be 1/1, but maybe it could be
* 1000/1 if mach time is microseconds already, or 1/1000 if
* picoseconds. Try to deal nicely with that.
*/
mach_timebase_info (&timebase_info);
#ifdef HAVE_UINT128_T
val = ((__uint128_t) val * (__uint128_t) timebase_info.numer) / timebase_info.denom / 1000;
#else
guint64 t_high, t_low;
guint64 result_high, result_low;
/* We actually want microseconds... */
if (timebase_info.numer % 1000 == 0)
timebase_info.numer /= 1000;
else
timebase_info.denom *= 1000;
/* We want to make the numer 1 to avoid having to multiply... */
if (timebase_info.denom % timebase_info.numer == 0)
{
timebase_info.denom /= timebase_info.numer;
timebase_info.numer = 1;
}
else
{
/* We could just multiply by timebase_info.numer below, but why
* bother for a case that may never actually exist...
*
* Plus -- performing the multiplication would risk integer
* overflow. If we ever actually end up in this situation, we
* should more carefully evaluate the correct course of action.
*/
mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */
g_error ("Got weird mach timebase info of %d/%d. Please file a bug against GLib.",
timebase_info.numer, timebase_info.denom);
}
/* 64 bit x 32 bit / 32 bit with 96-bit intermediate
* algorithm lifted from qemu */
t_low = (val & 0xffffffffLL) * (guint64) timebase_info.numer;
t_high = (val >> 32) * (guint64) timebase_info.numer;
t_high += (t_low >> 32);
result_high = t_high / (guint64) timebase_info.denom;
result_low = (((t_high % (guint64) timebase_info.denom) << 32) +
(t_low & 0xffffffff)) /
(guint64) timebase_info.denom;
val = ((result_high << 32) | result_low) / 1000;
#endif
}
else
{
/* nanoseconds to microseconds */
val = val / 1000;
}
return host_time / timebase_info.denom;
return val;
}

View File

@@ -207,6 +207,17 @@ foreach func : check_functions
endif
endforeach
# Check for __uint128_t (gcc) by checking for 128-bit division
uint128_t_src = '''int main() {
static __uint128_t v1 = 100;
static __uint128_t v2 = 10;
static __uint128_t u;
u = v1 / v2;
}'''
if cc.compiles(uint128_t_src, name : '__uint128_t available')
cdata.set('HAVE_UINT128_T', 1)
endif
# Disable deprecation checks for all libraries we depend on on stable branches.
# This is so newer versions of those libraries don't cause more warnings with
# a stable GTK version.