From 0aa4bab53931a0906dfabed1095afbd2ae705177 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Fri, 17 Jul 2020 13:38:55 -0700 Subject: [PATCH] kms: Use custom page flip function when retrying failed flips When using its EGLStream-based presentation path with the proprietary NVIDIA driver, mutter will use a different function to process page flips - custom_egl_stream_page_flip. If that fails due to an EBUSY error, it will attempt to retry the flip. However, when retrying, it unconditionally uses the libdrm-based path. In practice, this causes a segfault when attempting to access plane_assignments->fb_id, since plane_assignments will be NULL in the EGLStream case. The issue can be reproduced reliably by VT-switching away from GNOME and back again while an EGL application is running. This patch has mutter also use the custom page flip function when retrying the failed flip. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1375 --- src/backends/native/meta-kms-impl-simple.c | 46 ++++++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/backends/native/meta-kms-impl-simple.c b/src/backends/native/meta-kms-impl-simple.c index b5c7bb742..5aa7adc08 100644 --- a/src/backends/native/meta-kms-impl-simple.c +++ b/src/backends/native/meta-kms-impl-simple.c @@ -319,6 +319,8 @@ typedef struct _RetryPageFlipData MetaKmsPageFlipData *page_flip_data; float refresh_rate; uint64_t retry_time_us; + MetaKmsCustomPageFlipFunc custom_page_flip_func; + gpointer custom_page_flip_user_data; } RetryPageFlipData; static void @@ -370,6 +372,7 @@ retry_page_flips (gpointer user_data) int fd; int ret; MetaKmsPageFlipData *page_flip_data; + MetaKmsCustomPageFlipFunc custom_page_flip_func; if (is_timestamp_earlier_than (now_us, retry_page_flip_data->retry_time_us)) @@ -378,12 +381,22 @@ retry_page_flips (gpointer user_data) continue; } - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModePageFlip (fd, - meta_kms_crtc_get_id (crtc), - retry_page_flip_data->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - retry_page_flip_data->page_flip_data); + custom_page_flip_func = retry_page_flip_data->custom_page_flip_func; + if (custom_page_flip_func) + { + ret = custom_page_flip_func (retry_page_flip_data->custom_page_flip_user_data, + retry_page_flip_data->page_flip_data); + } + else + { + fd = meta_kms_impl_device_get_fd (impl_device); + ret = drmModePageFlip (fd, + meta_kms_crtc_get_id (crtc), + retry_page_flip_data->fb_id, + DRM_MODE_PAGE_FLIP_EVENT, + retry_page_flip_data->page_flip_data); + } + if (ret == -EBUSY) { float refresh_rate; @@ -451,11 +464,13 @@ retry_page_flips (gpointer user_data) } static void -schedule_retry_page_flip (MetaKmsImplSimple *impl_simple, - MetaKmsCrtc *crtc, - uint32_t fb_id, - float refresh_rate, - MetaKmsPageFlipData *page_flip_data) +schedule_retry_page_flip (MetaKmsImplSimple *impl_simple, + MetaKmsCrtc *crtc, + uint32_t fb_id, + float refresh_rate, + MetaKmsPageFlipData *page_flip_data, + MetaKmsCustomPageFlipFunc custom_page_flip_func, + gpointer custom_page_flip_user_data) { RetryPageFlipData *retry_page_flip_data; uint64_t now_us; @@ -471,6 +486,8 @@ schedule_retry_page_flip (MetaKmsImplSimple *impl_simple, .page_flip_data = meta_kms_page_flip_data_ref (page_flip_data), .refresh_rate = refresh_rate, .retry_time_us = retry_time_us, + .custom_page_flip_func = custom_page_flip_func, + .custom_page_flip_user_data = custom_page_flip_user_data, }; if (!impl_simple->retry_page_flips_source) @@ -677,9 +694,12 @@ process_page_flip (MetaKmsImpl *impl, refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); schedule_retry_page_flip (impl_simple, crtc, - plane_assignment->fb_id, + plane_assignment ? + plane_assignment->fb_id : 0, refresh_rate, - page_flip_data); + page_flip_data, + custom_page_flip_func, + page_flip->custom_page_flip_user_data); } else {