mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 04:22:05 +00:00
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>
This commit is contained in:
parent
4b0a10c562
commit
47d7bc7a13
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user