[mutter] kms/update: Make power saving an update wide change



commit 5f6aee341959eeb735eaec9244d7dcd662ca624b
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Oct 21 17:38:44 2020 +0200

    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>

 src/backends/native/meta-crtc-kms.c               |  19 ---
 src/backends/native/meta-gpu-kms.c                |  29 -----
 src/backends/native/meta-kms-impl-device-simple.c | 137 +++++++++++++++++++---
 src/backends/native/meta-kms-impl-device.c        |   9 ++
 src/backends/native/meta-kms-impl-device.h        |   2 +
 src/backends/native/meta-kms-update-private.h     |   7 +-
 src/backends/native/meta-kms-update.c             |  31 +++--
 src/backends/native/meta-kms-update.h             |   4 +-
 src/backends/native/meta-monitor-manager-kms.c    |   7 +-
 src/backends/native/meta-output-kms.c             |  14 ---
 10 files changed, 158 insertions(+), 101 deletions(-)
---
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index e37619b1c9..d5e469e7ae 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -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
     {
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 3df26ff3ec..643c258829 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -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)
 {
diff --git a/src/backends/native/meta-kms-impl-device-simple.c 
b/src/backends/native/meta-kms-impl-device-simple.c
index a045f8df67..1b6efa984a 100644
--- a/src/backends/native/meta-kms-impl-device-simple.c
+++ b/src/backends/native/meta-kms-impl-device-simple.c
@@ -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,
@@ -108,31 +167,40 @@ set_connector_property (MetaKmsImplDevice     *impl_device,
 }
 
 static gboolean
-process_connector_update (MetaKmsImplDevice  *impl_device,
-                          MetaKmsUpdate      *update,
-                          gpointer            update_entry,
-                          GError            **error)
+process_power_save (MetaKmsImplDevice  *impl_device,
+                    GError            **error)
 {
-  MetaKmsConnectorUpdate *connector_update = update_entry;
-  MetaKmsConnector *connector = connector_update->connector;
+  GList *l;
 
-  if (connector_update->dpms.has_update)
+  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 on connector %u (%s) to %"
-                  G_GUINT64_FORMAT,
+                  "[simple] Setting DPMS of connector %u (%s) to OFF",
                   meta_kms_connector_get_id (connector),
-                  meta_kms_impl_device_get_path (impl_device),
-                  connector_update->dpms.state);
+                  meta_kms_impl_device_get_path (impl_device));
 
       if (!set_connector_property (impl_device,
                                    connector,
                                    META_KMS_CONNECTOR_PROP_DPMS,
-                                   connector_update->dpms.state,
+                                   DRM_MODE_DPMS_OFF,
                                    error))
         return FALSE;
     }
 
+  return TRUE;
+}
+
+static gboolean
+process_connector_update (MetaKmsImplDevice  *impl_device,
+                          MetaKmsUpdate      *update,
+                          gpointer            update_entry,
+                          GError            **error)
+{
+  MetaKmsConnectorUpdate *connector_update = update_entry;
+  MetaKmsConnector *connector = connector_update->connector;
+
   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,17 +1353,24 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
               "[simple] Processing update %" G_GUINT64_FORMAT,
               meta_kms_update_get_sequence_number (update));
 
+  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,
-                        meta_kms_update_get_connector_updates (update),
-                        process_connector_update,
+                        meta_kms_update_get_mode_sets (update),
+                        process_mode_set,
                         &error))
     goto err;
 
   if (!process_entries (impl_device,
                         update,
-                        meta_kms_update_get_mode_sets (update),
-                        process_mode_set,
+                        meta_kms_update_get_connector_updates (update),
+                        process_connector_update,
                         &error))
     goto err;
 
@@ -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:
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index d944b6c076..c762e5ee21 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -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)
 {
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
index c378b78c3c..79db8a575b 100644
--- a/src/backends/native/meta-kms-impl-device.h
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -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);
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index 02afdc9343..6546eb9158 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -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);
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index 4508838656..36c1761c36 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -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)
 {
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
index 2274b37917..6438ff99bb 100644
--- a/src/backends/native/meta-kms-update.h
+++ b/src/backends/native/meta-kms-update.h
@@ -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,
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 72bdc91d03..13fb196a17 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -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);
         }
     }
diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c
index ca744ba413..16d33d6016 100644
--- a/src/backends/native/meta-output-kms.c
+++ b/src/backends/native/meta-output-kms.c
@@ -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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]