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
This commit is contained in:
Erik Kurzinger 2020-07-17 13:38:55 -07:00
parent 224db78409
commit 0aa4bab539

View File

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