From 3ec54181047ca857ce63432b76dc74019a4049c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sat, 10 Oct 2020 11:47:58 +0200 Subject: [PATCH] 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: --- src/backends/native/meta-crtc-kms.c | 42 +++++++++++++ src/backends/native/meta-crtc-kms.h | 5 ++ .../native/meta-monitor-manager-kms.c | 62 +++++++++++++------ .../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 3a72c46d1..e37619b1c 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 0c599844e..8c4df1fad 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 19b3faaf0..72bdc91d0 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 84499397c..3222d5a47 100644 --- a/src/backends/native/meta-monitor-manager-kms.h +++ b/src/backends/native/meta-monitor-manager-kms.h @@ -27,6 +27,8 @@ #include #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 8e204a6e4..1a083e909 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 786bd9d41..921b35c82 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 3b27c9930..efc45c3ee 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)); }