mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +00:00
u/render_timing: Add helper code for frame timing
This commit is contained in:
parent
3275f00464
commit
83081f9cc1
|
@ -89,6 +89,8 @@ set(UTIL_SOURCE_FILES
|
|||
util/u_hashset.h
|
||||
util/u_json.c
|
||||
util/u_json.h
|
||||
util/u_render_timing.c
|
||||
util/u_render_timing.h
|
||||
util/u_sink.h
|
||||
util/u_sink_converter.c
|
||||
util/u_sink_deinterleaver.c
|
||||
|
|
|
@ -29,6 +29,8 @@ lib_aux_util = static_library(
|
|||
'util/u_json.h',
|
||||
'util/u_misc.c',
|
||||
'util/u_misc.h',
|
||||
'util/u_render_timing.c',
|
||||
'util/u_render_timing.h',
|
||||
'util/u_sink.h',
|
||||
'util/u_sink_converter.c',
|
||||
'util/u_sink_deinterleaver.c',
|
||||
|
|
188
src/xrt/auxiliary/util/u_render_timing.c
Normal file
188
src/xrt/auxiliary/util/u_render_timing.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
// Copyright 2020, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Shared frame timing code.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*/
|
||||
|
||||
#include "util/u_misc.h"
|
||||
|
||||
#include "u_render_timing.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Helpers
|
||||
*
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define DEBUG_PRINT_FRAME_ID()
|
||||
fprintf(stderr, "%s %" PRIi64 "\n", __func__, frame_id)
|
||||
#else
|
||||
#define DEBUG_PRINT_FRAME_ID() \
|
||||
do { \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
static uint64_t
|
||||
get_last_input_plus_period_at_least_greater_then(struct u_rt_helper *urth,
|
||||
uint64_t then_ns)
|
||||
{
|
||||
uint64_t val = urth->last_input;
|
||||
|
||||
while (val <= then_ns) {
|
||||
val += urth->period;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
u_rt_helper_clear(struct u_rt_helper *urth)
|
||||
{
|
||||
U_ZERO(urth);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(urth->frames); i++) {
|
||||
urth->frames[i].state = U_RT_READY;
|
||||
urth->frames[i].frame_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_init(struct u_rt_helper *urth)
|
||||
{
|
||||
u_rt_helper_clear(urth);
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_predict(struct u_rt_helper *urth,
|
||||
int64_t *out_frame_id,
|
||||
uint64_t *predicted_display_time,
|
||||
uint64_t *wake_up_time,
|
||||
uint64_t *predicted_display_period,
|
||||
uint64_t *min_display_period)
|
||||
{
|
||||
int64_t frame_id = ++urth->frame_counter;
|
||||
*out_frame_id = frame_id;
|
||||
|
||||
DEBUG_PRINT_FRAME_ID();
|
||||
|
||||
uint64_t at_least_ns = os_monotonic_get_ns();
|
||||
|
||||
// Don't return a time before the last returned type.
|
||||
if (at_least_ns < urth->last_returned) {
|
||||
at_least_ns = urth->last_returned;
|
||||
}
|
||||
|
||||
uint64_t predict_ns =
|
||||
get_last_input_plus_period_at_least_greater_then(urth, at_least_ns);
|
||||
|
||||
urth->last_returned = predict_ns;
|
||||
|
||||
*wake_up_time = predict_ns - urth->period;
|
||||
*predicted_display_time = predict_ns;
|
||||
*predicted_display_period = urth->period;
|
||||
*min_display_period = urth->period;
|
||||
|
||||
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
|
||||
assert(urth->frames[index].frame_id == -1);
|
||||
assert(urth->frames[index].state == U_RT_READY);
|
||||
|
||||
urth->frames[index].predicted = os_monotonic_get_ns();
|
||||
urth->frames[index].state = U_RT_PREDICTED;
|
||||
urth->frames[index].frame_id = frame_id;
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_mark_wait_woke(struct u_rt_helper *urth, int64_t frame_id)
|
||||
{
|
||||
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
|
||||
assert(urth->frames[index].frame_id == frame_id);
|
||||
assert(urth->frames[index].state == U_RT_PREDICTED);
|
||||
|
||||
urth->frames[index].wait_woke = os_monotonic_get_ns();
|
||||
urth->frames[index].state = U_RT_WAIT_LEFT;
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_mark_begin(struct u_rt_helper *urth, int64_t frame_id)
|
||||
{
|
||||
DEBUG_PRINT_FRAME_ID();
|
||||
DEBUG_PRINT_FRAME_ID();
|
||||
|
||||
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
|
||||
assert(urth->frames[index].frame_id == frame_id);
|
||||
assert(urth->frames[index].state == U_RT_WAIT_LEFT);
|
||||
|
||||
urth->frames[index].begin = os_monotonic_get_ns();
|
||||
urth->frames[index].state = U_RT_BEGUN;
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id)
|
||||
{
|
||||
DEBUG_PRINT_FRAME_ID();
|
||||
|
||||
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
|
||||
assert(urth->frames[index].frame_id == frame_id);
|
||||
assert(urth->frames[index].state == U_RT_WAIT_LEFT ||
|
||||
urth->frames[index].state == U_RT_BEGUN);
|
||||
|
||||
urth->frames[index].end_frame = os_monotonic_get_ns();
|
||||
urth->frames[index].state = U_RT_READY;
|
||||
urth->frames[index].frame_id = -1;
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id)
|
||||
{
|
||||
DEBUG_PRINT_FRAME_ID();
|
||||
|
||||
size_t index = (uint64_t)frame_id % ARRAY_SIZE(urth->frames);
|
||||
assert(urth->frames[index].frame_id == frame_id);
|
||||
assert(urth->frames[index].state == U_RT_BEGUN);
|
||||
|
||||
uint64_t now_ns = os_monotonic_get_ns();
|
||||
|
||||
urth->frames[index].end_frame = now_ns;
|
||||
urth->frames[index].state = U_RT_READY;
|
||||
urth->frames[index].frame_id = -1;
|
||||
|
||||
#if 0
|
||||
uint64_t then_ns = urth->frames[index].wait_woke;
|
||||
uint64_t diff_ns = now_ns - then_ns;
|
||||
uint64_t ms100 = diff_ns / (1000 * 10);
|
||||
|
||||
fprintf(stderr, "%s: Diff %i.%02ims\n", __func__, (int)ms100 / 100,
|
||||
(int)ms100 % 100);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
u_rt_helper_new_sample(struct u_rt_helper *urth,
|
||||
uint64_t predict,
|
||||
uint64_t extra,
|
||||
uint64_t min_period)
|
||||
{
|
||||
urth->last_input = predict;
|
||||
urth->extra = extra;
|
||||
urth->period = min_period;
|
||||
|
||||
if (urth->last_returned == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
87
src/xrt/auxiliary/util/u_render_timing.h
Normal file
87
src/xrt/auxiliary/util/u_render_timing.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
// Copyright 2020, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Shared frame timing code.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup aux_util
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
#include "os/os_time.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
enum u_rt_state
|
||||
{
|
||||
U_RT_READY,
|
||||
U_RT_WAIT_LEFT,
|
||||
U_RT_PREDICTED,
|
||||
U_RT_BEGUN,
|
||||
};
|
||||
|
||||
struct u_rt_frame
|
||||
{
|
||||
uint64_t predicted;
|
||||
uint64_t wait_woke;
|
||||
uint64_t begin;
|
||||
uint64_t end_frame;
|
||||
int64_t frame_id;
|
||||
enum u_rt_state state;
|
||||
};
|
||||
|
||||
struct u_rt_helper
|
||||
{
|
||||
struct u_rt_frame frames[2];
|
||||
uint32_t current_frame;
|
||||
uint32_t next_frame;
|
||||
|
||||
int64_t frame_counter;
|
||||
|
||||
uint64_t extra;
|
||||
uint64_t period;
|
||||
uint64_t last_input;
|
||||
uint64_t last_returned;
|
||||
};
|
||||
|
||||
void
|
||||
u_rt_helper_init(struct u_rt_helper *urth);
|
||||
|
||||
void
|
||||
u_rt_helper_clear(struct u_rt_helper *urth);
|
||||
|
||||
void
|
||||
u_rt_helper_predict(struct u_rt_helper *urth,
|
||||
int64_t *out_frame_id,
|
||||
uint64_t *out_predicted_display_time,
|
||||
uint64_t *out_wake_up_time,
|
||||
uint64_t *out_predicted_display_period,
|
||||
uint64_t *out_min_display_period);
|
||||
|
||||
void
|
||||
u_rt_helper_mark_wait_woke(struct u_rt_helper *urth, int64_t frame_id);
|
||||
|
||||
void
|
||||
u_rt_helper_mark_begin(struct u_rt_helper *urth, int64_t frame_id);
|
||||
|
||||
void
|
||||
u_rt_helper_mark_discarded(struct u_rt_helper *urth, int64_t frame_id);
|
||||
|
||||
void
|
||||
u_rt_helper_mark_delivered(struct u_rt_helper *urth, int64_t frame_id);
|
||||
|
||||
void
|
||||
u_rt_helper_new_sample(struct u_rt_helper *urth,
|
||||
uint64_t predict,
|
||||
uint64_t extra,
|
||||
uint64_t min_period);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue