From 68f18f1fe9dc62667a42afa2c12905780e7db098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 3 May 2019 19:20:21 +0200 Subject: [PATCH] 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 +++++++++++++ .../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