mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-19 13:18:32 +00:00
c/multi: Be slightly smarter about late frames
This commit is contained in:
parent
cf413a445f
commit
e7713bf1e4
|
@ -177,15 +177,31 @@ wait_for_scheduled_free(struct multi_compositor *mc)
|
||||||
|
|
||||||
os_mutex_lock(&mc->slot_lock);
|
os_mutex_lock(&mc->slot_lock);
|
||||||
|
|
||||||
|
struct multi_compositor volatile *v_mc = mc;
|
||||||
|
|
||||||
// Block here if the scheduled slot is not clear.
|
// Block here if the scheduled slot is not clear.
|
||||||
while (mc->scheduled.active) {
|
while (v_mc->scheduled.active) {
|
||||||
|
|
||||||
|
// This frame is for the next frame, drop the old one no matter what.
|
||||||
|
if (time_is_within_half_ms(mc->progress.display_time_ns, mc->slot_next_frame_display)) {
|
||||||
|
U_LOG_W("Dropping old missed frame in favour for completed new frame");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace the scheduled frame if it's in the past.
|
// Replace the scheduled frame if it's in the past.
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
if (mc->scheduled.display_time_ns < now_ns) {
|
if (v_mc->scheduled.display_time_ns < now_ns) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U_LOG_D("next: %f (%" PRIu64 ")\nprogress: %f (%" PRIu64 ")\nscheduled: %f (%" PRIu64 ")\n",
|
||||||
|
time_ns_to_ms_f((int64_t)v_mc->slot_next_frame_display - now_ns), //
|
||||||
|
v_mc->slot_next_frame_display, //
|
||||||
|
time_ns_to_ms_f((int64_t)v_mc->progress.display_time_ns - now_ns), //
|
||||||
|
v_mc->progress.display_time_ns, //
|
||||||
|
time_ns_to_ms_f((int64_t)v_mc->scheduled.display_time_ns - now_ns), //
|
||||||
|
v_mc->scheduled.display_time_ns); //
|
||||||
|
|
||||||
os_mutex_unlock(&mc->slot_lock);
|
os_mutex_unlock(&mc->slot_lock);
|
||||||
|
|
||||||
os_nanosleep(U_TIME_1MS_IN_NS);
|
os_nanosleep(U_TIME_1MS_IN_NS);
|
||||||
|
|
|
@ -153,6 +153,11 @@ struct multi_compositor
|
||||||
//! Lock for all of the slots.
|
//! Lock for all of the slots.
|
||||||
struct os_mutex slot_lock;
|
struct os_mutex slot_lock;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* The next which the next frames to be picked up will be displayed.
|
||||||
|
*/
|
||||||
|
uint64_t slot_next_frame_display;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Currently being transferred or waited on.
|
* Currently being transferred or waited on.
|
||||||
* Not protected by the slot lock as it is only touched by the client thread.
|
* Not protected by the slot lock as it is only touched by the client thread.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2019-2021, Collabora, Ltd.
|
// Copyright 2019-2022, Collabora, Ltd.
|
||||||
// SPDX-License-Identifier: BSL-1.0
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
/*!
|
/*!
|
||||||
* @file
|
* @file
|
||||||
|
@ -282,10 +282,31 @@ transfer_layers_locked(struct multi_system_compositor *msc, uint64_t display_tim
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
broadcast_timings(struct multi_system_compositor *msc,
|
broadcast_timings_to_clients(struct multi_system_compositor *msc, uint64_t predicted_display_time_ns)
|
||||||
uint64_t predicted_display_time_ns,
|
{
|
||||||
uint64_t predicted_display_period_ns,
|
COMP_TRACE_MARKER();
|
||||||
uint64_t diff_ns)
|
|
||||||
|
os_mutex_lock(&msc->list_and_timing_lock);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(msc->clients); i++) {
|
||||||
|
struct multi_compositor *mc = msc->clients[i];
|
||||||
|
if (mc == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_mutex_lock(&mc->slot_lock);
|
||||||
|
mc->slot_next_frame_display = predicted_display_time_ns;
|
||||||
|
os_mutex_unlock(&mc->slot_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_mutex_unlock(&msc->list_and_timing_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
broadcast_timings_to_pacers(struct multi_system_compositor *msc,
|
||||||
|
uint64_t predicted_display_time_ns,
|
||||||
|
uint64_t predicted_display_period_ns,
|
||||||
|
uint64_t diff_ns)
|
||||||
{
|
{
|
||||||
COMP_TRACE_MARKER();
|
COMP_TRACE_MARKER();
|
||||||
|
|
||||||
|
@ -302,6 +323,10 @@ broadcast_timings(struct multi_system_compositor *msc,
|
||||||
predicted_display_time_ns, //
|
predicted_display_time_ns, //
|
||||||
predicted_display_period_ns, //
|
predicted_display_period_ns, //
|
||||||
diff_ns); //
|
diff_ns); //
|
||||||
|
|
||||||
|
os_mutex_lock(&mc->slot_lock);
|
||||||
|
mc->slot_next_frame_display = predicted_display_time_ns;
|
||||||
|
os_mutex_unlock(&mc->slot_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
msc->last_timings.predicted_display_time_ns = predicted_display_time_ns;
|
msc->last_timings.predicted_display_time_ns = predicted_display_time_ns;
|
||||||
|
@ -312,26 +337,10 @@ broadcast_timings(struct multi_system_compositor *msc,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wait_frame(struct xrt_compositor *xc,
|
wait_frame(struct xrt_compositor *xc, int64_t frame_id, uint64_t wake_up_time_ns)
|
||||||
int64_t *out_frame_id,
|
|
||||||
uint64_t *out_wake_time_ns,
|
|
||||||
uint64_t *out_predicted_gpu_time_ns,
|
|
||||||
uint64_t *out_predicted_display_time_ns,
|
|
||||||
uint64_t *out_predicted_display_period_ns)
|
|
||||||
{
|
{
|
||||||
COMP_TRACE_MARKER();
|
COMP_TRACE_MARKER();
|
||||||
|
|
||||||
int64_t frame_id = -1;
|
|
||||||
uint64_t wake_up_time_ns = 0;
|
|
||||||
|
|
||||||
xrt_comp_predict_frame( //
|
|
||||||
xc, //
|
|
||||||
&frame_id, //
|
|
||||||
&wake_up_time_ns, //
|
|
||||||
out_predicted_gpu_time_ns, //
|
|
||||||
out_predicted_display_time_ns, //
|
|
||||||
out_predicted_display_period_ns); //
|
|
||||||
|
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
if (now_ns < wake_up_time_ns) {
|
if (now_ns < wake_up_time_ns) {
|
||||||
os_nanosleep(wake_up_time_ns - now_ns);
|
os_nanosleep(wake_up_time_ns - now_ns);
|
||||||
|
@ -340,9 +349,6 @@ wait_frame(struct xrt_compositor *xc,
|
||||||
now_ns = os_monotonic_get_ns();
|
now_ns = os_monotonic_get_ns();
|
||||||
|
|
||||||
xrt_comp_mark_frame(xc, frame_id, XRT_COMPOSITOR_FRAME_POINT_WOKE, now_ns);
|
xrt_comp_mark_frame(xc, frame_id, XRT_COMPOSITOR_FRAME_POINT_WOKE, now_ns);
|
||||||
|
|
||||||
*out_frame_id = frame_id;
|
|
||||||
*out_wake_time_ns = wake_up_time_ns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -361,24 +367,32 @@ multi_main_loop(struct multi_system_compositor *msc)
|
||||||
while (os_thread_helper_is_running_locked(&msc->oth)) {
|
while (os_thread_helper_is_running_locked(&msc->oth)) {
|
||||||
os_thread_helper_unlock(&msc->oth);
|
os_thread_helper_unlock(&msc->oth);
|
||||||
|
|
||||||
int64_t frame_id;
|
int64_t frame_id = -1;
|
||||||
uint64_t wake_time_ns = 0;
|
uint64_t wake_up_time_ns = 0;
|
||||||
uint64_t predicted_gpu_time_ns = 0;
|
uint64_t predicted_gpu_time_ns = 0;
|
||||||
uint64_t predicted_display_time_ns = 0;
|
uint64_t predicted_display_time_ns = 0;
|
||||||
uint64_t predicted_display_period_ns = 0;
|
uint64_t predicted_display_period_ns = 0;
|
||||||
|
|
||||||
wait_frame( //
|
// Get the information for the next frame.
|
||||||
|
xrt_comp_predict_frame( //
|
||||||
xc, //
|
xc, //
|
||||||
&frame_id, //
|
&frame_id, //
|
||||||
&wake_time_ns, //
|
&wake_up_time_ns, //
|
||||||
&predicted_gpu_time_ns, //
|
&predicted_gpu_time_ns, //
|
||||||
&predicted_display_time_ns, //
|
&predicted_display_time_ns, //
|
||||||
&predicted_display_period_ns); //
|
&predicted_display_period_ns); //
|
||||||
|
|
||||||
|
// Do this as soon as we have the new display time.
|
||||||
|
broadcast_timings_to_clients(msc, predicted_display_time_ns);
|
||||||
|
|
||||||
|
// Now we can wait.
|
||||||
|
wait_frame(xc, frame_id, wake_up_time_ns);
|
||||||
|
|
||||||
uint64_t now_ns = os_monotonic_get_ns();
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
uint64_t diff_ns = predicted_display_time_ns - now_ns;
|
uint64_t diff_ns = predicted_display_time_ns - now_ns;
|
||||||
|
|
||||||
broadcast_timings(msc, predicted_display_time_ns, predicted_display_period_ns, diff_ns);
|
// Now we know the diff, broadcast to pacers.
|
||||||
|
broadcast_timings_to_pacers(msc, predicted_display_time_ns, predicted_display_period_ns, diff_ns);
|
||||||
|
|
||||||
xrt_comp_begin_frame(xc, frame_id);
|
xrt_comp_begin_frame(xc, frame_id);
|
||||||
xrt_comp_layer_begin(xc, frame_id, 0, 0);
|
xrt_comp_layer_begin(xc, frame_id, 0, 0);
|
||||||
|
|
Loading…
Reference in a new issue