mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-06 07:06:10 +00:00
u/time: Use a very large hammer to "fix" time_state
This commit is contained in:
parent
18fbd3f819
commit
ef41cf2088
|
@ -7,61 +7,41 @@
|
|||
* @ingroup aux_util
|
||||
*/
|
||||
|
||||
#include "u_time.h"
|
||||
#include "xrt/xrt_config_os.h"
|
||||
#include "xrt/xrt_compiler.h"
|
||||
|
||||
#include <chrono>
|
||||
#include "os/os_time.h"
|
||||
|
||||
#include "u_time.h"
|
||||
|
||||
#include <new>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef XRT_OS_LINUX
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
struct MatchingTimePoints
|
||||
{
|
||||
MatchingTimePoints()
|
||||
{
|
||||
#ifdef XRT_OS_LINUX
|
||||
clock_gettime(CLOCK_MONOTONIC, &clock_monotonic);
|
||||
#endif
|
||||
}
|
||||
system_clock::time_point sys = system_clock::now();
|
||||
steady_clock::time_point steady = steady_clock::now();
|
||||
// high_resolution_clock::time_point highRes;
|
||||
|
||||
#ifdef XRT_OS_LINUX
|
||||
struct timespec clock_monotonic;
|
||||
#endif
|
||||
|
||||
timepoint_ns
|
||||
getTimestamp(time_state const &prevState);
|
||||
};
|
||||
/*
|
||||
*
|
||||
* Structs.
|
||||
*
|
||||
*/
|
||||
|
||||
struct time_state
|
||||
{
|
||||
MatchingTimePoints lastTimePoints = {};
|
||||
timepoint_ns lastTime = {};
|
||||
// Hardcoded to one second offset.
|
||||
timepoint_ns offset = 1000 * 1000 * 1000;
|
||||
};
|
||||
|
||||
timepoint_ns
|
||||
MatchingTimePoints::getTimestamp(time_state const &prevState)
|
||||
{
|
||||
//! @todo right now just doing steady clock for simplicity.
|
||||
//! @todo Eventually need to make the high-res clock steady.
|
||||
auto elapsed = steady - prevState.lastTimePoints.steady;
|
||||
return prevState.lastTime + duration_cast<nanoseconds>(elapsed).count();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions.
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" struct time_state *
|
||||
time_state_create()
|
||||
{
|
||||
|
||||
time_state *state = new (std::nothrow) time_state;
|
||||
return state;
|
||||
}
|
||||
|
@ -83,24 +63,16 @@ extern "C" timepoint_ns
|
|||
time_state_get_now(struct time_state const *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
auto now = MatchingTimePoints();
|
||||
|
||||
return now.getTimestamp(*state);
|
||||
return time_state_monotonic_to_ts_ns(state, os_monotonic_get_ns());
|
||||
}
|
||||
|
||||
extern "C" timepoint_ns
|
||||
time_state_get_now_and_update(struct time_state *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
auto now = MatchingTimePoints();
|
||||
|
||||
auto timestamp = now.getTimestamp(*state);
|
||||
|
||||
// Update the state
|
||||
state->lastTimePoints = now;
|
||||
state->lastTime = timestamp;
|
||||
|
||||
return timestamp;
|
||||
return time_state_get_now(state);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
|
@ -110,60 +82,39 @@ time_state_to_timespec(struct time_state const *state,
|
|||
{
|
||||
assert(state != NULL);
|
||||
assert(out != NULL);
|
||||
// Subject to some jitter, roughly up to the magnitude of the actual
|
||||
// resolution difference between the used time source and the system
|
||||
// clock, as well as the non-simultaneity of the calls in
|
||||
// MatchingTimePoints::getNow()
|
||||
auto sinceLastUpdate = nanoseconds{timestamp - state->lastTime};
|
||||
auto equivSystemTimepoint = state->lastTimePoints.sys + sinceLastUpdate;
|
||||
|
||||
// System clock epoch is same as unix epoch for all known
|
||||
// implementations, but not strictly standard-required yet, see
|
||||
// wg21.link/p0355
|
||||
auto sinceEpoch = equivSystemTimepoint.time_since_epoch();
|
||||
auto secondsSinceEpoch = duration_cast<seconds>(sinceEpoch);
|
||||
sinceEpoch -= secondsSinceEpoch;
|
||||
out->tv_sec = secondsSinceEpoch.count();
|
||||
out->tv_nsec = duration_cast<nanoseconds>(sinceEpoch).count();
|
||||
uint64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
|
||||
|
||||
out->tv_sec = ns / (1000 * 1000 * 1000);
|
||||
out->tv_nsec = ns % (1000 * 1000 * 1000);
|
||||
}
|
||||
|
||||
|
||||
extern "C" timepoint_ns
|
||||
time_state_from_timespec(struct time_state const *state,
|
||||
const struct timespec *timespecTime)
|
||||
{
|
||||
assert(state != NULL);
|
||||
assert(timespecTime != NULL);
|
||||
auto sinceEpoch =
|
||||
seconds{timespecTime->tv_sec} + nanoseconds{timespecTime->tv_nsec};
|
||||
|
||||
uint64_t ns = 0;
|
||||
ns += timespecTime->tv_nsec;
|
||||
ns += timespecTime->tv_sec * 1000 * 1000 * 1000;
|
||||
|
||||
// System clock epoch is same as unix epoch for all known
|
||||
// implementations, but not strictly standard-required yet, see
|
||||
// wg21.link/p0355
|
||||
auto systemTimePoint = time_point<system_clock, nanoseconds>{
|
||||
duration_cast<system_clock::duration>(sinceEpoch)};
|
||||
|
||||
// duration between last update and the supplied timespec
|
||||
auto sinceLastUpdate = state->lastTimePoints.sys - systemTimePoint;
|
||||
|
||||
// Offset the last timestamp by that duration.
|
||||
return state->lastTime +
|
||||
duration_cast<nanoseconds>(sinceLastUpdate).count();
|
||||
return time_state_monotonic_to_ts_ns(state, ns);
|
||||
}
|
||||
|
||||
|
||||
timepoint_ns
|
||||
time_state_from_monotonic_ns(struct time_state const *state,
|
||||
uint64_t monotonic_ns)
|
||||
extern "C" timepoint_ns
|
||||
time_state_monotonic_to_ts_ns(struct time_state const *state,
|
||||
uint64_t monotonic_ns)
|
||||
{
|
||||
assert(state != NULL);
|
||||
auto sinceLastUpdate =
|
||||
seconds{state->lastTimePoints.clock_monotonic.tv_sec} +
|
||||
nanoseconds{state->lastTimePoints.clock_monotonic.tv_nsec} -
|
||||
nanoseconds{monotonic_ns};
|
||||
|
||||
// Offset the last timestamp by that duration.
|
||||
return state->lastTime +
|
||||
duration_cast<nanoseconds>(sinceLastUpdate).count();
|
||||
return monotonic_ns + state->offset;
|
||||
}
|
||||
|
||||
extern "C" uint64_t
|
||||
time_state_ts_to_monotonic_ns(struct time_state const *state,
|
||||
timepoint_ns timestamp)
|
||||
{
|
||||
return timestamp - state->offset;
|
||||
}
|
||||
|
|
|
@ -164,8 +164,23 @@ time_state_from_timespec(struct time_state const *state,
|
|||
* @ingroup aux_util
|
||||
*/
|
||||
timepoint_ns
|
||||
time_state_from_monotonic_ns(struct time_state const *state,
|
||||
uint64_t monotonic_ns);
|
||||
time_state_monotonic_to_ts_ns(struct time_state const *state,
|
||||
uint64_t monotonic_ns);
|
||||
|
||||
/*!
|
||||
* Convert a adjusted integer timestamp to an monotonic system time (such as
|
||||
* from @ref aux_os_time).
|
||||
*
|
||||
* Should not be called simultaneously with time_state_get_now_and_update.
|
||||
*
|
||||
* @public @memberof time_state
|
||||
* @ingroup aux_util
|
||||
*/
|
||||
uint64_t
|
||||
time_state_ts_to_monotonic_ns(struct time_state const *state,
|
||||
timepoint_ns timestamp);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -407,13 +407,13 @@ oxr_session_frame_wait(struct oxr_logger *log,
|
|||
|
||||
frameState->shouldRender = should_render(sess->state);
|
||||
frameState->predictedDisplayPeriod = predicted_display_period;
|
||||
frameState->predictedDisplayTime = time_state_from_monotonic_ns(
|
||||
frameState->predictedDisplayTime = time_state_monotonic_to_ts_ns(
|
||||
sess->sys->inst->timekeeping, predicted_display_time);
|
||||
|
||||
if (frameState->predictedDisplayTime <= 0) {
|
||||
return oxr_error(
|
||||
log, XR_ERROR_RUNTIME_FAILURE,
|
||||
" time_state_from_monotonic_ns returned '%" PRIi64 "'",
|
||||
" time_state_monotonic_to_ts_ns returned '%" PRIi64 "'",
|
||||
frameState->predictedDisplayTime);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ oxr_xdev_get_relation_at(struct oxr_logger *log,
|
|||
// Always make those to base things valid.
|
||||
ensure_valid_position_and_orientation(&relation, offset);
|
||||
|
||||
*out_relation_timestamp_ns = time_state_from_monotonic_ns(
|
||||
*out_relation_timestamp_ns = time_state_monotonic_to_ts_ns(
|
||||
inst->timekeeping, relation_timestamp_ns);
|
||||
|
||||
*out_relation = relation;
|
||||
|
|
Loading…
Reference in a new issue