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)
{
MetaKmsDevice *kms_device = l->data;
MetaKmsUpdateFlag flags;
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);
}
}

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_unlock (MetaKmsUpdate *update);
gboolean meta_kms_update_is_locked (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,
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);
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);
}
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 *
meta_kms_update_assign_plane (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
@ -469,6 +489,12 @@ meta_kms_update_lock (MetaKmsUpdate *update)
update->is_locked = TRUE;
}
void
meta_kms_update_unlock (MetaKmsUpdate *update)
{
update->is_locked = FALSE;
}
gboolean
meta_kms_update_is_locked (MetaKmsUpdate *update)
{

View File

@ -177,6 +177,13 @@ struct _MetaKms
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 *
meta_kms_ensure_pending_update (MetaKms *kms,
MetaKmsDevice *device)
@ -188,7 +195,7 @@ meta_kms_ensure_pending_update (MetaKms *kms,
return update;
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;
}
@ -246,8 +253,9 @@ meta_kms_process_update_in_impl (MetaKmsImpl *impl,
}
MetaKmsFeedback *
meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device)
meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device,
MetaKmsUpdateFlag flags)
{
MetaKmsUpdate *update;
MetaKmsFeedback *feedback;
@ -270,6 +278,27 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
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)
{
MetaKmsResultListener *listener = l->data;
@ -279,8 +308,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
}
g_list_free (result_listeners);
meta_kms_update_free (update);
return feedback;
}

View File

@ -25,6 +25,12 @@
#include "backends/meta-backend-private.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 ())
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,
MetaKmsDevice *device);
MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device);
MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device,
MetaKmsUpdateFlag flags);
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;
MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
MetaKmsUpdate *kms_update;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
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) !=
META_KMS_FEEDBACK_PASSED)
{
@ -423,6 +427,7 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
MetaKmsDevice *kms_device;
MetaKmsUpdate *kms_update;
g_autofree char *gamma_ramp_string = NULL;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
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",
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)
{
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));
GList *k;
gboolean did_mode_set = FALSE;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
@ -1896,7 +1897,10 @@ unset_disabled_crtcs (MetaBackend *backend,
if (!did_mode_set)
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) !=
META_KMS_FEEDBACK_PASSED)
{
@ -1938,6 +1942,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
MetaDrmBufferGbm *buffer_gbm;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
@ -2006,7 +2011,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
"Onscreen (post pending update)");
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->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)
{
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;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
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_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)
{
const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback);