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:
Jonas Ådahl 2020-10-21 17:38:44 +02:00 committed by Marge Bot
parent 3ec5418104
commit 5f6aee3419
10 changed files with 165 additions and 108 deletions

View File

@ -227,30 +227,11 @@ meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms,
{ {
const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode); 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); kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms);
g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s", g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s",
meta_crtc_get_id (crtc), meta_kms_mode_get_name (kms_mode)); 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 else
{ {

View File

@ -143,35 +143,6 @@ meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
return timespec_to_nanoseconds (&ts); 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 gboolean
meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms) meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms)
{ {

View File

@ -66,6 +66,65 @@ G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple,
static void static void
flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple); 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 static gboolean
set_connector_property (MetaKmsImplDevice *impl_device, set_connector_property (MetaKmsImplDevice *impl_device,
MetaKmsConnector *connector, MetaKmsConnector *connector,
@ -107,6 +166,32 @@ set_connector_property (MetaKmsImplDevice *impl_device,
return TRUE; 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 static gboolean
process_connector_update (MetaKmsImplDevice *impl_device, process_connector_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update, MetaKmsUpdate *update,
@ -116,23 +201,6 @@ process_connector_update (MetaKmsImplDevice *impl_device,
MetaKmsConnectorUpdate *connector_update = update_entry; MetaKmsConnectorUpdate *connector_update = update_entry;
MetaKmsConnector *connector = connector_update->connector; 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 && if (connector_update->underscanning.has_update &&
connector_update->underscanning.is_active) connector_update->underscanning.is_active)
{ {
@ -288,6 +356,7 @@ process_mode_set (MetaKmsImplDevice *impl_device,
if (mode_set->mode) if (mode_set->mode)
{ {
MetaDrmBuffer *buffer; MetaDrmBuffer *buffer;
GList *l;
drm_mode = g_alloca (sizeof *drm_mode); drm_mode = g_alloca (sizeof *drm_mode);
*drm_mode = *meta_kms_mode_get_drm_mode (mode_set->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; buffer = plane_assignment->buffer;
fb_id = meta_drm_buffer_get_fb_id (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, meta_topic (META_DEBUG_KMS,
"[simple] Setting mode of CRTC %u (%s) to %s", "[simple] Setting mode of CRTC %u (%s) to %s",
meta_kms_crtc_get_id (crtc), 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, "[simple] Processing update %" G_GUINT64_FORMAT,
meta_kms_update_get_sequence_number (update)); meta_kms_update_get_sequence_number (update));
if (!process_entries (impl_device, if (meta_kms_update_is_power_save (update))
update, {
meta_kms_update_get_connector_updates (update), if (!process_power_save (impl_device, &error))
process_connector_update, goto err;
&error)) goto out;
goto err; }
if (!process_entries (impl_device, if (!process_entries (impl_device,
update, update,
@ -1270,6 +1367,13 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
&error)) &error))
goto err; 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, if (!process_entries (impl_device,
update, update,
meta_kms_update_get_crtc_gammas (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)) if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, &error))
goto err; goto err;
out:
return meta_kms_feedback_new_passed (failed_planes); return meta_kms_feedback_new_passed (failed_planes);
err: err:

View File

@ -120,6 +120,15 @@ meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device)
return g_list_copy (priv->planes); 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 * const MetaKmsDeviceCaps *
meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device) meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device)
{ {

View File

@ -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_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); const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device);
GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device); GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device);

View File

@ -70,11 +70,6 @@ typedef struct _MetaKmsConnectorUpdate
uint64_t hborder; uint64_t hborder;
uint64_t vborder; uint64_t vborder;
} underscanning; } underscanning;
struct {
gboolean has_update;
uint64_t state;
} dpms;
} MetaKmsConnectorUpdate; } MetaKmsConnectorUpdate;
typedef struct _MetaKmsPageFlipListener 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); 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, void meta_kms_update_get_custom_page_flip_func (MetaKmsUpdate *update,
MetaKmsCustomPageFlipFunc *custom_page_flip_func, MetaKmsCustomPageFlipFunc *custom_page_flip_func,
gpointer *custom_page_flip_user_data); gpointer *custom_page_flip_user_data);

View File

@ -35,7 +35,8 @@ struct _MetaKmsUpdate
gboolean is_locked; gboolean is_locked;
uint64_t sequence_number; uint64_t sequence_number;
MetaPowerSave power_save; gboolean power_save;
GList *mode_sets; GList *mode_sets;
GList *plane_assignments; GList *plane_assignments;
GList *connector_updates; 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_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device); 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_device (plane) == update->device);
g_assert (meta_kms_plane_get_plane_type (plane) != g_assert (meta_kms_plane_get_plane_type (plane) !=
META_KMS_PLANE_TYPE_PRIMARY || 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_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device); g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (meta_kms_plane_get_device (plane) == 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 = g_new0 (MetaKmsPlaneAssignment, 1);
*plane_assignment = (MetaKmsPlaneAssignment) { *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_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device); g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (!update->power_save);
mode_set = g_new0 (MetaKmsModeSet, 1); mode_set = g_new0 (MetaKmsModeSet, 1);
*mode_set = (MetaKmsModeSet) { *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_update_is_locked (update));
g_assert (meta_kms_connector_get_device (connector) == update->device); g_assert (meta_kms_connector_get_device (connector) == update->device);
g_assert (!update->power_save);
connector_update = ensure_connector_update (update, connector); connector_update = ensure_connector_update (update, connector);
connector_update->underscanning.has_update = TRUE; 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_update_is_locked (update));
g_assert (meta_kms_connector_get_device (connector) == update->device); g_assert (meta_kms_connector_get_device (connector) == update->device);
g_assert (!update->power_save);
connector_update = ensure_connector_update (update, connector); connector_update = ensure_connector_update (update, connector);
connector_update->underscanning.has_update = TRUE; connector_update->underscanning.has_update = TRUE;
@ -319,18 +325,15 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
} }
void void
meta_kms_update_set_dpms_state (MetaKmsUpdate *update, meta_kms_update_set_power_save (MetaKmsUpdate *update)
MetaKmsConnector *connector,
uint64_t state)
{ {
MetaKmsConnectorUpdate *connector_update;
g_assert (!meta_kms_update_is_locked (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); update->power_save = TRUE;
connector_update->dpms.has_update = TRUE;
connector_update->dpms.state = state;
} }
void 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_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device); 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); 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) gpointer user_data)
{ {
g_assert (!meta_kms_update_is_locked (update)); g_assert (!meta_kms_update_is_locked (update));
g_assert (!update->power_save);
update->custom_page_flip_func = func; update->custom_page_flip_func = func;
update->custom_page_flip_user_data = user_data; update->custom_page_flip_user_data = user_data;
@ -523,6 +528,12 @@ meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
return update->crtc_gammas; return update->crtc_gammas;
} }
gboolean
meta_kms_update_is_power_save (MetaKmsUpdate *update)
{
return update->power_save;
}
void void
meta_kms_update_lock (MetaKmsUpdate *update) meta_kms_update_lock (MetaKmsUpdate *update)
{ {

View File

@ -95,9 +95,7 @@ void meta_kms_update_set_underscanning (MetaKmsUpdate *update,
void meta_kms_update_unset_underscanning (MetaKmsUpdate *update, void meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
MetaKmsConnector *connector); MetaKmsConnector *connector);
void meta_kms_update_set_dpms_state (MetaKmsUpdate *update, void meta_kms_update_set_power_save (MetaKmsUpdate *update);
MetaKmsConnector *connector,
uint64_t state);
void meta_kms_update_mode_set (MetaKmsUpdate *update, void meta_kms_update_mode_set (MetaKmsUpdate *update,
MetaKmsCrtc *crtc, MetaKmsCrtc *crtc,

View File

@ -143,7 +143,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaBackend *backend = meta_monitor_manager_get_backend (manager); MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaKms *kms = meta_backend_native_get_kms (backend_native);
uint64_t state;
GList *l; GList *l;
switch (mode) switch (mode)
@ -158,8 +157,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
break; break;
} }
state = meta_power_save_to_dpms_state (mode);
for (l = meta_backend_get_gpus (backend); l; l = l->next) for (l = meta_backend_get_gpus (backend); l; l = l->next)
{ {
MetaGpuKms *gpu_kms = l->data; 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; g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms, kms_device); 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; flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, 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) != if (meta_kms_feedback_get_result (kms_feedback) !=
META_KMS_FEEDBACK_PASSED) 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); meta_kms_feedback_get_error (kms_feedback)->message);
} }
} }

View File

@ -102,20 +102,6 @@ meta_output_kms_get_connector_id (MetaOutputKms *output_kms)
return meta_kms_connector_get_id (output_kms->kms_connector); 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 gboolean
meta_output_kms_can_clone (MetaOutputKms *output_kms, meta_output_kms_can_clone (MetaOutputKms *output_kms,
MetaOutputKms *other_output_kms) MetaOutputKms *other_output_kms)