mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +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);
|
||||
|
||||
struct multi_compositor volatile *v_mc = mc;
|
||||
|
||||
// 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.
|
||||
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;
|
||||
}
|
||||
|
||||
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_nanosleep(U_TIME_1MS_IN_NS);
|
||||
|
|
|
@ -153,6 +153,11 @@ struct multi_compositor
|
|||
//! Lock for all of the slots.
|
||||
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.
|
||||
* 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
|
||||
/*!
|
||||
* @file
|
||||
|
@ -282,10 +282,31 @@ transfer_layers_locked(struct multi_system_compositor *msc, uint64_t display_tim
|
|||
}
|
||||
|
||||
static void
|
||||
broadcast_timings(struct multi_system_compositor *msc,
|
||||
uint64_t predicted_display_time_ns,
|
||||
uint64_t predicted_display_period_ns,
|
||||
uint64_t diff_ns)
|
||||
broadcast_timings_to_clients(struct multi_system_compositor *msc, uint64_t predicted_display_time_ns)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
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();
|
||||
|
||||
|
@ -302,6 +323,10 @@ broadcast_timings(struct multi_system_compositor *msc,
|
|||
predicted_display_time_ns, //
|
||||
predicted_display_period_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;
|
||||
|
@ -312,26 +337,10 @@ broadcast_timings(struct multi_system_compositor *msc,
|
|||
}
|
||||
|
||||
static void
|
||||
wait_frame(struct xrt_compositor *xc,
|
||||
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)
|
||||
wait_frame(struct xrt_compositor *xc, int64_t frame_id, uint64_t wake_up_time_ns)
|
||||
{
|
||||
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();
|
||||
if (now_ns < wake_up_time_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();
|
||||
|
||||
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
|
||||
|
@ -361,24 +367,32 @@ multi_main_loop(struct multi_system_compositor *msc)
|
|||
while (os_thread_helper_is_running_locked(&msc->oth)) {
|
||||
os_thread_helper_unlock(&msc->oth);
|
||||
|
||||
int64_t frame_id;
|
||||
uint64_t wake_time_ns = 0;
|
||||
int64_t frame_id = -1;
|
||||
uint64_t wake_up_time_ns = 0;
|
||||
uint64_t predicted_gpu_time_ns = 0;
|
||||
uint64_t predicted_display_time_ns = 0;
|
||||
uint64_t predicted_display_period_ns = 0;
|
||||
|
||||
wait_frame( //
|
||||
// Get the information for the next frame.
|
||||
xrt_comp_predict_frame( //
|
||||
xc, //
|
||||
&frame_id, //
|
||||
&wake_time_ns, //
|
||||
&wake_up_time_ns, //
|
||||
&predicted_gpu_time_ns, //
|
||||
&predicted_display_time_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 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_layer_begin(xc, frame_id, 0, 0);
|
||||
|
|
Loading…
Reference in a new issue