[mutter] monitor-manager/kms: Use KMS abstraction to get and set CRTC gamma



commit 68f18f1fe9dc62667a42afa2c12905780e7db098
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Fri May 3 19:20:21 2019 +0200

    monitor-manager/kms: Use KMS abstraction to get and set CRTC gamma
    
    Still doesn't synchronize with frame drawing, but no point in doing that
    until gamma is managed by mutter itself and not gnome-settings-daemon.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/634

 src/backends/native/meta-kms-crtc.c            | 58 ++++++++++++++++++++++++++
 src/backends/native/meta-kms-crtc.h            | 15 +++++++
 src/backends/native/meta-kms-impl-simple.c     | 37 ++++++++++++++++
 src/backends/native/meta-kms-update-private.h  | 18 ++++++++
 src/backends/native/meta-kms-update.c          | 41 ++++++++++++++++++
 src/backends/native/meta-monitor-manager-kms.c | 43 +++++++++----------
 6 files changed, 191 insertions(+), 21 deletions(-)
---
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
index 5006a1816..2dd2b8da4 100644
--- a/src/backends/native/meta-kms-crtc.c
+++ b/src/backends/native/meta-kms-crtc.c
@@ -40,6 +40,17 @@ struct _MetaKmsCrtc
 
 G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
 
+void
+meta_kms_crtc_set_gamma (MetaKmsCrtc    *crtc,
+                         MetaKmsUpdate  *update,
+                         int             size,
+                         const uint16_t *red,
+                         const uint16_t *green,
+                         const uint16_t *blue)
+{
+  meta_kms_update_set_crtc_gamma (update, crtc, size, red, green, blue);
+}
+
 MetaKmsDevice *
 meta_kms_crtc_get_device (MetaKmsCrtc *crtc)
 {
@@ -64,6 +75,36 @@ meta_kms_crtc_get_idx (MetaKmsCrtc *crtc)
   return crtc->idx;
 }
 
+static void
+read_gamma_state (MetaKmsCrtc       *crtc,
+                  MetaKmsImplDevice *impl_device,
+                  drmModeCrtc       *drm_crtc)
+{
+  MetaKmsCrtcState *current_state = &crtc->current_state;
+
+  if (current_state->gamma.size != drm_crtc->gamma_size)
+    {
+      current_state->gamma.size = drm_crtc->gamma_size;
+
+      current_state->gamma.red = g_realloc_n (current_state->gamma.red,
+                                              drm_crtc->gamma_size,
+                                              sizeof (uint16_t));
+      current_state->gamma.green = g_realloc_n (current_state->gamma.green,
+                                                drm_crtc->gamma_size,
+                                                sizeof (uint16_t));
+      current_state->gamma.blue = g_realloc_n (current_state->gamma.blue,
+                                               drm_crtc->gamma_size,
+                                               sizeof (uint16_t));
+    }
+
+  drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device),
+                       crtc->id,
+                       current_state->gamma.size,
+                       current_state->gamma.red,
+                       current_state->gamma.green,
+                       current_state->gamma.blue);
+}
+
 static void
 meta_kms_crtc_read_state (MetaKmsCrtc       *crtc,
                           MetaKmsImplDevice *impl_device,
@@ -79,6 +120,8 @@ meta_kms_crtc_read_state (MetaKmsCrtc       *crtc,
     .is_drm_mode_valid = drm_crtc->mode_valid,
     .drm_mode = drm_crtc->mode,
   };
+
+  read_gamma_state (crtc, impl_device, drm_crtc);
 }
 
 void
@@ -109,6 +152,18 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
   return crtc;
 }
 
+static void
+meta_kms_crtc_finalize (GObject *object)
+{
+  MetaKmsCrtc *crtc = META_KMS_CRTC (object);
+
+  g_clear_pointer (&crtc->current_state.gamma.red, g_free);
+  g_clear_pointer (&crtc->current_state.gamma.green, g_free);
+  g_clear_pointer (&crtc->current_state.gamma.blue, g_free);
+
+  G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object);
+}
+
 static void
 meta_kms_crtc_init (MetaKmsCrtc *crtc)
 {
@@ -117,4 +172,7 @@ meta_kms_crtc_init (MetaKmsCrtc *crtc)
 static void
 meta_kms_crtc_class_init (MetaKmsCrtcClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_kms_crtc_finalize;
 }
diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h
index 9d0ceadd9..39a89a751 100644
--- a/src/backends/native/meta-kms-crtc.h
+++ b/src/backends/native/meta-kms-crtc.h
@@ -36,6 +36,14 @@ typedef struct _MetaKmsCrtcState
   uint32_t common_possible_crtcs;
   uint32_t common_possible_clones;
   uint32_t encoder_device_idxs;
+
+  struct {
+    uint16_t *red;
+    uint16_t *green;
+    uint16_t *blue;
+
+    int size;
+  } gamma;
 } MetaKmsCrtcState;
 
 #define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ())
@@ -43,6 +51,13 @@ G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc,
                       META, KMS_CRTC,
                       GObject)
 
+void meta_kms_crtc_set_gamma (MetaKmsCrtc    *crtc,
+                              MetaKmsUpdate  *update,
+                              int             size,
+                              const uint16_t *red,
+                              const uint16_t *green,
+                              const uint16_t *blue);
+
 MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc);
 
 const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc);
diff --git a/src/backends/native/meta-kms-impl-simple.c b/src/backends/native/meta-kms-impl-simple.c
index b62599354..929dd950a 100644
--- a/src/backends/native/meta-kms-impl-simple.c
+++ b/src/backends/native/meta-kms-impl-simple.c
@@ -284,6 +284,35 @@ process_mode_set (MetaKmsImpl     *impl,
   return TRUE;
 }
 
+static gboolean
+process_crtc_gamma (MetaKmsImpl       *impl,
+                    MetaKmsCrtcGamma  *gamma,
+                    GError           **error)
+{
+  MetaKmsCrtc *crtc = gamma->crtc;
+  MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+  int fd;
+  int ret;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+  ret = drmModeCrtcSetGamma (fd, meta_kms_crtc_get_id (crtc),
+                             gamma->size,
+                             gamma->red,
+                             gamma->green,
+                             gamma->blue);
+  if (ret != 0)
+    {
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
+                   "drmModeCrtcSetGamma on CRTC %u failed: %s",
+                   meta_kms_crtc_get_id (crtc),
+                   g_strerror (-ret));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static gboolean
 is_timestamp_earlier_than (uint64_t ts1,
                            uint64_t ts2)
@@ -708,6 +737,14 @@ meta_kms_impl_simple_process_update (MetaKmsImpl    *impl,
         goto discard_page_flips;
     }
 
+  for (l = meta_kms_update_get_crtc_gammas (update); l; l = l->next)
+    {
+      MetaKmsCrtcGamma *gamma = l->data;
+
+      if (!process_crtc_gamma (impl, gamma, error))
+        goto discard_page_flips;
+    }
+
   for (l = meta_kms_update_get_page_flips (update); l; l = l->next)
     {
       MetaKmsPageFlip *page_flip = l->data;
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index 32bb68bb8..fe320e9b3 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -59,6 +59,15 @@ typedef struct _MetaKmsConnectorProperty
   uint64_t value;
 } MetaKmsConnectorProperty;
 
+typedef struct _MetaKmsCrtcGamma
+{
+  MetaKmsCrtc *crtc;
+  int size;
+  uint16_t *red;
+  uint16_t *green;
+  uint16_t *blue;
+} MetaKmsCrtcGamma;
+
 typedef struct _MetaKmsPageFlip
 {
   MetaKmsCrtc *crtc;
@@ -77,6 +86,13 @@ void meta_kms_update_set_connector_property (MetaKmsUpdate    *update,
                                              uint32_t          prop_id,
                                              uint64_t          value);
 
+void meta_kms_update_set_crtc_gamma (MetaKmsUpdate  *update,
+                                     MetaKmsCrtc    *crtc,
+                                     int             size,
+                                     const uint16_t *red,
+                                     const uint16_t *green,
+                                     const uint16_t *blue);
+
 void meta_kms_plane_assignment_set_plane_property (MetaKmsPlaneAssignment *plane_assignment,
                                                    uint32_t                prop_id,
                                                    uint64_t                value);
@@ -89,6 +105,8 @@ GList * meta_kms_update_get_page_flips (MetaKmsUpdate *update);
 
 GList * meta_kms_update_get_connector_properties (MetaKmsUpdate *update);
 
+GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
+
 gboolean meta_kms_update_has_mode_set (MetaKmsUpdate *update);
 
 #endif /* META_KMS_UPDATE_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index 95b2464b6..b6658e7c8 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -34,6 +34,7 @@ struct _MetaKmsUpdate
   GList *plane_assignments;
   GList *page_flips;
   GList *connector_properties;
+  GList *crtc_gammas;
 };
 
 static MetaKmsProperty *
@@ -142,6 +143,39 @@ meta_kms_update_set_connector_property (MetaKmsUpdate    *update,
                                                  prop);
 }
 
+static void
+meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma)
+{
+  g_free (gamma->red);
+  g_free (gamma->green);
+  g_free (gamma->blue);
+  g_free (gamma);
+}
+
+void
+meta_kms_update_set_crtc_gamma (MetaKmsUpdate  *update,
+                                MetaKmsCrtc    *crtc,
+                                int             size,
+                                const uint16_t *red,
+                                const uint16_t *green,
+                                const uint16_t *blue)
+{
+  MetaKmsCrtcGamma *gamma;
+
+  g_assert (!meta_kms_update_is_sealed (update));
+
+  gamma = g_new0 (MetaKmsCrtcGamma, 1);
+  *gamma = (MetaKmsCrtcGamma) {
+    .crtc = crtc,
+    .size = size,
+    .red = g_memdup (red, size * sizeof *red),
+    .green = g_memdup (green, size * sizeof *green),
+    .blue = g_memdup (blue, size * sizeof *blue),
+  };
+
+  update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma);
+}
+
 void
 meta_kms_update_page_flip (MetaKmsUpdate                 *update,
                            MetaKmsCrtc                   *crtc,
@@ -225,6 +259,12 @@ meta_kms_update_get_connector_properties (MetaKmsUpdate *update)
   return update->connector_properties;
 }
 
+GList *
+meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
+{
+  return update->crtc_gammas;
+}
+
 gboolean
 meta_kms_update_has_mode_set (MetaKmsUpdate *update)
 {
@@ -258,6 +298,7 @@ meta_kms_update_free (MetaKmsUpdate *update)
                     (GDestroyNotify) meta_kms_mode_set_free);
   g_list_free_full (update->page_flips, g_free);
   g_list_free_full (update->connector_properties, g_free);
+  g_list_free_full (update->crtc_gammas, (GDestroyNotify) meta_kms_crtc_gamma_free);
 
   g_free (update);
 }
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 7f094ab42..9bac13576 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -367,20 +367,16 @@ meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager  *manager,
                                          unsigned short     **green,
                                          unsigned short     **blue)
 {
-  MetaGpu *gpu = meta_crtc_get_gpu (crtc);
-  int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu));
-  drmModeCrtc *kms_crtc;
+  MetaKmsCrtc *kms_crtc;
+  const MetaKmsCrtcState *crtc_state;
 
-  kms_crtc = drmModeGetCrtc (kms_fd, crtc->crtc_id);
+  kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
+  crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
 
-  *size = kms_crtc->gamma_size;
-  *red = g_new (unsigned short, *size);
-  *green = g_new (unsigned short, *size);
-  *blue = g_new (unsigned short, *size);
-
-  drmModeCrtcGetGamma (kms_fd, crtc->crtc_id, *size, *red, *green, *blue);
-
-  drmModeFreeCrtc (kms_crtc);
+  *size = crtc_state->gamma.size;
+  *red = g_memdup (crtc_state->gamma.red, *size * sizeof **red);
+  *green = g_memdup (crtc_state->gamma.green, *size * sizeof **green);
+  *blue = g_memdup (crtc_state->gamma.blue, *size * sizeof **blue);
 }
 
 static char *
@@ -453,20 +449,25 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
                                          unsigned short     *green,
                                          unsigned short     *blue)
 {
-  MetaGpu *gpu = meta_crtc_get_gpu (crtc);
-  int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu));
+  MetaBackend *backend = meta_monitor_manager_get_backend (manager);
+  MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
+  MetaKms *kms = meta_backend_native_get_kms (backend_native);
+  MetaKmsCrtc *kms_crtc;
   g_autofree char *gamma_ramp_string = NULL;
-  int ret;
+  MetaKmsUpdate *kms_update;
+  g_autoptr (GError) error = NULL;
 
   gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue);
   g_debug ("Setting CRTC (%ld) gamma to %s", crtc->crtc_id, gamma_ramp_string);
 
-  ret = drmModeCrtcSetGamma (kms_fd, crtc->crtc_id, size, red, green, blue);
-  if (ret != 0)
-    {
-      g_warning ("Failed to set CRTC (%ld) Gamma: %s",
-                 crtc->crtc_id, g_strerror (-ret));
-    }
+  kms_update = meta_kms_ensure_pending_update (kms);
+
+  kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
+  meta_kms_crtc_set_gamma (kms_crtc, kms_update,
+                           size, red, green, blue);
+
+  if (!meta_kms_post_pending_update_sync (kms, &error))
+    g_warning ("Failed to CRTC gamma: %s", error->message);
 }
 
 static void


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