[mutter/cherry-pick-1d792087] kms: Gracefully handle page flipping direct scanouts failing
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/cherry-pick-1d792087] kms: Gracefully handle page flipping direct scanouts failing
- Date: Fri, 2 Jul 2021 16:51:13 +0000 (UTC)
commit b9684c7f24359e383f4b3577a439bf74782380a8
Author: Jonas Ådahl <jadahl gmail com>
Date: Thu Jul 1 19:45:03 2021 +0200
kms: Gracefully handle page flipping direct scanouts failing
When drmModePageFlip() or drmModeAtomicCommit() unexpectedly failed (e.g.
ENOSPC, which has been seen in the wild), this failure was not handled
very gracefully. The page flip listener for the scanout was left in the
MetaKmsUpdate, meaning when the primary plane composition was later page
flipped, two page flip listeners were added, one for the primary plane,
and one for the scanout. This caused the 'page-flipped' event to be
handled twice, the second time being fatal.
Handle this by making 'no-discard' listener flag be somewhat reversed,
and say 'drop-on-error', and then drop all 'drop-on-error' listeners
when a MetaKmsUpdate failed to be processed.
Also for a "preserve" flagged update, don't ever trigger "discard"
callbacks just yet, as preserved updates are used again for the primary
plane composition, in order to not miss e.g. CRTC gamma updates, or
cursor plane updates, which were added separately.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1809
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1910>
(cherry picked from commit 1d7920872d23946014afa67c753e7c512bf510d6)
src/backends/native/meta-kms-impl-device-atomic.c | 22 +++++++++++++---------
src/backends/native/meta-kms-impl-device-simple.c | 19 +++++++++++++------
src/backends/native/meta-kms-impl-device.c | 5 +++--
src/backends/native/meta-kms-impl-device.h | 7 +++++--
src/backends/native/meta-kms-impl.c | 7 ++++---
src/backends/native/meta-kms-impl.h | 5 +++--
src/backends/native/meta-kms-page-flip.c | 3 ---
src/backends/native/meta-kms-update-private.h | 2 ++
src/backends/native/meta-kms-update.c | 22 ++++++++++++++++++++++
src/backends/native/meta-kms-update.h | 2 +-
src/backends/native/meta-kms.c | 20 +++++++++++++++++---
src/backends/native/meta-onscreen-native.c | 2 +-
12 files changed, 84 insertions(+), 32 deletions(-)
---
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c
b/src/backends/native/meta-kms-impl-device-atomic.c
index d1f2e7b82f..4115b9b05d 100644
--- a/src/backends/native/meta-kms-impl-device-atomic.c
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
@@ -849,7 +849,8 @@ process_power_save (MetaKmsImplDevice *impl_device,
static MetaKmsFeedback *
meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
- MetaKmsUpdate *update)
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags)
{
GError *error = NULL;
GList *failed_planes = NULL;
@@ -973,14 +974,17 @@ commit:
err:
meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message);
- process_entries (impl_device,
- update,
- req,
- blob_ids,
- meta_kms_update_get_page_flip_listeners (update),
- error,
- discard_page_flip_listener,
- NULL);
+ if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR))
+ {
+ process_entries (impl_device,
+ update,
+ req,
+ blob_ids,
+ meta_kms_update_get_page_flip_listeners (update),
+ error,
+ discard_page_flip_listener,
+ NULL);
+ }
release_blob_ids (impl_device, blob_ids);
diff --git a/src/backends/native/meta-kms-impl-device-simple.c
b/src/backends/native/meta-kms-impl-device-simple.c
index 1519962b8e..4f9fe78845 100644
--- a/src/backends/native/meta-kms-impl-device-simple.c
+++ b/src/backends/native/meta-kms-impl-device-simple.c
@@ -1085,6 +1085,7 @@ static gboolean
maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
GList **failed_planes,
+ MetaKmsUpdateFlag flags,
GError **error)
{
g_autoptr (GList) page_flip_datas = NULL;
@@ -1122,7 +1123,8 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
*failed_planes = g_list_prepend (*failed_planes, plane_feedback);
}
- meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
+ if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR))
+ meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
goto err;
}
@@ -1131,11 +1133,14 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
return TRUE;
err:
- for (l = page_flip_datas; l; l = l->next)
+ if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR))
{
- MetaKmsPageFlipData *page_flip_data = l->data;
+ for (l = page_flip_datas; l; l = l->next)
+ {
+ MetaKmsPageFlipData *page_flip_data = l->data;
- meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
+ meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
+ }
}
g_list_free (page_flip_datas);
@@ -1375,7 +1380,8 @@ meta_kms_impl_device_simple_setup_drm_event_context (MetaKmsImplDevice *impl_dev
static MetaKmsFeedback *
meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
- MetaKmsUpdate *update)
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags)
{
GError *error = NULL;
GList *failed_planes = NULL;
@@ -1415,7 +1421,8 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
if (!process_plane_assignments (impl_device, update, &failed_planes, &error))
goto err;
- if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, &error))
+ if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, flags,
+ &error))
goto err;
out:
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index 9dc631b577..75920fe6b5 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -651,11 +651,12 @@ meta_kms_impl_device_leak_fd (MetaKmsImplDevice *impl_device)
MetaKmsFeedback *
meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device,
- MetaKmsUpdate *update)
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags)
{
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
- return klass->process_update (impl_device, update);
+ return klass->process_update (impl_device, update, flags);
}
void
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
index 6e8ec23787..913ba992f7 100644
--- a/src/backends/native/meta-kms-impl-device.h
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -29,6 +29,7 @@
#include "backends/native/meta-kms-page-flip-private.h"
#include "backends/native/meta-kms-types.h"
#include "backends/native/meta-kms-update.h"
+#include "backends/native/meta-kms.h"
typedef struct _MetaKmsDeviceCaps
{
@@ -64,7 +65,8 @@ struct _MetaKmsImplDeviceClass
void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device,
drmEventContext *drm_event_context);
MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device,
- MetaKmsUpdate *update);
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags);
void (* handle_page_flip_callback) (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data);
void (* discard_pending_page_flips) (MetaKmsImplDevice *impl_device);
@@ -132,7 +134,8 @@ void meta_kms_impl_device_reload_prop_values (MetaKmsImplDevice *impl_device,
...);
MetaKmsFeedback * meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device,
- MetaKmsUpdate *update);
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags);
void meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data);
diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c
index 036a0d783d..3a186209c6 100644
--- a/src/backends/native/meta-kms-impl.c
+++ b/src/backends/native/meta-kms-impl.c
@@ -78,8 +78,9 @@ meta_kms_impl_remove_impl_device (MetaKmsImpl *impl,
}
MetaKmsFeedback *
-meta_kms_impl_process_update (MetaKmsImpl *impl,
- MetaKmsUpdate *update)
+meta_kms_impl_process_update (MetaKmsImpl *impl,
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags)
{
MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl);
MetaKmsDevice *device;
@@ -90,7 +91,7 @@ meta_kms_impl_process_update (MetaKmsImpl *impl,
device = meta_kms_update_get_device (update);
impl_device = meta_kms_device_get_impl_device (device);
- return meta_kms_impl_device_process_update (impl_device, update);
+ return meta_kms_impl_device_process_update (impl_device, update, flags);
}
void
diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h
index 723a21cd2e..00cf5538d0 100644
--- a/src/backends/native/meta-kms-impl.h
+++ b/src/backends/native/meta-kms-impl.h
@@ -31,8 +31,9 @@ G_DECLARE_FINAL_TYPE (MetaKmsImpl, meta_kms_impl,
MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl);
-MetaKmsFeedback * meta_kms_impl_process_update (MetaKmsImpl *impl,
- MetaKmsUpdate *update);
+MetaKmsFeedback * meta_kms_impl_process_update (MetaKmsImpl *impl,
+ MetaKmsUpdate *update,
+ MetaKmsUpdateFlag flags);
void meta_kms_impl_add_impl_device (MetaKmsImpl *impl,
MetaKmsImplDevice *impl_device);
diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c
index 130fba06c9..817f4e7c8d 100644
--- a/src/backends/native/meta-kms-page-flip.c
+++ b/src/backends/native/meta-kms-page-flip.c
@@ -255,9 +255,6 @@ meta_kms_page_flip_data_discard (MetaKms *kms,
{
MetaKmsPageFlipClosure *closure = l->data;
- if (closure->flags & META_KMS_PAGE_FLIP_LISTENER_FLAG_NO_DISCARD)
- continue;
-
closure->vtable->discarded (page_flip_data->crtc,
closure->user_data,
page_flip_data->error);
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index 1954c7a782..22491ece2d 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -126,6 +126,8 @@ GList * meta_kms_update_get_mode_sets (MetaKmsUpdate *update);
GList * meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update);
+void meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update);
+
GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update);
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index 06d6d75155..be6eaefcc2 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -417,6 +417,28 @@ meta_kms_update_add_page_flip_listener (MetaKmsUpdate *upd
listener);
}
+void
+meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update)
+{
+ GList *l;
+
+ l = update->page_flip_listeners;
+ while (l)
+ {
+ MetaKmsPageFlipListener *listener = l->data;
+ GList *l_next = l->next;
+
+ if (listener->flags & META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR)
+ {
+ meta_kms_page_flip_listener_free (listener);
+ update->page_flip_listeners =
+ g_list_delete_link (update->page_flip_listeners, l);
+ }
+
+ l = l_next;
+ }
+}
+
void
meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update,
MetaKmsCustomPageFlipFunc func,
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
index 98fb8088f7..0c7707bbc4 100644
--- a/src/backends/native/meta-kms-update.h
+++ b/src/backends/native/meta-kms-update.h
@@ -46,7 +46,7 @@ typedef enum _MetaKmsAssignPlaneFlag
enum _MetaKmsPageFlipListenerFlag
{
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE = 0,
- META_KMS_PAGE_FLIP_LISTENER_FLAG_NO_DISCARD = 1 << 0,
+ META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR = 1 << 0,
};
struct _MetaKmsPageFlipListenerVtable
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 57bb88e5f7..edb6f29eec 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -239,15 +239,22 @@ meta_kms_take_pending_update (MetaKms *kms,
return NULL;
}
+typedef struct
+{
+ MetaKmsUpdate *update;
+ MetaKmsUpdateFlag flags;
+} PostUpdateData;
+
static gpointer
meta_kms_process_update_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
+ PostUpdateData *data = user_data;
+ MetaKmsUpdate *update = data->update;
MetaKmsFeedback *feedback;
- MetaKmsUpdate *update = user_data;
- feedback = meta_kms_impl_process_update (impl, update);
+ feedback = meta_kms_impl_process_update (impl, data->update, data->flags);
meta_kms_device_predict_states_in_impl (meta_kms_update_get_device (update),
update);
@@ -260,6 +267,7 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsUpdateFlag flags)
{
MetaKmsUpdate *update;
+ PostUpdateData data;
MetaKmsFeedback *feedback;
GList *result_listeners;
GList *l;
@@ -273,9 +281,13 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
meta_kms_update_lock (update);
+ data = (PostUpdateData) {
+ .update = update,
+ .flags = flags,
+ };
feedback = meta_kms_run_impl_task_sync (kms,
meta_kms_process_update_in_impl,
- update,
+ &data,
NULL);
result_listeners = meta_kms_update_take_result_listeners (update);
@@ -294,6 +306,8 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
meta_kms_update_drop_plane_assignment (update, plane);
}
+ meta_kms_update_drop_defunct_page_flip_listeners (update);
+
meta_kms_add_pending_update (kms, update);
}
else
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
index da75b03ec4..02cd5da2e8 100644
--- a/src/backends/native/meta-onscreen-native.c
+++ b/src/backends/native/meta-onscreen-native.c
@@ -1259,7 +1259,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
meta_onscreen_native_flip_crtc (onscreen,
onscreen_native->view,
onscreen_native->crtc,
- META_KMS_PAGE_FLIP_LISTENER_FLAG_NO_DISCARD);
+ META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR);
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]