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.
This commit is contained in:
parent
8124914758
commit
d4832ab578
1 changed files with 28 additions and 3 deletions
|
@ -881,6 +881,25 @@ clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
|
||||||
maybe_reschedule_update (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
|
void
|
||||||
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
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_SCHEDULED_NOW:
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
||||||
return;
|
return;
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
||||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
||||||
next_update_time_us = g_get_monotonic_time ();
|
next_update_time_us = g_get_monotonic_time ();
|
||||||
frame_clock->state =
|
frame_clock->state =
|
||||||
CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW;
|
CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW;
|
||||||
break;
|
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:
|
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
||||||
frame_clock->pending_reschedule = TRUE;
|
frame_clock->pending_reschedule = TRUE;
|
||||||
frame_clock->pending_reschedule_now = 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;
|
TripleBufferingMode current_mode = triple_buffering_mode;
|
||||||
|
|
||||||
if (current_mode == TRIPLE_BUFFERING_MODE_AUTO &&
|
if (current_mode == TRIPLE_BUFFERING_MODE_AUTO &&
|
||||||
(frame_clock->last_flip_hints &
|
!want_triple_buffering (frame_clock))
|
||||||
CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED))
|
|
||||||
current_mode = TRIPLE_BUFFERING_MODE_NEVER;
|
current_mode = TRIPLE_BUFFERING_MODE_NEVER;
|
||||||
|
|
||||||
if (frame_clock->inhibit_count > 0)
|
if (frame_clock->inhibit_count > 0)
|
||||||
|
|
Loading…
Reference in a new issue