From 81b28a1d975f2511d8800faa2c187703eb66ce63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 17 Mar 2022 10:33:23 +0100 Subject: [PATCH] kms: Notify about privacy screen changes via predictions When we change the privacy screen, we added a result listener to the KMS update object to notify the upper layer about the privacy screen state change. This was slightly awkward as one might have changed the state multiple times for a single update, thus it was necessary to remove any old result listeners to an update before adding a new one. Doing this will not be possible when updates are fully async and managed by the KMS impl device. To handle this, instead make the post-commit prediction notify about changes that happens in response to a successfully committed update. We already predicted the new privacy screen state, so the necessary change was to plumb the actual change into a callback which emits the signal if there actually was a privacy screen change. This will then be communicated via the same signal listener that already listens to the 'resources-changed' signal. Part-of: --- src/backends/meta-monitor-manager-private.h | 3 - src/backends/meta-monitor-manager.c | 37 +++-------- .../native/meta-kms-connector-private.h | 4 +- src/backends/native/meta-kms-connector.c | 15 ++++- src/backends/native/meta-kms-crtc-private.h | 4 +- src/backends/native/meta-kms-crtc.c | 6 +- src/backends/native/meta-kms-impl-device.c | 45 +++++++++++-- src/backends/native/meta-kms-private.h | 3 + src/backends/native/meta-kms.c | 9 ++- .../native/meta-monitor-manager-native.c | 65 ------------------- src/backends/native/meta-output-kms.c | 23 +++++-- 11 files changed, 98 insertions(+), 116 deletions(-) diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index edf7e4501..e14ab207f 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -246,9 +246,6 @@ struct _MetaMonitorManagerClass unsigned short *green, unsigned short *blue); - gboolean (* set_privacy_screen_enabled) (MetaMonitorManager *manager, - gboolean enabled); - void (* tiled_monitor_added) (MetaMonitorManager *manager, MetaMonitor *monitor); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 6d9b7f416..4230fcd23 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -1009,17 +1009,21 @@ experimental_features_changed (MetaSettings *settings, } static gboolean -meta_monitor_manager_real_set_privacy_screen_enabled (MetaMonitorManager *manager, - gboolean enabled) +ensure_privacy_screen_settings (MetaMonitorManager *manager) { + MetaSettings *settings = meta_backend_get_settings (manager->backend); + gboolean privacy_screen_enabled; GList *l; + privacy_screen_enabled = meta_settings_is_privacy_screen_enabled (settings); for (l = manager->monitors; l; l = l->next) { - g_autoptr (GError) error = NULL; MetaMonitor *monitor = l->data; + g_autoptr (GError) error = NULL; - if (!meta_monitor_set_privacy_screen_enabled (monitor, enabled, &error)) + if (!meta_monitor_set_privacy_screen_enabled (monitor, + privacy_screen_enabled, + &error)) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) continue; @@ -1033,25 +1037,6 @@ meta_monitor_manager_real_set_privacy_screen_enabled (MetaMonitorManager *manage return TRUE; } -static gboolean -set_privacy_screen_enabled (MetaMonitorManager *manager, - gboolean enabled) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->set_privacy_screen_enabled (manager, enabled); -} - -static gboolean -ensure_monitors_settings (MetaMonitorManager *manager) -{ - MetaSettings *settings = meta_backend_get_settings (manager->backend); - - return set_privacy_screen_enabled ( - manager, meta_settings_is_privacy_screen_enabled (settings)); -} - static MetaPrivacyScreenState get_global_privacy_screen_state (MetaMonitorManager *manager) { @@ -1098,7 +1083,7 @@ static void apply_privacy_screen_settings (MetaMonitorManager *manager) { if (privacy_screen_needs_update (manager) && - ensure_monitors_settings (manager)) + ensure_privacy_screen_settings (manager)) { manager->privacy_screen_change_state = META_PRIVACY_SCREEN_CHANGE_STATE_PENDING_SETTING; @@ -1396,8 +1381,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) klass->read_edid = meta_monitor_manager_real_read_edid; klass->read_current_state = meta_monitor_manager_real_read_current_state; - klass->set_privacy_screen_enabled = - meta_monitor_manager_real_set_privacy_screen_enabled; signals[MONITORS_CHANGED] = g_signal_new ("monitors-changed", @@ -3619,7 +3602,7 @@ meta_monitor_manager_rebuild (MetaMonitorManager *manager, meta_monitor_manager_notify_monitors_changed (manager); - ensure_monitors_settings (manager); + ensure_privacy_screen_settings (manager); g_list_free_full (old_logical_monitors, g_object_unref); } diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h index e5aa3e332..e1d9b44cd 100644 --- a/src/backends/native/meta-kms-connector-private.h +++ b/src/backends/native/meta-kms-connector-private.h @@ -106,8 +106,8 @@ MetaKmsResourceChanges meta_kms_connector_update_state (MetaKmsConnector *connec void meta_kms_connector_disable (MetaKmsConnector *connector); -void meta_kms_connector_predict_state (MetaKmsConnector *connector, - MetaKmsUpdate *update); +MetaKmsResourceChanges meta_kms_connector_predict_state (MetaKmsConnector *connector, + MetaKmsUpdate *update); MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device, drmModeConnector *drm_connector, diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c index 8d77b2115..724f96e36 100644 --- a/src/backends/native/meta-kms-connector.c +++ b/src/backends/native/meta-kms-connector.c @@ -758,7 +758,7 @@ meta_kms_connector_disable (MetaKmsConnector *connector) current_state->current_crtc_id = 0; } -void +MetaKmsResourceChanges meta_kms_connector_predict_state (MetaKmsConnector *connector, MetaKmsUpdate *update) { @@ -766,10 +766,11 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector, MetaKmsConnectorState *current_state; GList *mode_sets; GList *l; + MetaKmsResourceChanges changes = META_KMS_RESOURCE_CHANGE_NONE; current_state = connector->current_state; if (!current_state) - return; + return META_KMS_RESOURCE_CHANGE_NONE; mode_sets = meta_kms_update_get_mode_sets (update); for (l = mode_sets; l; l = l->next) @@ -812,11 +813,19 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector, { if (connector_update->privacy_screen.is_enabled) { + if (current_state->privacy_screen_state != + META_PRIVACY_SCREEN_ENABLED) + changes |= META_KMS_RESOURCE_CHANGE_PRIVACY_SCREEN; + current_state->privacy_screen_state = META_PRIVACY_SCREEN_ENABLED; } else { + if (current_state->privacy_screen_state != + META_PRIVACY_SCREEN_DISABLED) + changes |= META_KMS_RESOURCE_CHANGE_PRIVACY_SCREEN; + current_state->privacy_screen_state = META_PRIVACY_SCREEN_DISABLED; } @@ -826,6 +835,8 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector, impl_device = meta_kms_device_get_impl_device (connector->device); sync_fd_held (connector, impl_device); + + return changes; } static void diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h index baf5f4099..79a5f0fe6 100644 --- a/src/backends/native/meta-kms-crtc-private.h +++ b/src/backends/native/meta-kms-crtc-private.h @@ -42,8 +42,8 @@ MetaKmsResourceChanges meta_kms_crtc_update_state (MetaKmsCrtc *crtc); void meta_kms_crtc_disable (MetaKmsCrtc *crtc); -void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, - MetaKmsUpdate *update); +MetaKmsResourceChanges meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, + MetaKmsUpdate *update); uint32_t meta_kms_crtc_get_prop_id (MetaKmsCrtc *crtc, MetaKmsCrtcProp prop); diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index ee9e19d2d..707dfd4b8 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -278,13 +278,14 @@ meta_kms_crtc_disable (MetaKmsCrtc *crtc) crtc->current_state.drm_mode = (drmModeModeInfo) { 0 }; } -void +MetaKmsResourceChanges meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, MetaKmsUpdate *update) { GList *mode_sets; GList *crtc_gammas; GList *l; + MetaKmsResourceChanges changes = META_KMS_RESOURCE_CHANGE_NONE; mode_sets = meta_kms_update_get_mode_sets (update); for (l = mode_sets; l; l = l->next) @@ -337,8 +338,11 @@ meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, crtc->current_state.gamma.blue = g_memdup2 (gamma->blue, gamma->size * sizeof (uint16_t)); + changes |= META_KMS_RESOURCE_CHANGE_GAMMA; break; } + + return changes; } static void diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index 5ef04abc3..653a96f71 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -914,17 +914,30 @@ err: return META_KMS_RESOURCE_CHANGE_FULL; } -static void +static MetaKmsResourceChanges meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update) { MetaKmsImplDevicePrivate *priv = meta_kms_impl_device_get_instance_private (impl_device); + MetaKmsResourceChanges changes = META_KMS_RESOURCE_CHANGE_NONE; + GList *l; - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_predict_state, - update); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_predict_state, - update); + for (l = priv->crtcs; l; l = l->next) + { + MetaKmsCrtc *crtc = l->data; + + changes |= meta_kms_crtc_predict_state (crtc, update); + } + + for (l = priv->connectors; l; l = l->next) + { + MetaKmsConnector *connector = l->data; + + changes |= meta_kms_connector_predict_state (connector, update); + } + + return changes; } void @@ -944,14 +957,26 @@ meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device) return meta_device_file_get_fd (priv->device_file); } +static void +emit_resources_changed_callback (MetaKms *kms, + gpointer user_data) +{ + MetaKmsResourceChanges changes = GPOINTER_TO_UINT (user_data); + + meta_kms_emit_resources_changed (kms, changes); +} + MetaKmsFeedback * meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, MetaKmsUpdateFlag flags) { + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); MetaKmsFeedback *feedback; g_autoptr (GError) error = NULL; + MetaKmsResourceChanges changes = META_KMS_RESOURCE_CHANGE_NONE; if (!ensure_device_file (impl_device, &error)) return meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error)); @@ -959,9 +984,17 @@ meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, meta_kms_impl_device_hold_fd (impl_device); feedback = klass->process_update (impl_device, update, flags); if (!(flags & META_KMS_UPDATE_FLAG_TEST_ONLY)) - meta_kms_impl_device_predict_states (impl_device, update); + changes = meta_kms_impl_device_predict_states (impl_device, update); meta_kms_impl_device_unhold_fd (impl_device); + if (changes != META_KMS_RESOURCE_CHANGE_NONE) + { + MetaKms *kms = meta_kms_device_get_kms (priv->device); + + meta_kms_queue_callback (kms, + emit_resources_changed_callback, + GUINT_TO_POINTER (changes), NULL); + } return feedback; } diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h index 0c383834b..615e2bdf7 100644 --- a/src/backends/native/meta-kms-private.h +++ b/src/backends/native/meta-kms-private.h @@ -61,6 +61,9 @@ gboolean meta_kms_in_impl_task (MetaKms *kms); gboolean meta_kms_is_waiting_for_impl_task (MetaKms *kms); +void meta_kms_emit_resources_changed (MetaKms *kms, + MetaKmsResourceChanges changes); + #define meta_assert_in_kms_impl(kms) \ g_assert (meta_kms_in_impl_task (kms)) #define meta_assert_not_in_kms_impl(kms) \ diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 521690a19..21be532a2 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -651,7 +651,7 @@ handle_hotplug_event (MetaKms *kms, changes |= meta_kms_update_states_sync (kms, udev_device); if (changes != META_KMS_RESOURCE_CHANGE_NONE) - g_signal_emit (kms, signals[RESOURCES_CHANGED], 0, changes); + meta_kms_emit_resources_changed (kms, changes); } void @@ -799,3 +799,10 @@ meta_kms_class_init (MetaKmsClass *klass) G_TYPE_NONE, 1, META_TYPE_KMS_RESOURCE_CHANGES); } + +void +meta_kms_emit_resources_changed (MetaKms *kms, + MetaKmsResourceChanges changes) +{ + g_signal_emit (kms, signals[RESOURCES_CHANGED], 0, changes); +} diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c index 4ea5ac602..90fae7d42 100644 --- a/src/backends/native/meta-monitor-manager-native.c +++ b/src/backends/native/meta-monitor-manager-native.c @@ -736,69 +736,6 @@ allocate_virtual_monitor_id (MetaMonitorManagerNative *manager_native) } } -static void -on_kms_privacy_screen_update_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data) -{ - MetaMonitorManager *manager = user_data; - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); - - if (meta_kms_feedback_get_result (kms_feedback) == META_KMS_FEEDBACK_FAILED) - { - manager->privacy_screen_change_state = - META_PRIVACY_SCREEN_CHANGE_STATE_NONE; - return; - } - - on_kms_resources_changed (kms, - META_KMS_RESOURCE_CHANGE_PRIVACY_SCREEN, - manager); -} - -static gboolean -meta_monitor_manager_native_set_privacy_screen_enabled (MetaMonitorManager *manager, - gboolean enabled) -{ - MetaMonitorManagerClass *manager_class; - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); - gboolean any_update = FALSE; - GList *l; - - manager_class = - META_MONITOR_MANAGER_CLASS (meta_monitor_manager_native_parent_class); - - if (!manager_class->set_privacy_screen_enabled (manager, enabled)) - return FALSE; - - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdate *kms_update; - - kms_update = meta_kms_get_pending_update (kms, kms_device); - - if (kms_update) - { - meta_kms_update_remove_result_listeners ( - kms_update, on_kms_privacy_screen_update_result, manager); - meta_kms_update_add_result_listener ( - kms_update, on_kms_privacy_screen_update_result, manager); - any_update = TRUE; - } - } - - if (any_update) - { - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - - clutter_stage_schedule_update (stage); - } - - return TRUE; -} - static gboolean rebuild_virtual_idle_cb (gpointer user_data) { @@ -956,8 +893,6 @@ meta_monitor_manager_native_class_init (MetaMonitorManagerNativeClass *klass) meta_monitor_manager_native_get_crtc_gamma; manager_class->set_crtc_gamma = meta_monitor_manager_native_set_crtc_gamma; - manager_class->set_privacy_screen_enabled = - meta_monitor_manager_native_set_privacy_screen_enabled; manager_class->is_transform_handled = meta_monitor_manager_native_is_transform_handled; manager_class->calculate_monitor_mode_scale = diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index f60d5ad0d..108567cb1 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -114,12 +114,15 @@ meta_output_kms_set_privacy_screen_enabled (MetaOutput *output, gboolean enabled, GError **error) { - MetaGpu *gpu; - MetaKms *kms; - MetaKmsDevice *kms_device; - MetaKmsUpdate *kms_update; + MetaGpu *gpu = meta_output_get_gpu (output); + MetaBackend *backend = meta_gpu_get_backend (gpu); + MetaRenderer *renderer = meta_backend_get_renderer (backend); + MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); + MetaKms *kms = meta_kms_device_get_kms (kms_device); MetaOutputKms *output_kms = META_OUTPUT_KMS (output); MetaKmsConnector *connector = meta_output_kms_get_kms_connector (output_kms); + MetaKmsUpdate *kms_update; + MetaCrtc *crtc; if (!meta_kms_connector_is_privacy_screen_supported (connector)) { @@ -128,13 +131,19 @@ meta_output_kms_set_privacy_screen_enabled (MetaOutput *output, return FALSE; } - gpu = meta_output_get_gpu (META_OUTPUT (output_kms)); - kms_device = meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); - kms = meta_kms_device_get_kms (kms_device); kms_update = meta_kms_ensure_pending_update (kms, kms_device); meta_kms_update_set_privacy_screen (kms_update, connector, enabled); + crtc = meta_output_get_assigned_crtc (output); + if (crtc) + { + MetaRendererView *view; + + view = meta_renderer_get_view_for_crtc (renderer, crtc); + clutter_stage_view_schedule_update (CLUTTER_STAGE_VIEW (view)); + } + return TRUE; }