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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2340>
This commit is contained in:
Jonas Ådahl 2022-03-17 10:33:23 +01:00 committed by Marge Bot
parent 1b0aa0b3ad
commit 81b28a1d97
11 changed files with 98 additions and 116 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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) \

View File

@ -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);
}

View File

@ -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 =

View File

@ -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;
}