diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index 43f974f47..781d719b8 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -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); } } diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 8f4f780cb..2a1675836 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -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, diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index 5815bc666..197ebc3bd 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -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) { diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 18b45506e..15fc6f2ef 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -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; } diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 97876d370..792279e84 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -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); diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 16e3423de..f3881862f 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -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", diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 018e9ca53..c2b98920b 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -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);