kms/impl-device: Track dispatch duration in crtc_frame_deadline_dispatch
And take it into account in meta_kms_crtc_get_deadline_evasion. This uses the same fundamental approach as clutter frame clock scheduling: Measure the deadline timer dispatch duration, keep track of the longest duration, and set the timer to fire such that the longest measured dispatch duration would result in it completing shortly before start of vblank. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3612 v2: * Move DEADLINE_EVASION_CONSTANT_US addition from meta_kms_crtc_determine_deadline to meta_kms_crtc_get_deadline_evasion. * Calculate how long before start of vblank dispatch completed for debug output in crtc_frame_deadline_dispatch. * Shorten over-long lines in crtc_frame_deadline_dispatch. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934> Signed-off-by: Mingi Sung <sungmg@saltyming.net> (cherry picked from commit 88e7f353)
This commit is contained in:
parent
b5dffcdc67
commit
e3bbee2630
3 changed files with 76 additions and 13 deletions
|
@ -28,8 +28,7 @@
|
||||||
#include "backends/native/meta-kms-update-private.h"
|
#include "backends/native/meta-kms-update-private.h"
|
||||||
#include "backends/native/meta-kms-utils.h"
|
#include "backends/native/meta-kms-utils.h"
|
||||||
|
|
||||||
#define DEADLINE_EVASION_US 800
|
#define DEADLINE_EVASION_CONSTANT_US 200
|
||||||
#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000
|
|
||||||
|
|
||||||
#define MINIMUM_REFRESH_RATE 30.f
|
#define MINIMUM_REFRESH_RATE 30.f
|
||||||
|
|
||||||
|
@ -50,6 +49,10 @@ struct _MetaKmsCrtc
|
||||||
MetaKmsCrtcState current_state;
|
MetaKmsCrtcState current_state;
|
||||||
|
|
||||||
MetaKmsCrtcPropTable prop_table;
|
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)
|
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
|
gboolean
|
||||||
meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
||||||
int64_t *out_next_deadline_us,
|
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);
|
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);
|
vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode);
|
||||||
next_deadline_us = next_presentation_us - (vblank_duration_us +
|
next_deadline_us = next_presentation_us - (vblank_duration_us +
|
||||||
|
@ -623,11 +654,25 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
||||||
return TRUE;
|
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
|
int64_t
|
||||||
meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc)
|
meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc)
|
||||||
{
|
{
|
||||||
if (meta_is_topic_enabled (META_DEBUG_KMS))
|
return MAX (crtc->shortterm_max_dispatch_duration_us,
|
||||||
return DEADLINE_EVASION_WITH_KMS_TOPIC_US;
|
crtc->deadline_evasion_us) + DEADLINE_EVASION_CONSTANT_US;
|
||||||
else
|
|
||||||
return DEADLINE_EVASION_US;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,4 +66,7 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc);
|
||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc);
|
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);
|
int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc);
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "backends/native/meta-kms-plane-private.h"
|
#include "backends/native/meta-kms-plane-private.h"
|
||||||
#include "backends/native/meta-kms-plane.h"
|
#include "backends/native/meta-kms-plane.h"
|
||||||
#include "backends/native/meta-kms-private.h"
|
#include "backends/native/meta-kms-private.h"
|
||||||
|
#include "backends/native/meta-kms-utils.h"
|
||||||
#include "backends/native/meta-thread-private.h"
|
#include "backends/native/meta-thread-private.h"
|
||||||
|
|
||||||
#include "meta-default-modes.h"
|
#include "meta-default-modes.h"
|
||||||
|
@ -1394,12 +1395,13 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
CrtcFrame *crtc_frame = user_data;
|
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);
|
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||||
g_autoptr (MetaKmsFeedback) feedback = NULL;
|
g_autoptr (MetaKmsFeedback) feedback = NULL;
|
||||||
uint64_t timer_value;
|
uint64_t timer_value;
|
||||||
ssize_t ret;
|
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))
|
if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
||||||
dispatch_time_us = g_get_monotonic_time ();
|
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),
|
g_steal_pointer (&crtc_frame->pending_update),
|
||||||
META_KMS_UPDATE_FLAG_NONE);
|
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))
|
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 -
|
lateness_us = dispatch_time_us -
|
||||||
crtc_frame->deadline.expected_deadline_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,
|
meta_topic (META_DEBUG_KMS_DEADLINE,
|
||||||
"Deadline dispatch started %3"G_GINT64_FORMAT "µs %s and "
|
"Deadline evasion %3"G_GINT64_FORMAT "µs, "
|
||||||
"completed %3"G_GINT64_FORMAT "µs after that.",
|
"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),
|
ABS (lateness_us),
|
||||||
lateness_us >= 0 ? "late" : "early",
|
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))
|
if (meta_kms_feedback_did_pass (feedback))
|
||||||
crtc_frame->deadline.is_deadline_page_flip = TRUE;
|
crtc_frame->deadline.is_deadline_page_flip = TRUE;
|
||||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||||
|
|
Loading…
Reference in a new issue