[mutter] backends/kms: Implement privacy screen handling and setting
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] backends/kms: Implement privacy screen handling and setting
- Date: Tue, 25 Jan 2022 08:10:39 +0000 (UTC)
commit 47d7bc7a132ce60a6922221550cad4c0645be2a5
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Mon Mar 22 01:27:39 2021 +0100
backends/kms: Implement privacy screen handling and setting
Privacy screen events on connector are handled as notification events
that won't cause any monitors reconfiguration but will emit monitors
changed on DBus, so that the new value can be fetched.
We monitor the hardware state so that we can also handle the case of
devices with hw-switchers only.
In case a software state is available it means we can also support
changing the state, and if so expose the state as unlocked.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1952>
src/backends/native/meta-kms-connector-private.h | 2 +
src/backends/native/meta-kms-connector.c | 128 +++++++++++++++++++++-
src/backends/native/meta-kms-connector.h | 3 +
src/backends/native/meta-kms-impl-device-atomic.c | 16 +++
src/backends/native/meta-kms-impl-device-simple.c | 16 +++
src/backends/native/meta-kms-types.h | 1 +
src/backends/native/meta-kms-update-private.h | 5 +
src/backends/native/meta-kms-update.c | 15 +++
src/backends/native/meta-kms-update.h | 4 +
src/backends/native/meta-monitor-manager-native.c | 66 +++++++++++
src/backends/native/meta-output-kms.c | 48 ++++++++
src/backends/native/meta-renderer-native.c | 1 +
12 files changed, 302 insertions(+), 3 deletions(-)
---
diff --git a/src/backends/native/meta-kms-connector-private.h
b/src/backends/native/meta-kms-connector-private.h
index 77f9e476a0..a9201f3f4c 100644
--- a/src/backends/native/meta-kms-connector-private.h
+++ b/src/backends/native/meta-kms-connector-private.h
@@ -29,6 +29,8 @@ typedef enum _MetaKmsConnectorProp
META_KMS_CONNECTOR_PROP_UNDERSCAN,
META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER,
META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_SW_STATE,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_HW_STATE,
META_KMS_CONNECTOR_N_PROPS
} MetaKmsConnectorProp;
diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c
index 4f1b38da59..b317cf935b 100644
--- a/src/backends/native/meta-kms-connector.c
+++ b/src/backends/native/meta-kms-connector.c
@@ -19,6 +19,7 @@
#include "config.h"
+#include "backends/meta-output.h"
#include "backends/native/meta-kms-connector.h"
#include "backends/native/meta-kms-connector-private.h"
@@ -59,6 +60,14 @@ struct _MetaKmsConnector
G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT)
+typedef enum _MetaKmsPrivacyScreenHwState
+{
+ META_KMS_PRIVACY_SCREEN_HW_STATE_DISABLED,
+ META_KMS_PRIVACY_SCREEN_HW_STATE_ENABLED,
+ META_KMS_PRIVACY_SCREEN_HW_STATE_DISABLED_LOCKED,
+ META_KMS_PRIVACY_SCREEN_HW_STATE_ENABLED_LOCKED,
+} MetaKmsPrivacyScreenHwState;
+
MetaKmsDevice *
meta_kms_connector_get_device (MetaKmsConnector *connector)
{
@@ -132,6 +141,20 @@ meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector)
return underscan_prop_id != 0;
}
+gboolean
+meta_kms_connector_is_privacy_screen_supported (MetaKmsConnector *connector)
+{
+ return meta_kms_connector_get_prop_id (connector,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_HW_STATE) != 0;
+}
+
+static gboolean
+has_privacy_screen_software_toggle (MetaKmsConnector *connector)
+{
+ return meta_kms_connector_get_prop_id (connector,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_SW_STATE) != 0;
+}
+
static void
sync_fd_held (MetaKmsConnector *connector,
MetaKmsImplDevice *impl_device)
@@ -181,9 +204,44 @@ set_panel_orientation (MetaKmsConnectorState *state,
}
}
+static void
+set_privacy_screen (MetaKmsConnectorState *state,
+ MetaKmsConnector *connector,
+ drmModePropertyPtr prop,
+ uint64_t value)
+{
+ if (!meta_kms_connector_is_privacy_screen_supported (connector))
+ return;
+
+ switch (value)
+ {
+ case META_KMS_PRIVACY_SCREEN_HW_STATE_DISABLED:
+ state->privacy_screen_state = META_PRIVACY_SCREEN_DISABLED;
+ break;
+ case META_KMS_PRIVACY_SCREEN_HW_STATE_DISABLED_LOCKED:
+ state->privacy_screen_state = META_PRIVACY_SCREEN_DISABLED;
+ state->privacy_screen_state |= META_PRIVACY_SCREEN_LOCKED;
+ break;
+ case META_KMS_PRIVACY_SCREEN_HW_STATE_ENABLED:
+ state->privacy_screen_state = META_PRIVACY_SCREEN_ENABLED;
+ break;
+ case META_KMS_PRIVACY_SCREEN_HW_STATE_ENABLED_LOCKED:
+ state->privacy_screen_state = META_PRIVACY_SCREEN_ENABLED;
+ state->privacy_screen_state |= META_PRIVACY_SCREEN_LOCKED;
+ break;
+ default:
+ state->privacy_screen_state = META_PRIVACY_SCREEN_DISABLED;
+ g_warning ("Unknown privacy screen state: %" G_GUINT64_FORMAT, value);
+ }
+
+ if (!has_privacy_screen_software_toggle (connector))
+ state->privacy_screen_state |= META_PRIVACY_SCREEN_LOCKED;
+}
+
static void
state_set_properties (MetaKmsConnectorState *state,
MetaKmsImplDevice *impl_device,
+ MetaKmsConnector *connector,
drmModeConnector *drm_connector)
{
int fd;
@@ -216,6 +274,10 @@ state_set_properties (MetaKmsConnectorState *state,
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
strcmp (prop->name, "non-desktop") == 0)
state->non_desktop = drm_connector->prop_values[i];
+ else if (prop->prop_id == meta_kms_connector_get_prop_id (connector,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_HW_STATE))
+ set_privacy_screen (state, connector, prop,
+ drm_connector->prop_values[i]);
drmModeFreeProperty (prop);
}
@@ -554,9 +616,25 @@ meta_kms_connector_state_changes (MetaKmsConnectorState *state,
if (!kms_modes_equal (state->modes, new_state->modes))
return META_KMS_UPDATE_CHANGE_FULL;
+ if (state->privacy_screen_state != new_state->privacy_screen_state)
+ return META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN;
+
return META_KMS_UPDATE_CHANGE_NONE;
}
+static void
+meta_kms_connector_update_state_changes (MetaKmsConnector *connector,
+ MetaKmsUpdateChanges changes,
+ MetaKmsConnectorState *new_state)
+{
+ MetaKmsConnectorState *current_state = connector->current_state;
+
+ g_return_if_fail (changes != META_KMS_UPDATE_CHANGE_FULL);
+
+ if (changes & META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN)
+ current_state->privacy_screen_state = new_state->privacy_screen_state;
+}
+
static MetaKmsUpdateChanges
meta_kms_connector_read_state (MetaKmsConnector *connector,
MetaKmsImplDevice *impl_device,
@@ -593,7 +671,7 @@ meta_kms_connector_read_state (MetaKmsConnector *connector,
state_set_blobs (state, connector, impl_device, drm_connector);
- state_set_properties (state, impl_device, drm_connector);
+ state_set_properties (state, impl_device, connector, drm_connector);
state->subpixel_order =
drm_subpixel_order_to_cogl_subpixel_order (drm_connector->subpixel);
@@ -615,14 +693,18 @@ meta_kms_connector_read_state (MetaKmsConnector *connector,
else
connector_changes = meta_kms_connector_state_changes (current_state, state);
- if (connector_changes == META_KMS_UPDATE_CHANGE_NONE)
+ changes |= connector_changes;
+
+ if (!(changes & META_KMS_UPDATE_CHANGE_FULL))
{
+ meta_kms_connector_update_state_changes (connector,
+ connector_changes,
+ state);
connector->current_state = g_steal_pointer (¤t_state);
}
else
{
connector->current_state = g_steal_pointer (&state);
- changes |= connector_changes;
}
out:
@@ -686,6 +768,36 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector,
}
}
+ if (has_privacy_screen_software_toggle (connector))
+ {
+ GList *connector_updates;
+
+ connector_updates = meta_kms_update_get_connector_updates (update);
+ for (l = connector_updates; l; l = l->next)
+ {
+ MetaKmsConnectorUpdate *connector_update = l->data;
+
+ if (connector_update->connector != connector)
+ continue;
+
+ if (connector_update->privacy_screen.has_update &&
+ !(current_state->privacy_screen_state &
+ META_PRIVACY_SCREEN_LOCKED))
+ {
+ if (connector_update->privacy_screen.is_enabled)
+ {
+ current_state->privacy_screen_state =
+ META_PRIVACY_SCREEN_ENABLED;
+ }
+ else
+ {
+ current_state->privacy_screen_state =
+ META_PRIVACY_SCREEN_DISABLED;
+ }
+ }
+ }
+ }
+
impl_device = meta_kms_device_get_impl_device (connector->device);
sync_fd_held (connector, impl_device);
}
@@ -724,6 +836,16 @@ init_properties (MetaKmsConnector *connector,
.name = "underscan vborder",
.type = DRM_MODE_PROP_RANGE,
},
+ [META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_SW_STATE] =
+ {
+ .name = "privacy-screen sw-state",
+ .type = DRM_MODE_PROP_ENUM,
+ },
+ [META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_HW_STATE] =
+ {
+ .name = "privacy-screen hw-state",
+ .type = DRM_MODE_PROP_ENUM,
+ },
}
};
diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h
index a3a7136c5a..397753b433 100644
--- a/src/backends/native/meta-kms-connector.h
+++ b/src/backends/native/meta-kms-connector.h
@@ -49,6 +49,7 @@ typedef struct _MetaKmsConnectorState
gboolean has_scaling;
gboolean non_desktop;
+ MetaPrivacyScreenState privacy_screen_state;
CoglSubpixelOrder subpixel_order;
@@ -74,4 +75,6 @@ const MetaKmsConnectorState * meta_kms_connector_get_current_state (MetaKmsConne
gboolean meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector);
+gboolean meta_kms_connector_is_privacy_screen_supported (MetaKmsConnector *connector);
+
#endif /* META_KMS_CONNECTOR_H */
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c
b/src/backends/native/meta-kms-impl-device-atomic.c
index bcb41e8adb..bf1abf5727 100644
--- a/src/backends/native/meta-kms-impl-device-atomic.c
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
@@ -196,6 +196,22 @@ process_connector_update (MetaKmsImplDevice *impl_device,
return FALSE;
}
+ if (connector_update->privacy_screen.has_update)
+ {
+ meta_topic (META_DEBUG_KMS,
+ "[atomic] Toggling privacy screen to %d on connector %u (%s)",
+ connector_update->privacy_screen.is_enabled,
+ meta_kms_connector_get_id (connector),
+ meta_kms_impl_device_get_path (impl_device));
+
+ if (!add_connector_property (impl_device,
+ connector, req,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_SW_STATE,
+ connector_update->privacy_screen.is_enabled,
+ error))
+ return FALSE;
+ }
+
return TRUE;
}
diff --git a/src/backends/native/meta-kms-impl-device-simple.c
b/src/backends/native/meta-kms-impl-device-simple.c
index 5017d86bf0..e201e80fbd 100644
--- a/src/backends/native/meta-kms-impl-device-simple.c
+++ b/src/backends/native/meta-kms-impl-device-simple.c
@@ -260,6 +260,22 @@ process_connector_update (MetaKmsImplDevice *impl_device,
return FALSE;
}
+ if (connector_update->privacy_screen.has_update)
+ {
+ meta_topic (META_DEBUG_KMS,
+ "[simple] Toggling privacy screen to %d on connector %u (%s)",
+ connector_update->privacy_screen.is_enabled,
+ meta_kms_connector_get_id (connector),
+ meta_kms_impl_device_get_path (impl_device));
+
+ if (!set_connector_property (impl_device,
+ connector,
+ META_KMS_CONNECTOR_PROP_PRIVACY_SCREEN_SW_STATE,
+ connector_update->privacy_screen.is_enabled,
+ error))
+ return FALSE;
+ }
+
return TRUE;
}
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h
index 5e9a4b3e7e..4ba2003a5e 100644
--- a/src/backends/native/meta-kms-types.h
+++ b/src/backends/native/meta-kms-types.h
@@ -69,6 +69,7 @@ typedef enum _MetaKmsUpdateChanges
META_KMS_UPDATE_CHANGE_NONE = 0,
META_KMS_UPDATE_CHANGE_GAMMA = 1 << 0,
META_KMS_UPDATE_CHANGE_NO_DEVICES = 1 << 1,
+ META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN = 1 << 2,
META_KMS_UPDATE_CHANGE_FULL = -1,
} MetaKmsUpdateChanges;
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index c375f7ead8..44c950ea22 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -77,6 +77,11 @@ typedef struct _MetaKmsConnectorUpdate
uint64_t hborder;
uint64_t vborder;
} underscanning;
+
+ struct {
+ gboolean has_update;
+ gboolean is_enabled;
+ } privacy_screen;
} MetaKmsConnectorUpdate;
typedef struct _MetaKmsPageFlipListener
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index f61e740d74..18999210fb 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -349,6 +349,21 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
connector_update->underscanning.is_active = FALSE;
}
+void
+meta_kms_update_set_privacy_screen (MetaKmsUpdate *update,
+ MetaKmsConnector *connector,
+ gboolean enabled)
+{
+ MetaKmsConnectorUpdate *connector_update;
+
+ g_assert (meta_kms_connector_get_device (connector) == update->device);
+ g_assert (!update->power_save);
+
+ connector_update = ensure_connector_update (update, connector);
+ connector_update->privacy_screen.has_update = TRUE;
+ connector_update->privacy_screen.is_enabled = enabled;
+}
+
void
meta_kms_update_set_power_save (MetaKmsUpdate *update)
{
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
index 89f4146efd..0c3028b52a 100644
--- a/src/backends/native/meta-kms-update.h
+++ b/src/backends/native/meta-kms-update.h
@@ -101,6 +101,10 @@ void meta_kms_update_set_underscanning (MetaKmsUpdate *update,
void meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
MetaKmsConnector *connector);
+void meta_kms_update_set_privacy_screen (MetaKmsUpdate *update,
+ MetaKmsConnector *connector,
+ gboolean enabled);
+
void meta_kms_update_set_power_save (MetaKmsUpdate *update);
void meta_kms_update_mode_set (MetaKmsUpdate *update,
diff --git a/src/backends/native/meta-monitor-manager-native.c
b/src/backends/native/meta-monitor-manager-native.c
index bfa04b719c..4cd02468fe 100644
--- a/src/backends/native/meta-monitor-manager-native.c
+++ b/src/backends/native/meta-monitor-manager-native.c
@@ -37,6 +37,8 @@
#include "backends/meta-monitor.h"
#include "config.h"
+#include "backends/native/meta-kms-device.h"
+#include "backends/native/meta-kms-types.h"
#include "backends/native/meta-monitor-manager-native.h"
#include <drm.h>
@@ -518,6 +520,9 @@ on_kms_resources_changed (MetaKms *kms,
return;
}
+ if (changes == META_KMS_UPDATE_CHANGE_PRIVACY_SCREEN)
+ return;
+
handle_hotplug_event (manager);
}
@@ -696,6 +701,65 @@ 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)
+ return;
+
+ on_kms_resources_changed (kms,
+ META_KMS_UPDATE_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 MetaVirtualMonitor *
meta_monitor_manager_native_create_virtual_monitor (MetaMonitorManager *manager,
const MetaVirtualMonitorInfo *info,
@@ -819,6 +883,8 @@ 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 4359b1161c..fb658f29d4 100644
--- a/src/backends/native/meta-output-kms.c
+++ b/src/backends/native/meta-output-kms.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "backends/meta-crtc.h"
+#include "backends/native/meta-kms.h"
#include "backends/native/meta-kms-connector.h"
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-mode.h"
@@ -96,6 +97,47 @@ meta_output_kms_set_underscan (MetaOutputKms *output_kms,
}
}
+static MetaPrivacyScreenState
+meta_output_kms_get_privacy_screen_state (MetaOutput *output)
+{
+ MetaOutputKms *output_kms = META_OUTPUT_KMS (output);
+ const MetaKmsConnectorState *connector_state;
+
+ connector_state =
+ meta_kms_connector_get_current_state (output_kms->kms_connector);
+
+ return connector_state->privacy_screen_state;
+}
+
+static gboolean
+meta_output_kms_set_privacy_screen_enabled (MetaOutput *output,
+ gboolean enabled,
+ GError **error)
+{
+ MetaGpu *gpu;
+ MetaKms *kms;
+ MetaKmsDevice *kms_device;
+ MetaKmsUpdate *kms_update;
+ MetaOutputKms *output_kms = META_OUTPUT_KMS (output);
+ MetaKmsConnector *connector = meta_output_kms_get_kms_connector (output_kms);
+
+ if (!meta_kms_connector_is_privacy_screen_supported (connector))
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "No privacy screen support");
+ 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);
+
+ return TRUE;
+}
+
uint32_t
meta_output_kms_get_connector_id (MetaOutputKms *output_kms)
{
@@ -425,6 +467,12 @@ static void
meta_output_kms_class_init (MetaOutputKmsClass *klass)
{
MetaOutputNativeClass *output_native_class = META_OUTPUT_NATIVE_CLASS (klass);
+ MetaOutputClass *output_class = META_OUTPUT_CLASS (klass);
+
+ output_class->get_privacy_screen_state =
+ meta_output_kms_get_privacy_screen_state;
+ output_class->set_privacy_screen_enabled =
+ meta_output_kms_set_privacy_screen_enabled;
output_native_class->read_edid = meta_output_kms_read_edid;
}
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index be7bbce1fd..d63ac23bf2 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -58,6 +58,7 @@
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms.h"
#include "backends/native/meta-onscreen-native.h"
+#include "backends/native/meta-output-kms.h"
#include "backends/native/meta-render-device-gbm.h"
#include "backends/native/meta-render-device-surfaceless.h"
#include "backends/native/meta-renderer-native-private.h"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]