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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1154>
This commit is contained in:
Dor Askayo 2024-02-02 21:47:37 +02:00 committed by Marge Bot
parent 2a3fc9b830
commit a74fbecbd6

View File

@ -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;