[mutter] backend/native: Set CRTC gamma once per frame



commit 3ec54181047ca857ce63432b76dc74019a4049c7
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat Oct 10 11:47:58 2020 +0200

    backend/native: Set CRTC gamma once per frame
    
    Before we received new gamma updates via D-Bus and posted the update to
    KMS directly. This won't be possible with atomic KMS, since one can only
    update the state of a CRTC once per cycle.
    
    Thus, to handle this, when configured by D-Bus, only cache the value,
    and mark it as invalid. The next frame, the native renderer will pick
    up the newly cached gamma value and configure the CRTCs accordingly.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>

 src/backends/native/meta-crtc-kms.c            | 42 +++++++++++++++++
 src/backends/native/meta-crtc-kms.h            |  5 +++
 src/backends/native/meta-monitor-manager-kms.c | 62 ++++++++++++++++++--------
 src/backends/native/meta-monitor-manager-kms.h |  5 +++
 src/backends/native/meta-renderer-native.c     | 13 ++++++
 src/backends/native/meta-renderer-native.h     |  4 ++
 src/backends/native/meta-stage-native.c        |  5 +++
 7 files changed, 117 insertions(+), 19 deletions(-)
---
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 3a72c46d1a..e37619b1c9 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -33,6 +33,7 @@
 #include "backends/native/meta-kms-mode.h"
 #include "backends/native/meta-kms-plane.h"
 #include "backends/native/meta-kms-update.h"
+#include "backends/native/meta-kms.h"
 #include "backends/native/meta-monitor-manager-kms.h"
 
 #define ALL_TRANSFORMS_MASK ((1 << META_MONITOR_N_TRANSFORMS) - 1)
@@ -47,6 +48,8 @@ struct _MetaCrtcKms
 
   gpointer cursor_renderer_private;
   GDestroyNotify cursor_renderer_private_destroy_notify;
+
+  gboolean is_gamma_valid;
 };
 
 static GQuark kms_crtc_crtc_kms_quark;
@@ -176,6 +179,39 @@ generate_crtc_connector_list (MetaGpu  *gpu,
   return connectors;
 }
 
+void
+meta_crtc_kms_maybe_set_gamma (MetaCrtcKms   *crtc_kms,
+                               MetaKmsDevice *kms_device)
+{
+  MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms));
+  MetaBackend *backend = meta_gpu_get_backend (gpu);
+  MetaMonitorManager *monitor_manager =
+    meta_backend_get_monitor_manager (backend);
+  MetaMonitorManagerKms *monitor_manager_kms =
+    META_MONITOR_MANAGER_KMS (monitor_manager);
+  MetaKms *kms = meta_kms_device_get_kms (kms_device);
+  MetaKmsUpdate *kms_update;
+  MetaKmsCrtcGamma *gamma;
+
+  if (crtc_kms->is_gamma_valid)
+    return;
+
+  gamma = meta_monitor_manager_kms_get_cached_crtc_gamma (monitor_manager_kms,
+                                                          crtc_kms);
+  if (!gamma)
+    return;
+
+  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
+  meta_kms_update_set_crtc_gamma (kms_update,
+                                  meta_crtc_kms_get_kms_crtc (crtc_kms),
+                                  gamma->size,
+                                  gamma->red,
+                                  gamma->green,
+                                  gamma->blue);
+
+  crtc_kms->is_gamma_valid = TRUE;
+}
+
 void
 meta_crtc_kms_set_mode (MetaCrtcKms   *crtc_kms,
                         MetaKmsUpdate *kms_update)
@@ -287,6 +323,12 @@ meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms,
                                              drm_format);
 }
 
+void
+meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms)
+{
+  crtc_kms->is_gamma_valid = FALSE;
+}
+
 MetaCrtcKms *
 meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc)
 {
diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h
index 0c599844e5..8c4df1fad0 100644
--- a/src/backends/native/meta-crtc-kms.h
+++ b/src/backends/native/meta-crtc-kms.h
@@ -72,6 +72,11 @@ gboolean
 meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms,
                                uint32_t     drm_format);
 
+void meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms);
+
+void meta_crtc_kms_maybe_set_gamma (MetaCrtcKms   *crtc_kms,
+                                    MetaKmsDevice *kms_device);
+
 MetaCrtcKms * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc);
 
 MetaCrtcKms * meta_crtc_kms_new (MetaGpuKms  *gpu_kms,
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 19b3faaf08..72bdc91d03 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -76,6 +76,8 @@ struct _MetaMonitorManagerKms
   MetaMonitorManager parent_instance;
 
   gulong kms_resources_changed_handler_id;
+
+  GHashTable *crtc_gamma_cache;
 };
 
 struct _MetaMonitorManagerKmsClass
@@ -430,6 +432,17 @@ generate_gamma_ramp_string (size_t          size,
   return g_string_free (string, FALSE);
 }
 
+MetaKmsCrtcGamma *
+meta_monitor_manager_kms_get_cached_crtc_gamma (MetaMonitorManagerKms *manager_kms,
+                                                MetaCrtcKms           *crtc_kms)
+{
+  uint64_t crtc_id;
+
+  crtc_id = meta_crtc_get_id (META_CRTC (crtc_kms));
+  return g_hash_table_lookup (manager_kms->crtc_gamma_cache,
+                              GUINT_TO_POINTER (crtc_id));
+}
+
 static void
 meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
                                          MetaCrtc           *crtc,
@@ -438,32 +451,24 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
                                          unsigned short     *green,
                                          unsigned short     *blue)
 {
-  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;
-  MetaKmsDevice *kms_device;
-  MetaKmsUpdate *kms_update;
+  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+  MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
+  MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
   g_autofree char *gamma_ramp_string = NULL;
-  MetaKmsUpdateFlag flags;
-  g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
+  MetaBackend *backend = meta_monitor_manager_get_backend (manager);
+  ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
 
-  kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
-  kms_device = meta_kms_crtc_get_device (kms_crtc);
-  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
-  meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, size, red, green, blue);
+  g_hash_table_replace (manager_kms->crtc_gamma_cache,
+                        GUINT_TO_POINTER (meta_crtc_get_id (crtc)),
+                        meta_kms_crtc_gamma_new (kms_crtc, size,
+                                                 red, green, blue));
 
   gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue);
   g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s",
            meta_crtc_get_id (crtc), gamma_ramp_string);
 
-  flags = META_KMS_UPDATE_FLAG_NONE;
-  kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
-  if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
-    {
-      g_warning ("Failed to set CRTC gamma: %s",
-                 meta_kms_feedback_get_error (kms_feedback)->message);
-    }
+  meta_crtc_kms_invalidate_gamma (crtc_kms);
+  clutter_stage_schedule_update (stage);
 }
 
 static void
@@ -595,6 +600,17 @@ meta_monitor_manager_kms_get_default_layout_mode (MetaMonitorManager *manager)
     return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
 }
 
+static void
+meta_monitor_manager_kms_dispose (GObject *object)
+{
+  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
+
+  g_clear_pointer (&manager_kms->crtc_gamma_cache,
+                   g_hash_table_unref);
+
+  G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object);
+}
+
 static gboolean
 meta_monitor_manager_kms_initable_init (GInitable    *initable,
                                         GCancellable *cancellable,
@@ -626,6 +642,11 @@ meta_monitor_manager_kms_initable_init (GInitable    *initable,
       return FALSE;
     }
 
+  manager_kms->crtc_gamma_cache =
+    g_hash_table_new_full (NULL, NULL,
+                           NULL,
+                           (GDestroyNotify) meta_kms_crtc_gamma_free);
+
   return TRUE;
 }
 
@@ -643,8 +664,11 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 static void
 meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
 
+  object_class->dispose = meta_monitor_manager_kms_dispose;
+
   manager_class->read_edid = meta_monitor_manager_kms_read_edid;
   manager_class->read_current_state = meta_monitor_manager_kms_read_current_state;
   manager_class->ensure_initial_config = meta_monitor_manager_kms_ensure_initial_config;
diff --git a/src/backends/native/meta-monitor-manager-kms.h b/src/backends/native/meta-monitor-manager-kms.h
index 84499397c8..3222d5a47f 100644
--- a/src/backends/native/meta-monitor-manager-kms.h
+++ b/src/backends/native/meta-monitor-manager-kms.h
@@ -27,6 +27,8 @@
 #include <xf86drmMode.h>
 
 #include "backends/meta-monitor-manager-private.h"
+#include "backends/native/meta-crtc-kms.h"
+#include "backends/native/meta-kms-crtc.h"
 
 typedef struct _MetaGpuKms MetaGpuKms;
 
@@ -41,4 +43,7 @@ void meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms);
 
 uint64_t meta_power_save_to_dpms_state (MetaPowerSave power_save);
 
+MetaKmsCrtcGamma * meta_monitor_manager_kms_get_cached_crtc_gamma (MetaMonitorManagerKms *manager_kms,
+                                                                   MetaCrtcKms           *crtc_kms);
+
 #endif /* META_MONITOR_MANAGER_KMS_H */
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 8e204a6e4f..1a083e909e 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -3283,6 +3283,19 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer)
   meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
 }
 
+void
+meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native,
+                                    MetaRendererView   *view,
+                                    ClutterFrame       *frame)
+{
+  MetaCrtc *crtc = meta_renderer_view_get_crtc (view);
+  MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
+  MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
+  MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
+
+  meta_crtc_kms_maybe_set_gamma (crtc_kms, kms_device);
+}
+
 static void
 add_onscreen_frame_info (MetaCrtc *crtc)
 {
diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h
index 786bd9d41b..921b35c82d 100644
--- a/src/backends/native/meta-renderer-native.h
+++ b/src/backends/native/meta-renderer-native.h
@@ -53,6 +53,10 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms);
 
 MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native);
 
+void meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native,
+                                         MetaRendererView   *view,
+                                         ClutterFrame       *frame);
+
 void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native,
                                         MetaRendererView   *view,
                                         ClutterFrame       *frame);
diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c
index 3b27c99303..efc45c3eee 100644
--- a/src/backends/native/meta-stage-native.c
+++ b/src/backends/native/meta-stage-native.c
@@ -112,11 +112,16 @@ meta_stage_native_prepare_frame (ClutterStageWindow *stage_window,
                                  ClutterFrame       *frame)
 {
   MetaBackend *backend = meta_get_backend ();
+  MetaRenderer *renderer = meta_backend_get_renderer (backend);
+  MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
   MetaCursorRenderer *cursor_renderer =
     meta_backend_get_cursor_renderer (backend);
   MetaCursorRendererNative *cursor_renderer_native =
     META_CURSOR_RENDERER_NATIVE (cursor_renderer);
 
+  meta_renderer_native_prepare_frame (renderer_native,
+                                      META_RENDERER_VIEW (stage_view),
+                                      frame);
   meta_cursor_renderer_native_prepare_frame (cursor_renderer_native,
                                              META_RENDERER_VIEW (stage_view));
 }


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