From d4832ab57839c3f9685ea643944ba53d551b62ab Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Wed, 24 Apr 2024 18:21:01 +0800 Subject: [PATCH] clutter/frame-clock: Break a feedback loop between VRR and triple buffering VRR calls `clutter_frame_clock_schedule_update_now` which would keep the buffer queue full, which in turn prevented direct scanout mode. Because OnscreenNative currently only supports direct scanout with double buffering. We now break that feedback loop by preventing triple buffering from being scheduled when the frame clock mode becomes variable. Long term this could also be solved by supporting triple buffering in direct scanout mode. But whether or not that would be optimal given the latency penalty remains to be seen. --- clutter/clutter/clutter-frame-clock.c | 31 ++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 63a4b3aaa..9d4a2531a 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c @@ -881,6 +881,25 @@ clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock) maybe_reschedule_update (frame_clock); } +static gboolean +want_triple_buffering (ClutterFrameClock *frame_clock) +{ + switch (triple_buffering_mode) + { + case TRIPLE_BUFFERING_MODE_NEVER: + return FALSE; + case TRIPLE_BUFFERING_MODE_AUTO: + return frame_clock->mode == CLUTTER_FRAME_CLOCK_MODE_FIXED && + !(frame_clock->last_flip_hints & + CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED); + case TRIPLE_BUFFERING_MODE_ALWAYS: + return TRUE; + } + + g_assert_not_reached (); + return FALSE; +} + void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) { @@ -903,12 +922,19 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW: case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW: return; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: next_update_time_us = g_get_monotonic_time (); frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW; break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + if (want_triple_buffering (frame_clock)) + { + frame_clock->state = + CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW; + break; + } + G_GNUC_FALLTHROUGH; case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: frame_clock->pending_reschedule = TRUE; frame_clock->pending_reschedule_now = TRUE; @@ -947,8 +973,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) TripleBufferingMode current_mode = triple_buffering_mode; if (current_mode == TRIPLE_BUFFERING_MODE_AUTO && - (frame_clock->last_flip_hints & - CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)) + !want_triple_buffering (frame_clock)) current_mode = TRIPLE_BUFFERING_MODE_NEVER; if (frame_clock->inhibit_count > 0)