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; gboolean is_next_presentation_time_valid;
int64_t next_presentation_time_us; 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 /* Buffer must be submitted to KMS and GPU rendering must be finished
* this amount of time before the next presentation time. * this amount of time before the next presentation time.
@ -451,7 +453,7 @@ static void
calculate_next_update_time_us (ClutterFrameClock *frame_clock, calculate_next_update_time_us (ClutterFrameClock *frame_clock,
int64_t *out_next_update_time_us, int64_t *out_next_update_time_us,
int64_t *out_next_presentation_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 last_presentation_time_us;
int64_t now_us; int64_t now_us;
@ -474,7 +476,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
now_us; now_us;
*out_next_presentation_time_us = 0; *out_next_presentation_time_us = 0;
*out_min_render_time_allowed_us = 0; *out_next_frame_deadline_us = 0;
return; return;
} }
@ -583,7 +585,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
} }
else 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_presentation_time_us += refresh_interval_us;
next_update_time_us = next_presentation_time_us - max_render_time_allowed_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_update_time_us = next_update_time_us;
*out_next_presentation_time_us = next_presentation_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 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); g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
frame_clock->is_next_presentation_time_valid = FALSE; frame_clock->is_next_presentation_time_valid = FALSE;
frame_clock->has_next_frame_deadline = FALSE;
} }
void void
@ -686,9 +689,11 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
calculate_next_update_time_us (frame_clock, calculate_next_update_time_us (frame_clock,
&next_update_time_us, &next_update_time_us,
&frame_clock->next_presentation_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->is_next_presentation_time_valid =
(frame_clock->next_presentation_time_us != 0); (frame_clock->next_presentation_time_us != 0);
frame_clock->has_next_frame_deadline =
(frame_clock->next_frame_deadline_us != 0);
break; break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return; return;
@ -770,7 +775,9 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
frame->frame_count = frame_count; frame->frame_count = frame_count;
frame->has_target_presentation_time = frame_clock->is_next_presentation_time_valid; frame->has_target_presentation_time = frame_clock->is_next_presentation_time_valid;
frame->target_presentation_time_us = frame_clock->next_presentation_time_us; 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()"); COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockEvents, "Clutter::FrameListener::before_frame()");
if (iface->before_frame) if (iface->before_frame)

View File

@ -30,7 +30,9 @@ struct _ClutterFrame
gboolean has_target_presentation_time; gboolean has_target_presentation_time;
int64_t target_presentation_time_us; 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; gboolean has_result;
ClutterFrameResult result; ClutterFrameResult result;

View File

@ -76,12 +76,12 @@ clutter_frame_get_target_presentation_time (ClutterFrame *frame,
} }
gboolean gboolean
clutter_frame_get_min_render_time_allowed (ClutterFrame *frame, clutter_frame_get_frame_deadline (ClutterFrame *frame,
int64_t *min_render_time_allowed_us) 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; return TRUE;
} }
else else

View File

@ -44,8 +44,8 @@ gboolean clutter_frame_get_target_presentation_time (ClutterFrame *frame,
int64_t *target_presentation_time_us); int64_t *target_presentation_time_us);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_frame_get_min_render_time_allowed (ClutterFrame *frame, gboolean clutter_frame_get_frame_deadline (ClutterFrame *frame,
int64_t *min_render_time_allowed_us); int64_t *frame_deadline_us);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_frame_set_result (ClutterFrame *frame, 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); MetaBackend *backend = meta_context_get_backend (context);
MetaFrameNative *frame_native; MetaFrameNative *frame_native;
GSource *source; GSource *source;
int64_t min_render_time_allowed_us;
int64_t target_presentation_time_us;
int64_t frame_deadline_us; int64_t frame_deadline_us;
if (!META_IS_BACKEND_NATIVE (backend)) if (!META_IS_BACKEND_NATIVE (backend))
@ -310,19 +308,14 @@ on_after_update (ClutterStage *stage,
source = ensure_source_for_stage_view (compositor, stage_view); source = ensure_source_for_stage_view (compositor, stage_view);
if (meta_frame_native_had_kms_update (frame_native) || if (meta_frame_native_had_kms_update (frame_native) ||
!clutter_frame_get_min_render_time_allowed (frame, !clutter_frame_get_frame_deadline (frame,
&min_render_time_allowed_us) || &frame_deadline_us))
!clutter_frame_get_target_presentation_time (frame,
&target_presentation_time_us))
{ {
g_source_set_ready_time (source, -1); g_source_set_ready_time (source, -1);
emit_frame_callbacks_for_stage_view (compositor, stage_view); emit_frame_callbacks_for_stage_view (compositor, stage_view);
return; return;
} }
frame_deadline_us = target_presentation_time_us -
min_render_time_allowed_us;
if (frame_deadline_us <= g_get_monotonic_time ()) if (frame_deadline_us <= g_get_monotonic_time ())
{ {
g_source_set_ready_time (source, -1); g_source_set_ready_time (source, -1);