mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-07 15:46:12 +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
|
* @ingroup aux_util
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "u_time.h"
|
|
||||||
#include "xrt/xrt_config_os.h"
|
#include "xrt/xrt_config_os.h"
|
||||||
#include "xrt/xrt_compiler.h"
|
#include "xrt/xrt_compiler.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include "os/os_time.h"
|
||||||
|
|
||||||
|
#include "u_time.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#ifdef XRT_OS_LINUX
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std::chrono;
|
/*
|
||||||
|
*
|
||||||
struct MatchingTimePoints
|
* Structs.
|
||||||
{
|
*
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct time_state
|
struct time_state
|
||||||
{
|
{
|
||||||
MatchingTimePoints lastTimePoints = {};
|
// Hardcoded to one second offset.
|
||||||
timepoint_ns lastTime = {};
|
timepoint_ns offset = 1000 * 1000 * 1000;
|
||||||
};
|
};
|
||||||
|
|
||||||
timepoint_ns
|
|
||||||
MatchingTimePoints::getTimestamp(time_state const &prevState)
|
/*
|
||||||
{
|
*
|
||||||
//! @todo right now just doing steady clock for simplicity.
|
* 'Exported' functions.
|
||||||
//! @todo Eventually need to make the high-res clock steady.
|
*
|
||||||
auto elapsed = steady - prevState.lastTimePoints.steady;
|
*/
|
||||||
return prevState.lastTime + duration_cast<nanoseconds>(elapsed).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" struct time_state *
|
extern "C" struct time_state *
|
||||||
time_state_create()
|
time_state_create()
|
||||||
{
|
{
|
||||||
|
|
||||||
time_state *state = new (std::nothrow) time_state;
|
time_state *state = new (std::nothrow) time_state;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -83,24 +63,16 @@ extern "C" timepoint_ns
|
||||||
time_state_get_now(struct time_state const *state)
|
time_state_get_now(struct time_state const *state)
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
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
|
extern "C" timepoint_ns
|
||||||
time_state_get_now_and_update(struct time_state *state)
|
time_state_get_now_and_update(struct time_state *state)
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
auto now = MatchingTimePoints();
|
|
||||||
|
|
||||||
auto timestamp = now.getTimestamp(*state);
|
return time_state_get_now(state);
|
||||||
|
|
||||||
// Update the state
|
|
||||||
state->lastTimePoints = now;
|
|
||||||
state->lastTime = timestamp;
|
|
||||||
|
|
||||||
return timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
|
@ -110,60 +82,39 @@ time_state_to_timespec(struct time_state const *state,
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
assert(out != 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
|
uint64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
|
||||||
// implementations, but not strictly standard-required yet, see
|
|
||||||
// wg21.link/p0355
|
out->tv_sec = ns / (1000 * 1000 * 1000);
|
||||||
auto sinceEpoch = equivSystemTimepoint.time_since_epoch();
|
out->tv_nsec = ns % (1000 * 1000 * 1000);
|
||||||
auto secondsSinceEpoch = duration_cast<seconds>(sinceEpoch);
|
|
||||||
sinceEpoch -= secondsSinceEpoch;
|
|
||||||
out->tv_sec = secondsSinceEpoch.count();
|
|
||||||
out->tv_nsec = duration_cast<nanoseconds>(sinceEpoch).count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" timepoint_ns
|
extern "C" timepoint_ns
|
||||||
time_state_from_timespec(struct time_state const *state,
|
time_state_from_timespec(struct time_state const *state,
|
||||||
const struct timespec *timespecTime)
|
const struct timespec *timespecTime)
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
assert(timespecTime != 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
|
return time_state_monotonic_to_ts_ns(state, ns);
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" timepoint_ns
|
||||||
timepoint_ns
|
time_state_monotonic_to_ts_ns(struct time_state const *state,
|
||||||
time_state_from_monotonic_ns(struct time_state const *state,
|
uint64_t monotonic_ns)
|
||||||
uint64_t monotonic_ns)
|
|
||||||
{
|
{
|
||||||
assert(state != NULL);
|
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 monotonic_ns + state->offset;
|
||||||
return state->lastTime +
|
}
|
||||||
duration_cast<nanoseconds>(sinceLastUpdate).count();
|
|
||||||
|
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
|
* @ingroup aux_util
|
||||||
*/
|
*/
|
||||||
timepoint_ns
|
timepoint_ns
|
||||||
time_state_from_monotonic_ns(struct time_state const *state,
|
time_state_monotonic_to_ts_ns(struct time_state const *state,
|
||||||
uint64_t monotonic_ns);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -407,13 +407,13 @@ oxr_session_frame_wait(struct oxr_logger *log,
|
||||||
|
|
||||||
frameState->shouldRender = should_render(sess->state);
|
frameState->shouldRender = should_render(sess->state);
|
||||||
frameState->predictedDisplayPeriod = predicted_display_period;
|
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);
|
sess->sys->inst->timekeeping, predicted_display_time);
|
||||||
|
|
||||||
if (frameState->predictedDisplayTime <= 0) {
|
if (frameState->predictedDisplayTime <= 0) {
|
||||||
return oxr_error(
|
return oxr_error(
|
||||||
log, XR_ERROR_RUNTIME_FAILURE,
|
log, XR_ERROR_RUNTIME_FAILURE,
|
||||||
" time_state_from_monotonic_ns returned '%" PRIi64 "'",
|
" time_state_monotonic_to_ts_ns returned '%" PRIi64 "'",
|
||||||
frameState->predictedDisplayTime);
|
frameState->predictedDisplayTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ oxr_xdev_get_relation_at(struct oxr_logger *log,
|
||||||
// Always make those to base things valid.
|
// Always make those to base things valid.
|
||||||
ensure_valid_position_and_orientation(&relation, offset);
|
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);
|
inst->timekeeping, relation_timestamp_ns);
|
||||||
|
|
||||||
*out_relation = relation;
|
*out_relation = relation;
|
||||||
|
|
Loading…
Reference in a new issue