clutter/frame-clock,wayland: Calculate frame deadline during scheduling

Calculate the frame deadline in ClutterFrameClock's
calculate_next_update_time_us() rather than in MetaWaylandCompositor's
on_after_update().

The specifics of the deadline calculation for a given frame should be
implementation detail of the frame clock and and remain internal to
allow extensibility.

This extensibility is specifically useful for scenarios where a
different deadline calculation is needed due to alternative frame
scheduling logic, such as for VRR.

No change in behavior.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3521>
This commit is contained in:
Dor Askayo 2023-09-24 16:18:42 +03:00
parent d5c2f20d55
commit 3e4a330ae7
5 changed files with 25 additions and 23 deletions

View File

@ -79,7 +79,9 @@ struct _ClutterFrameClock
gboolean is_next_presentation_time_valid;
int64_t next_presentation_time_us;
int64_t min_render_time_allowed_us;
gboolean has_next_frame_deadline;
int64_t next_frame_deadline_us;
/* Buffer must be submitted to KMS and GPU rendering must be finished
* this amount of time before the next presentation time.
@ -451,7 +453,7 @@ static void
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
int64_t *out_next_update_time_us,
int64_t *out_next_presentation_time_us,
int64_t *out_min_render_time_allowed_us)
int64_t *out_next_frame_deadline_us)
{
int64_t last_presentation_time_us;
int64_t now_us;
@ -474,7 +476,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
now_us;
*out_next_presentation_time_us = 0;
*out_min_render_time_allowed_us = 0;
*out_next_frame_deadline_us = 0;
return;
}
@ -583,7 +585,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
}
else
{
while (next_presentation_time_us < now_us + min_render_time_allowed_us)
while (next_presentation_time_us - min_render_time_allowed_us < now_us)
next_presentation_time_us += refresh_interval_us;
next_update_time_us = next_presentation_time_us - max_render_time_allowed_us;
@ -593,7 +595,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
*out_next_update_time_us = next_update_time_us;
*out_next_presentation_time_us = next_presentation_time_us;
*out_min_render_time_allowed_us = min_render_time_allowed_us;
*out_next_frame_deadline_us = next_presentation_time_us - min_render_time_allowed_us;
}
void
@ -664,6 +666,7 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
frame_clock->is_next_presentation_time_valid = FALSE;
frame_clock->has_next_frame_deadline = FALSE;
}
void
@ -686,9 +689,11 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
calculate_next_update_time_us (frame_clock,
&next_update_time_us,
&frame_clock->next_presentation_time_us,
&frame_clock->min_render_time_allowed_us);
&frame_clock->next_frame_deadline_us);
frame_clock->is_next_presentation_time_valid =
(frame_clock->next_presentation_time_us != 0);
frame_clock->has_next_frame_deadline =
(frame_clock->next_frame_deadline_us != 0);
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return;
@ -770,7 +775,9 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
frame->frame_count = frame_count;
frame->has_target_presentation_time = frame_clock->is_next_presentation_time_valid;
frame->target_presentation_time_us = frame_clock->next_presentation_time_us;
frame->min_render_time_allowed_us = frame_clock->min_render_time_allowed_us;
frame->has_frame_deadline = frame_clock->has_next_frame_deadline;
frame->frame_deadline_us = frame_clock->next_frame_deadline_us;
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockEvents, "Clutter::FrameListener::before_frame()");
if (iface->before_frame)

View File

@ -30,7 +30,9 @@ struct _ClutterFrame
gboolean has_target_presentation_time;
int64_t target_presentation_time_us;
int64_t min_render_time_allowed_us;
gboolean has_frame_deadline;
int64_t frame_deadline_us;
gboolean has_result;
ClutterFrameResult result;

View File

@ -76,12 +76,12 @@ clutter_frame_get_target_presentation_time (ClutterFrame *frame,
}
gboolean
clutter_frame_get_min_render_time_allowed (ClutterFrame *frame,
int64_t *min_render_time_allowed_us)
clutter_frame_get_frame_deadline (ClutterFrame *frame,
int64_t *frame_deadline_us)
{
if (frame->has_target_presentation_time)
if (frame->has_frame_deadline)
{
*min_render_time_allowed_us = frame->min_render_time_allowed_us;
*frame_deadline_us = frame->frame_deadline_us;
return TRUE;
}
else

View File

@ -44,8 +44,8 @@ gboolean clutter_frame_get_target_presentation_time (ClutterFrame *frame,
int64_t *target_presentation_time_us);
CLUTTER_EXPORT
gboolean clutter_frame_get_min_render_time_allowed (ClutterFrame *frame,
int64_t *min_render_time_allowed_us);
gboolean clutter_frame_get_frame_deadline (ClutterFrame *frame,
int64_t *frame_deadline_us);
CLUTTER_EXPORT
void clutter_frame_set_result (ClutterFrame *frame,

View File

@ -295,8 +295,6 @@ on_after_update (ClutterStage *stage,
MetaBackend *backend = meta_context_get_backend (context);
MetaFrameNative *frame_native;
GSource *source;
int64_t min_render_time_allowed_us;
int64_t target_presentation_time_us;
int64_t frame_deadline_us;
if (!META_IS_BACKEND_NATIVE (backend))
@ -310,19 +308,14 @@ on_after_update (ClutterStage *stage,
source = ensure_source_for_stage_view (compositor, stage_view);
if (meta_frame_native_had_kms_update (frame_native) ||
!clutter_frame_get_min_render_time_allowed (frame,
&min_render_time_allowed_us) ||
!clutter_frame_get_target_presentation_time (frame,
&target_presentation_time_us))
!clutter_frame_get_frame_deadline (frame,
&frame_deadline_us))
{
g_source_set_ready_time (source, -1);
emit_frame_callbacks_for_stage_view (compositor, stage_view);
return;
}
frame_deadline_us = target_presentation_time_us -
min_render_time_allowed_us;
if (frame_deadline_us <= g_get_monotonic_time ())
{
g_source_set_ready_time (source, -1);