mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
kms/update: Make power saving an update wide change
This makes "power save" (i.e. when you make a monitor go into power save mode, or make it come out of power save mode), a per device action when turning on power saving (power save being set to 'off'), and implicitly handled when turning off power saving (power save being set to 'on') when doing a mode set. This is needed as with atomic mode setting, the configuration of DPMS (Display Power Management Signaling), is replaced by directly turning on or off CRTCs, and via the CRTC drm properties. Thus in order to handle both with a common API, make that API high level enough for both cases being covered. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
parent
3ec5418104
commit
5f6aee3419
@ -227,30 +227,11 @@ meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms,
|
||||
{
|
||||
const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
|
||||
MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode);
|
||||
MetaBackend *backend = meta_gpu_get_backend (gpu);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaPowerSave power_save;
|
||||
uint64_t dpms_state;
|
||||
GList *l;
|
||||
|
||||
kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms);
|
||||
|
||||
g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s",
|
||||
meta_crtc_get_id (crtc), meta_kms_mode_get_name (kms_mode));
|
||||
|
||||
power_save = meta_monitor_manager_get_power_save_mode (monitor_manager);
|
||||
g_warn_if_fail (power_save == META_POWER_SAVE_ON);
|
||||
|
||||
dpms_state = meta_power_save_to_dpms_state (power_save);
|
||||
for (l = connectors; l; l = l->next)
|
||||
{
|
||||
MetaKmsConnector *kms_connector = l->data;
|
||||
|
||||
meta_kms_update_set_dpms_state (kms_update,
|
||||
kms_connector,
|
||||
dpms_state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -143,35 +143,6 @@ meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
|
||||
return timespec_to_nanoseconds (&ts);
|
||||
}
|
||||
|
||||
void
|
||||
meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
|
||||
uint64_t state,
|
||||
MetaKmsUpdate *kms_update)
|
||||
{
|
||||
MetaGpu *gpu = META_GPU (gpu_kms);
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (state != DRM_MODE_DPMS_ON);
|
||||
|
||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
meta_output_kms_set_power_save_mode (META_OUTPUT_KMS (output),
|
||||
state, kms_update);
|
||||
}
|
||||
|
||||
/* Turn off CRTCs for DPMS */
|
||||
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data);
|
||||
|
||||
meta_kms_update_mode_set (kms_update,
|
||||
meta_crtc_kms_get_kms_crtc (crtc_kms),
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
|
@ -66,6 +66,65 @@ G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple,
|
||||
static void
|
||||
flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple);
|
||||
|
||||
static gboolean
|
||||
get_connector_property (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsConnector *connector,
|
||||
MetaKmsConnectorProp prop,
|
||||
uint64_t *value,
|
||||
GError **error)
|
||||
{
|
||||
uint32_t prop_id;
|
||||
int fd;
|
||||
drmModeConnector *drm_connector;
|
||||
int i;
|
||||
gboolean found;
|
||||
|
||||
prop_id = meta_kms_connector_get_prop_id (connector, prop);
|
||||
if (!prop_id)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
"Property (%s) not found on connector %u",
|
||||
meta_kms_connector_get_prop_name (connector, prop),
|
||||
meta_kms_connector_get_id (connector));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fd = meta_kms_impl_device_get_fd (impl_device);
|
||||
|
||||
drm_connector = drmModeGetConnector (fd,
|
||||
meta_kms_connector_get_id (connector));
|
||||
if (!drm_connector)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
|
||||
"Failed to get connector %u resources: %s",
|
||||
meta_kms_connector_get_id (connector),
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
found = FALSE;
|
||||
for (i = 0; i < drm_connector->count_props; i++)
|
||||
{
|
||||
if (drm_connector->props[i] == prop_id)
|
||||
{
|
||||
*value = drm_connector->prop_values[i];
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFreeConnector (drm_connector);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
"Connector property %u not found", prop_id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_connector_property (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsConnector *connector,
|
||||
@ -107,6 +166,32 @@ set_connector_property (MetaKmsImplDevice *impl_device,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_power_save (MetaKmsImplDevice *impl_device,
|
||||
GError **error)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next)
|
||||
{
|
||||
MetaKmsConnector *connector = l->data;
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[simple] Setting DPMS of connector %u (%s) to OFF",
|
||||
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_DPMS,
|
||||
DRM_MODE_DPMS_OFF,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_connector_update (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdate *update,
|
||||
@ -116,23 +201,6 @@ process_connector_update (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsConnectorUpdate *connector_update = update_entry;
|
||||
MetaKmsConnector *connector = connector_update->connector;
|
||||
|
||||
if (connector_update->dpms.has_update)
|
||||
{
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[simple] Setting DPMS on connector %u (%s) to %"
|
||||
G_GUINT64_FORMAT,
|
||||
meta_kms_connector_get_id (connector),
|
||||
meta_kms_impl_device_get_path (impl_device),
|
||||
connector_update->dpms.state);
|
||||
|
||||
if (!set_connector_property (impl_device,
|
||||
connector,
|
||||
META_KMS_CONNECTOR_PROP_DPMS,
|
||||
connector_update->dpms.state,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (connector_update->underscanning.has_update &&
|
||||
connector_update->underscanning.is_active)
|
||||
{
|
||||
@ -288,6 +356,7 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
||||
if (mode_set->mode)
|
||||
{
|
||||
MetaDrmBuffer *buffer;
|
||||
GList *l;
|
||||
|
||||
drm_mode = g_alloca (sizeof *drm_mode);
|
||||
*drm_mode = *meta_kms_mode_get_drm_mode (mode_set->mode);
|
||||
@ -321,6 +390,34 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
||||
buffer = plane_assignment->buffer;
|
||||
fb_id = meta_drm_buffer_get_fb_id (buffer);
|
||||
|
||||
for (l = mode_set->connectors; l; l = l->next)
|
||||
{
|
||||
MetaKmsConnector *connector = l->data;
|
||||
uint64_t dpms_value;
|
||||
|
||||
if (!get_connector_property (impl_device,
|
||||
connector,
|
||||
META_KMS_CONNECTOR_PROP_DPMS,
|
||||
&dpms_value,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (dpms_value != DRM_MODE_DPMS_ON)
|
||||
{
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[simple] Setting DPMS of connector %u (%s) to ON",
|
||||
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_DPMS,
|
||||
DRM_MODE_DPMS_ON,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[simple] Setting mode of CRTC %u (%s) to %s",
|
||||
meta_kms_crtc_get_id (crtc),
|
||||
@ -1256,12 +1353,12 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
||||
"[simple] Processing update %" G_GUINT64_FORMAT,
|
||||
meta_kms_update_get_sequence_number (update));
|
||||
|
||||
if (!process_entries (impl_device,
|
||||
update,
|
||||
meta_kms_update_get_connector_updates (update),
|
||||
process_connector_update,
|
||||
&error))
|
||||
goto err;
|
||||
if (meta_kms_update_is_power_save (update))
|
||||
{
|
||||
if (!process_power_save (impl_device, &error))
|
||||
goto err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!process_entries (impl_device,
|
||||
update,
|
||||
@ -1270,6 +1367,13 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
||||
&error))
|
||||
goto err;
|
||||
|
||||
if (!process_entries (impl_device,
|
||||
update,
|
||||
meta_kms_update_get_connector_updates (update),
|
||||
process_connector_update,
|
||||
&error))
|
||||
goto err;
|
||||
|
||||
if (!process_entries (impl_device,
|
||||
update,
|
||||
meta_kms_update_get_crtc_gammas (update),
|
||||
@ -1283,6 +1387,7 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
||||
if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, &error))
|
||||
goto err;
|
||||
|
||||
out:
|
||||
return meta_kms_feedback_new_passed (failed_planes);
|
||||
|
||||
err:
|
||||
|
@ -120,6 +120,15 @@ meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device)
|
||||
return g_list_copy (priv->planes);
|
||||
}
|
||||
|
||||
GList *
|
||||
meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
|
||||
return priv->connectors;
|
||||
}
|
||||
|
||||
const MetaKmsDeviceCaps *
|
||||
meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
|
@ -78,6 +78,8 @@ GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device);
|
||||
|
||||
GList * meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device);
|
||||
|
||||
GList * meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device);
|
||||
|
||||
const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device);
|
||||
|
||||
GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device);
|
||||
|
@ -70,11 +70,6 @@ typedef struct _MetaKmsConnectorUpdate
|
||||
uint64_t hborder;
|
||||
uint64_t vborder;
|
||||
} underscanning;
|
||||
|
||||
struct {
|
||||
gboolean has_update;
|
||||
uint64_t state;
|
||||
} dpms;
|
||||
} MetaKmsConnectorUpdate;
|
||||
|
||||
typedef struct _MetaKmsPageFlipListener
|
||||
@ -127,6 +122,8 @@ GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update);
|
||||
|
||||
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
|
||||
|
||||
gboolean meta_kms_update_is_power_save (MetaKmsUpdate *update);
|
||||
|
||||
void meta_kms_update_get_custom_page_flip_func (MetaKmsUpdate *update,
|
||||
MetaKmsCustomPageFlipFunc *custom_page_flip_func,
|
||||
gpointer *custom_page_flip_user_data);
|
||||
|
@ -35,7 +35,8 @@ struct _MetaKmsUpdate
|
||||
gboolean is_locked;
|
||||
uint64_t sequence_number;
|
||||
|
||||
MetaPowerSave power_save;
|
||||
gboolean power_save;
|
||||
|
||||
GList *mode_sets;
|
||||
GList *plane_assignments;
|
||||
GList *connector_updates;
|
||||
@ -188,6 +189,7 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
|
||||
g_assert (!update->power_save);
|
||||
g_assert (meta_kms_plane_get_device (plane) == update->device);
|
||||
g_assert (meta_kms_plane_get_plane_type (plane) !=
|
||||
META_KMS_PLANE_TYPE_PRIMARY ||
|
||||
@ -226,6 +228,7 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update,
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
|
||||
g_assert (meta_kms_plane_get_device (plane) == update->device);
|
||||
g_assert (!update->power_save);
|
||||
|
||||
plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1);
|
||||
*plane_assignment = (MetaKmsPlaneAssignment) {
|
||||
@ -251,6 +254,7 @@ meta_kms_update_mode_set (MetaKmsUpdate *update,
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
|
||||
g_assert (!update->power_save);
|
||||
|
||||
mode_set = g_new0 (MetaKmsModeSet, 1);
|
||||
*mode_set = (MetaKmsModeSet) {
|
||||
@ -296,6 +300,7 @@ meta_kms_update_set_underscanning (MetaKmsUpdate *update,
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (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->underscanning.has_update = TRUE;
|
||||
@ -312,6 +317,7 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (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->underscanning.has_update = TRUE;
|
||||
@ -319,18 +325,15 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_update_set_dpms_state (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector,
|
||||
uint64_t state)
|
||||
meta_kms_update_set_power_save (MetaKmsUpdate *update)
|
||||
{
|
||||
MetaKmsConnectorUpdate *connector_update;
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (meta_kms_connector_get_device (connector) == update->device);
|
||||
g_assert (!update->mode_sets);
|
||||
g_assert (!update->plane_assignments);
|
||||
g_assert (!update->connector_updates);
|
||||
g_assert (!update->crtc_gammas);
|
||||
|
||||
connector_update = ensure_connector_update (update, connector);
|
||||
connector_update->dpms.has_update = TRUE;
|
||||
connector_update->dpms.state = state;
|
||||
update->power_save = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -375,6 +378,7 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
|
||||
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
|
||||
g_assert (!update->power_save);
|
||||
|
||||
gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue);
|
||||
|
||||
@ -409,6 +413,7 @@ meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_assert (!meta_kms_update_is_locked (update));
|
||||
g_assert (!update->power_save);
|
||||
|
||||
update->custom_page_flip_func = func;
|
||||
update->custom_page_flip_user_data = user_data;
|
||||
@ -523,6 +528,12 @@ meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
|
||||
return update->crtc_gammas;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_kms_update_is_power_save (MetaKmsUpdate *update)
|
||||
{
|
||||
return update->power_save;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_update_lock (MetaKmsUpdate *update)
|
||||
{
|
||||
|
@ -95,9 +95,7 @@ void meta_kms_update_set_underscanning (MetaKmsUpdate *update,
|
||||
void meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector);
|
||||
|
||||
void meta_kms_update_set_dpms_state (MetaKmsUpdate *update,
|
||||
MetaKmsConnector *connector,
|
||||
uint64_t state);
|
||||
void meta_kms_update_set_power_save (MetaKmsUpdate *update);
|
||||
|
||||
void meta_kms_update_mode_set (MetaKmsUpdate *update,
|
||||
MetaKmsCrtc *crtc,
|
||||
|
@ -143,7 +143,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
||||
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
||||
MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
||||
uint64_t state;
|
||||
GList *l;
|
||||
|
||||
switch (mode)
|
||||
@ -158,8 +157,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
break;
|
||||
}
|
||||
|
||||
state = meta_power_save_to_dpms_state (mode);
|
||||
|
||||
for (l = meta_backend_get_gpus (backend); l; l = l->next)
|
||||
{
|
||||
MetaGpuKms *gpu_kms = l->data;
|
||||
@ -169,7 +166,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
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);
|
||||
meta_kms_update_set_power_save (kms_update);
|
||||
|
||||
flags = META_KMS_UPDATE_FLAG_NONE;
|
||||
kms_feedback = meta_kms_post_pending_update_sync (kms,
|
||||
@ -178,7 +175,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
if (meta_kms_feedback_get_result (kms_feedback) !=
|
||||
META_KMS_FEEDBACK_PASSED)
|
||||
{
|
||||
g_warning ("Failed to set DPMS: %s",
|
||||
g_warning ("Failed to enter power saving mode: %s",
|
||||
meta_kms_feedback_get_error (kms_feedback)->message);
|
||||
}
|
||||
}
|
||||
|
@ -102,20 +102,6 @@ meta_output_kms_get_connector_id (MetaOutputKms *output_kms)
|
||||
return meta_kms_connector_get_id (output_kms->kms_connector);
|
||||
}
|
||||
|
||||
void
|
||||
meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms,
|
||||
uint64_t dpms_state,
|
||||
MetaKmsUpdate *kms_update)
|
||||
{
|
||||
g_debug ("Setting DPMS state of connector %s to %" G_GUINT64_FORMAT,
|
||||
meta_kms_connector_get_name (output_kms->kms_connector),
|
||||
dpms_state);
|
||||
|
||||
meta_kms_update_set_dpms_state (kms_update,
|
||||
output_kms->kms_connector,
|
||||
dpms_state);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_output_kms_can_clone (MetaOutputKms *output_kms,
|
||||
MetaOutputKms *other_output_kms)
|
||||
|
Loading…
Reference in New Issue
Block a user