From a74fbecbd6ff426b60d07b280214b0ac6cbb088e Mon Sep 17 00:00:00 2001 From: Dor Askayo Date: Fri, 2 Feb 2024 21:47:37 +0200 Subject: [PATCH] kms/crtc: Calculate CRTC deadline for VRR Use a sufficiently low refresh rate to calculate the CRTC deadline when variable refresh rate is enabled. This is done to avoid cursor updates from driving the monitor refresh rate. It's not great solution and is sometimes not enough, but it avoids stutter in the main content as a result of cursor movement in most cases. The unfortunate downside of this approach is that cursor movement would usually only update with the main content and would not be smooth when the main content updates are not frequent enough. A better solution may use an approach similar to LFC (Low Framerate Compensation) to insert cursor-only updates between updates of the main content, but achieving adequate results with an approach of this nature requires more research and experimentation. Part-of: --- src/backends/native/meta-kms-crtc.c | 64 ++++++++++++++++++----------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index a06d6cd37..5b044402b 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -31,6 +31,8 @@ #define DEADLINE_EVASION_US 800 #define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000 +#define MINIMUM_REFRESH_RATE 30.f + typedef struct _MetaKmsCrtcPropTable { MetaKmsProp props[META_KMS_CRTC_N_PROPS]; @@ -550,9 +552,6 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, int ret; int64_t next_presentation_us; int64_t next_deadline_us; - drmModeModeInfo *drm_mode; - int64_t vblank_duration_us; - int64_t deadline_evasion_us; if (!crtc->current_state.is_drm_mode_valid) { @@ -578,30 +577,45 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, return FALSE; } - drm_mode = &crtc->current_state.drm_mode; - next_presentation_us = - s2us (vblank.reply.tval_sec) + vblank.reply.tval_usec + 0.5 + - G_USEC_PER_SEC / meta_calculate_drm_mode_refresh_rate (drm_mode); - - /* - * 1 - * time per pixel = ----------------- - * Pixel clock (Hz) - * - * number of pixels = vdisplay * htotal - * - * time spent scanning out = time per pixel * number of pixels - * - */ - - if (meta_is_topic_enabled (META_DEBUG_KMS)) - deadline_evasion_us = DEADLINE_EVASION_WITH_KMS_TOPIC_US; + if (crtc->current_state.vrr_enabled) + { + next_presentation_us = 0; + next_deadline_us = + s2us (vblank.reply.tval_sec) + vblank.reply.tval_usec + 0.5 + + G_USEC_PER_SEC / MINIMUM_REFRESH_RATE; + } else - deadline_evasion_us = DEADLINE_EVASION_US; + { + drmModeModeInfo *drm_mode; + int64_t vblank_duration_us; + int64_t deadline_evasion_us; - vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode); - next_deadline_us = next_presentation_us - (vblank_duration_us + - deadline_evasion_us); + drm_mode = &crtc->current_state.drm_mode; + + next_presentation_us = + s2us (vblank.reply.tval_sec) + vblank.reply.tval_usec + 0.5 + + G_USEC_PER_SEC / meta_calculate_drm_mode_refresh_rate (drm_mode); + + /* + * 1 + * time per pixel = ----------------- + * Pixel clock (Hz) + * + * number of pixels = vdisplay * htotal + * + * time spent scanning out = time per pixel * number of pixels + * + */ + + if (meta_is_topic_enabled (META_DEBUG_KMS)) + deadline_evasion_us = DEADLINE_EVASION_WITH_KMS_TOPIC_US; + else + deadline_evasion_us = DEADLINE_EVASION_US; + + vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode); + next_deadline_us = next_presentation_us - (vblank_duration_us + + deadline_evasion_us); + } *out_next_presentation_us = next_presentation_us; *out_next_deadline_us = next_deadline_us;