kms: Add way to preserve failed update

When we e.g. try to post an direct client buffer scanout update, it
might arbitrarily fail; when this happen we still will want to post the
rest of the update when we try again after having composited the primary
plane. To do this, add a way to preserve the metadata of an update if it
failed, only dropping the failed plane assignments. This involves
unlocking a previously locked MetaKmsUpdate, so that e.g. a new primary
plane can be assigned.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
Jonas Ådahl
2020-10-02 16:48:34 +02:00
committed by Marge Bot
parent 8876b217af
commit 3bad37482d
7 changed files with 98 additions and 13 deletions

View File

@ -1079,9 +1079,13 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
for (l = meta_kms_get_devices (kms); l; l = l->next) for (l = meta_kms_get_devices (kms); l; l = l->next)
{ {
MetaKmsDevice *kms_device = l->data; MetaKmsDevice *kms_device = l->data;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device); flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
on_kms_update_result (kms_feedback, renderer); on_kms_update_result (kms_feedback, renderer);
} }
} }

View File

@ -112,6 +112,8 @@ MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes,
void meta_kms_update_lock (MetaKmsUpdate *update); void meta_kms_update_lock (MetaKmsUpdate *update);
void meta_kms_update_unlock (MetaKmsUpdate *update);
gboolean meta_kms_update_is_locked (MetaKmsUpdate *update); gboolean meta_kms_update_is_locked (MetaKmsUpdate *update);
MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update);
@ -136,6 +138,9 @@ void meta_kms_update_get_custom_page_flip_func (MetaKmsUpdate *updat
MetaKmsCustomPageFlipFunc *custom_page_flip_func, MetaKmsCustomPageFlipFunc *custom_page_flip_func,
gpointer *custom_page_flip_user_data); gpointer *custom_page_flip_user_data);
void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update,
MetaKmsPlane *plane);
GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update);
void meta_kms_result_listener_notify (MetaKmsResultListener *listener, void meta_kms_result_listener_notify (MetaKmsResultListener *listener,

View File

@ -141,6 +141,26 @@ meta_kms_mode_set_free (MetaKmsModeSet *mode_set)
g_free (mode_set); g_free (mode_set);
} }
void
meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update,
MetaKmsPlane *plane)
{
GList *l;
for (l = update->plane_assignments; l; l = l->next)
{
MetaKmsPlaneAssignment *plane_assignment = l->data;
if (plane_assignment->plane == plane)
{
update->plane_assignments =
g_list_delete_link (update->plane_assignments, l);
meta_kms_plane_assignment_free (plane_assignment);
return;
}
}
}
MetaKmsPlaneAssignment * MetaKmsPlaneAssignment *
meta_kms_update_assign_plane (MetaKmsUpdate *update, meta_kms_update_assign_plane (MetaKmsUpdate *update,
MetaKmsCrtc *crtc, MetaKmsCrtc *crtc,
@ -469,6 +489,12 @@ meta_kms_update_lock (MetaKmsUpdate *update)
update->is_locked = TRUE; update->is_locked = TRUE;
} }
void
meta_kms_update_unlock (MetaKmsUpdate *update)
{
update->is_locked = FALSE;
}
gboolean gboolean
meta_kms_update_is_locked (MetaKmsUpdate *update) meta_kms_update_is_locked (MetaKmsUpdate *update)
{ {

View File

@ -177,6 +177,13 @@ struct _MetaKms
G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
static void
meta_kms_add_pending_update (MetaKms *kms,
MetaKmsUpdate *update)
{
kms->pending_updates = g_list_prepend (kms->pending_updates, update);
}
MetaKmsUpdate * MetaKmsUpdate *
meta_kms_ensure_pending_update (MetaKms *kms, meta_kms_ensure_pending_update (MetaKms *kms,
MetaKmsDevice *device) MetaKmsDevice *device)
@ -188,7 +195,7 @@ meta_kms_ensure_pending_update (MetaKms *kms,
return update; return update;
update = meta_kms_update_new (device); update = meta_kms_update_new (device);
kms->pending_updates = g_list_prepend (kms->pending_updates, update); meta_kms_add_pending_update (kms, update);
return update; return update;
} }
@ -246,8 +253,9 @@ meta_kms_process_update_in_impl (MetaKmsImpl *impl,
} }
MetaKmsFeedback * MetaKmsFeedback *
meta_kms_post_pending_update_sync (MetaKms *kms, meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device) MetaKmsDevice *device,
MetaKmsUpdateFlag flags)
{ {
MetaKmsUpdate *update; MetaKmsUpdate *update;
MetaKmsFeedback *feedback; MetaKmsFeedback *feedback;
@ -270,6 +278,27 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
result_listeners = meta_kms_update_take_result_listeners (update); result_listeners = meta_kms_update_take_result_listeners (update);
if (feedback->error &&
flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)
{
GList *l;
meta_kms_update_unlock (update);
for (l = feedback->failed_planes; l; l = l->next)
{
MetaKmsPlane *plane = l->data;
meta_kms_update_drop_plane_assignment (update, plane);
}
meta_kms_add_pending_update (kms, update);
}
else
{
meta_kms_update_free (update);
}
for (l = result_listeners; l; l = l->next) for (l = result_listeners; l; l = l->next)
{ {
MetaKmsResultListener *listener = l->data; MetaKmsResultListener *listener = l->data;
@ -279,8 +308,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
} }
g_list_free (result_listeners); g_list_free (result_listeners);
meta_kms_update_free (update);
return feedback; return feedback;
} }

View File

@ -25,6 +25,12 @@
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/native/meta-kms-types.h" #include "backends/native/meta-kms-types.h"
typedef enum _MetaKmsUpdateFlag
{
META_KMS_UPDATE_FLAG_NONE = 0,
META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR = 1 << 0,
} MetaKmsUpdateFlag;
#define META_TYPE_KMS (meta_kms_get_type ()) #define META_TYPE_KMS (meta_kms_get_type ())
G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject) G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject)
@ -34,8 +40,9 @@ MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms,
MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms,
MetaKmsDevice *device); MetaKmsDevice *device);
MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device); MetaKmsDevice *device,
MetaKmsUpdateFlag flags);
void meta_kms_discard_pending_page_flips (MetaKms *kms); void meta_kms_discard_pending_page_flips (MetaKms *kms);

View File

@ -145,12 +145,16 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaGpuKms *gpu_kms = l->data; MetaGpuKms *gpu_kms = l->data;
MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
MetaKmsUpdate *kms_update; MetaKmsUpdate *kms_update;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms, kms_device); kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update); meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device); flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
if (meta_kms_feedback_get_result (kms_feedback) != if (meta_kms_feedback_get_result (kms_feedback) !=
META_KMS_FEEDBACK_PASSED) META_KMS_FEEDBACK_PASSED)
{ {
@ -423,6 +427,7 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
MetaKmsDevice *kms_device; MetaKmsDevice *kms_device;
MetaKmsUpdate *kms_update; MetaKmsUpdate *kms_update;
g_autofree char *gamma_ramp_string = NULL; g_autofree char *gamma_ramp_string = NULL;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
@ -434,7 +439,8 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s", g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s",
meta_crtc_get_id (crtc), gamma_ramp_string); meta_crtc_get_id (crtc), gamma_ramp_string);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device); flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{ {
g_warning ("Failed to set CRTC gamma: %s", g_warning ("Failed to set CRTC gamma: %s",

View File

@ -1877,6 +1877,7 @@ unset_disabled_crtcs (MetaBackend *backend,
meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu));
GList *k; GList *k;
gboolean did_mode_set = FALSE; gboolean did_mode_set = FALSE;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
@ -1896,7 +1897,10 @@ unset_disabled_crtcs (MetaBackend *backend,
if (!did_mode_set) if (!did_mode_set)
continue; continue;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device); flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
if (meta_kms_feedback_get_result (kms_feedback) != if (meta_kms_feedback_get_result (kms_feedback) !=
META_KMS_FEEDBACK_PASSED) META_KMS_FEEDBACK_PASSED)
{ {
@ -1938,6 +1942,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
MetaDrmBufferGbm *buffer_gbm; MetaDrmBufferGbm *buffer_gbm;
MetaKmsCrtc *kms_crtc; MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device; MetaKmsDevice *kms_device;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
@ -2006,7 +2011,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
"Onscreen (post pending update)"); "Onscreen (post pending update)");
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc); kms_device = meta_kms_crtc_get_device (kms_crtc);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{ {
const GError *error = meta_kms_feedback_get_error (kms_feedback); const GError *error = meta_kms_feedback_get_error (kms_feedback);
@ -2176,6 +2183,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
MetaPowerSave power_save_mode; MetaPowerSave power_save_mode;
MetaKmsCrtc *kms_crtc; MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device; MetaKmsDevice *kms_device;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
@ -2199,7 +2207,9 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc); kms_device = meta_kms_crtc_get_device (kms_crtc);
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device);
flags = META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED) if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
{ {
const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback); const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback);