diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index 4dfafb19a..cad9f88ce 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -28,8 +28,7 @@ #include "backends/native/meta-kms-update-private.h" #include "backends/native/meta-kms-utils.h" -#define DEADLINE_EVASION_US 800 -#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000 +#define DEADLINE_EVASION_CONSTANT_US 200 #define MINIMUM_REFRESH_RATE 30.f @@ -50,6 +49,10 @@ struct _MetaKmsCrtc MetaKmsCrtcState current_state; MetaKmsCrtcPropTable prop_table; + + int64_t shortterm_max_dispatch_duration_us; + int64_t deadline_evasion_us; + int64_t deadline_evasion_update_time_us; }; G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) @@ -543,6 +546,33 @@ get_crtc_type_bitmask (MetaKmsCrtc *crtc) } } +static void +maybe_update_deadline_evasion (MetaKmsCrtc *crtc, + int64_t next_presentation_time_us) +{ + /* Do not update long-term max if there has been no measurement */ + if (!crtc->shortterm_max_dispatch_duration_us) + return; + + if (next_presentation_time_us - crtc->deadline_evasion_update_time_us < + G_USEC_PER_SEC) + return; + + if (crtc->deadline_evasion_us > crtc->shortterm_max_dispatch_duration_us) + { + /* Exponential drop-off toward the clamped short-term max */ + crtc->deadline_evasion_us -= + (crtc->deadline_evasion_us - crtc->shortterm_max_dispatch_duration_us) / 2; + } + else + { + crtc->deadline_evasion_us = crtc->shortterm_max_dispatch_duration_us; + } + + crtc->shortterm_max_dispatch_duration_us = 0; + crtc->deadline_evasion_update_time_us = next_presentation_time_us; +} + gboolean meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, int64_t *out_next_deadline_us, @@ -611,6 +641,7 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, */ deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc); + maybe_update_deadline_evasion (crtc, next_presentation_us); vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode); next_deadline_us = next_presentation_us - (vblank_duration_us + @@ -623,11 +654,25 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, return TRUE; } +void +meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc, + int64_t duration_us) +{ + int64_t refresh_interval_us; + + if (duration_us <= crtc->shortterm_max_dispatch_duration_us) + return; + + refresh_interval_us = + (int64_t) (0.5 + G_USEC_PER_SEC / + meta_calculate_drm_mode_refresh_rate (&crtc->current_state.drm_mode)); + + crtc->shortterm_max_dispatch_duration_us = MIN (duration_us, refresh_interval_us); +} + int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc) { - if (meta_is_topic_enabled (META_DEBUG_KMS)) - return DEADLINE_EVASION_WITH_KMS_TOPIC_US; - else - return DEADLINE_EVASION_US; + return MAX (crtc->shortterm_max_dispatch_duration_us, + crtc->deadline_evasion_us) + DEADLINE_EVASION_CONSTANT_US; } diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h index d9682fce3..b293f8e7c 100644 --- a/src/backends/native/meta-kms-crtc.h +++ b/src/backends/native/meta-kms-crtc.h @@ -66,4 +66,7 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc); META_EXPORT_TEST gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc); +void meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc, + int64_t duration_us); + int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc); diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index dd4f4d834..cea045441 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -39,6 +39,7 @@ #include "backends/native/meta-kms-plane-private.h" #include "backends/native/meta-kms-plane.h" #include "backends/native/meta-kms-private.h" +#include "backends/native/meta-kms-utils.h" #include "backends/native/meta-thread-private.h" #include "meta-default-modes.h" @@ -1394,12 +1395,13 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, GError **error) { CrtcFrame *crtc_frame = user_data; - MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc); + MetaKmsCrtc *crtc = crtc_frame->crtc; + MetaKmsDevice *device = meta_kms_crtc_get_device (crtc); MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); g_autoptr (MetaKmsFeedback) feedback = NULL; uint64_t timer_value; ssize_t ret; - int64_t dispatch_time_us = 0; + int64_t dispatch_time_us = 0, update_done_time_us, interval_us; if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE)) dispatch_time_us = g_get_monotonic_time (); @@ -1425,22 +1427,35 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, g_steal_pointer (&crtc_frame->pending_update), META_KMS_UPDATE_FLAG_NONE); + update_done_time_us = g_get_monotonic_time (); + /* Calculate how long after the planned start of deadline dispatch it finished */ + interval_us = update_done_time_us - crtc_frame->deadline.expected_deadline_time_us; + if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE)) { - int64_t lateness_us, duration_us; + int64_t deadline_evasion_us, lateness_us, duration_us, vblank_delta_us; + deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc); lateness_us = dispatch_time_us - crtc_frame->deadline.expected_deadline_time_us; - duration_us = g_get_monotonic_time () - dispatch_time_us; + duration_us = update_done_time_us - dispatch_time_us; + vblank_delta_us = deadline_evasion_us - lateness_us - duration_us; meta_topic (META_DEBUG_KMS_DEADLINE, - "Deadline dispatch started %3"G_GINT64_FORMAT "µs %s and " - "completed %3"G_GINT64_FORMAT "µs after that.", + "Deadline evasion %3"G_GINT64_FORMAT "µs, " + "dispatch started %3"G_GINT64_FORMAT "µs %s and " + "completed %3"G_GINT64_FORMAT "µs after that, " + "%3"G_GINT64_FORMAT "µs %s start of vblank.", + deadline_evasion_us, ABS (lateness_us), lateness_us >= 0 ? "late" : "early", - duration_us); + duration_us, + ABS (vblank_delta_us), + vblank_delta_us >= 0 ? "before" : "after"); } + meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us); + if (meta_kms_feedback_did_pass (feedback)) crtc_frame->deadline.is_deadline_page_flip = TRUE; disarm_crtc_frame_deadline_timer (crtc_frame);