mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-24 15:41:55 +00:00
c24e482e5e
This solves a problem where OpenXR timestamps could become invalid (negative) in certain circumstances: The timestamps that the OpenXR state tracker returned were offset such that they appeared to start at OpenXR application startup time. However monado-service is a long running service using system timestamps. Because of this, if monado-service started work using a system timestamp acquired before an OpenXR application started, then this system timestamp could not be converted into an OpenXR without becoming invalid. With this change, the OpenXR timestamps for OpenXR applications are offset such that they appear to start at monado-service startup time instead. As a side effect, all OpenXR applications connected to the same monado-service instance will receive timestamps from the same domain.
145 lines
2.8 KiB
C++
145 lines
2.8 KiB
C++
// Copyright 2019-2020, Collabora, Ltd.
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
/*!
|
|
* @file
|
|
* @brief Implementation of a steady, convertible clock.
|
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
|
* @ingroup aux_util
|
|
*/
|
|
|
|
#include "xrt/xrt_config_os.h"
|
|
#include "xrt/xrt_compiler.h"
|
|
|
|
#include "os/os_time.h"
|
|
|
|
#include "u_time.h"
|
|
|
|
#include <new>
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
|
|
/*
|
|
*
|
|
* Structs.
|
|
*
|
|
*/
|
|
|
|
struct time_state
|
|
{
|
|
timepoint_ns offset;
|
|
};
|
|
|
|
|
|
/*
|
|
*
|
|
* 'Exported' functions.
|
|
*
|
|
*/
|
|
|
|
extern "C" struct time_state *
|
|
time_state_create(uint64_t offset)
|
|
{
|
|
time_state *state = new (std::nothrow) time_state;
|
|
if (!state) {
|
|
return state;
|
|
}
|
|
state->offset = offset;
|
|
return state;
|
|
}
|
|
|
|
extern "C" void
|
|
time_state_destroy(struct time_state **state_ptr)
|
|
{
|
|
struct time_state *state = *state_ptr;
|
|
|
|
if (state == NULL) {
|
|
return;
|
|
}
|
|
|
|
delete state;
|
|
*state_ptr = NULL;
|
|
}
|
|
|
|
extern "C" timepoint_ns
|
|
time_state_get_now(struct time_state const *state)
|
|
{
|
|
assert(state != NULL);
|
|
|
|
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);
|
|
|
|
return time_state_get_now(state);
|
|
}
|
|
|
|
extern "C" void
|
|
time_state_to_timespec(struct time_state const *state, timepoint_ns timestamp, struct timespec *out)
|
|
{
|
|
assert(state != NULL);
|
|
assert(out != NULL);
|
|
|
|
uint64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
|
|
|
|
out->tv_sec = ns / (U_1_000_000_000);
|
|
out->tv_nsec = ns % (U_1_000_000_000);
|
|
}
|
|
|
|
extern "C" timepoint_ns
|
|
time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime)
|
|
{
|
|
assert(state != NULL);
|
|
assert(timespecTime != NULL);
|
|
|
|
uint64_t ns = 0;
|
|
ns += timespecTime->tv_nsec;
|
|
ns += timespecTime->tv_sec * U_1_000_000_000;
|
|
|
|
return time_state_monotonic_to_ts_ns(state, ns);
|
|
}
|
|
|
|
extern "C" timepoint_ns
|
|
time_state_monotonic_to_ts_ns(struct time_state const *state, uint64_t monotonic_ns)
|
|
{
|
|
assert(state != NULL);
|
|
|
|
return monotonic_ns - state->offset;
|
|
}
|
|
|
|
extern "C" uint64_t
|
|
time_state_ts_to_monotonic_ns(struct time_state const *state, timepoint_ns timestamp)
|
|
{
|
|
assert(state != NULL);
|
|
|
|
return timestamp + state->offset;
|
|
}
|
|
|
|
#ifdef XRT_OS_WINDOWS
|
|
extern "C" void
|
|
time_state_to_win32perfcounter(struct time_state const *state, timepoint_ns timestamp, LARGE_INTEGER *out_qpc_ticks)
|
|
{
|
|
assert(state != NULL);
|
|
assert(out_qpc_ticks != NULL);
|
|
|
|
uint64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
|
|
|
|
out_qpc_ticks->QuadPart = ns / os_ns_per_qpc_tick_get();
|
|
}
|
|
|
|
extern "C" timepoint_ns
|
|
time_state_from_win32perfcounter(struct time_state const *state, const LARGE_INTEGER *qpc_ticks)
|
|
{
|
|
assert(state != NULL);
|
|
assert(qpc_ticks != NULL);
|
|
|
|
uint64_t ns = qpc_ticks->QuadPart * os_ns_per_qpc_tick_get();
|
|
|
|
return time_state_monotonic_to_ts_ns(state, ns);
|
|
}
|
|
#endif // XRT_OS_WINDOWS
|