From 4ad282cf26db545d2ef4dcf032bfd16c59242add Mon Sep 17 00:00:00 2001 From: Dor Askayo Date: Sat, 2 Jul 2022 17:10:36 +0300 Subject: [PATCH] kms: Allow setting the "VRR_ENABLED" property on a CRTC Add functions to update and monitor the value of the "VRR_ENABLED" KMS property. This requires the addition of functions to process CRTC property updates in both the atomic and the simple KMS backends. The implementation is similar to the implemention of processing connector updates. Part-of: --- src/backends/native/meta-kms-crtc-private.h | 1 + src/backends/native/meta-kms-crtc.c | 35 ++++++- src/backends/native/meta-kms-crtc.h | 2 + .../native/meta-kms-impl-device-atomic.c | 35 +++++++ .../native/meta-kms-impl-device-simple.c | 70 +++++++++++++ src/backends/native/meta-kms-update-private.h | 13 +++ src/backends/native/meta-kms-update.c | 99 +++++++++++++++++++ src/backends/native/meta-kms-update.h | 5 + src/tests/native-kms-device.c | 5 + src/tests/native-kms-updates.c | 15 +++ 10 files changed, 276 insertions(+), 4 deletions(-) diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h index 27cb0c08d..299482d6e 100644 --- a/src/backends/native/meta-kms-crtc-private.h +++ b/src/backends/native/meta-kms-crtc-private.h @@ -28,6 +28,7 @@ typedef enum _MetaKmsCrtcProp META_KMS_CRTC_PROP_ACTIVE, META_KMS_CRTC_PROP_GAMMA_LUT, META_KMS_CRTC_PROP_GAMMA_LUT_SIZE, + META_KMS_CRTC_PROP_VRR_ENABLED, META_KMS_CRTC_N_PROPS } MetaKmsCrtcProp; diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index 865cfbcde..a06d6cd37 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -227,6 +227,9 @@ meta_kms_crtc_state_changes (MetaKmsCrtcState *state, if (!meta_drm_mode_equal (&state->drm_mode, &other_state->drm_mode)) return META_KMS_RESOURCE_CHANGE_FULL; + if (state->vrr_enabled != other_state->vrr_enabled) + return META_KMS_RESOURCE_CHANGE_FULL; + if (!gamma_equal (state, other_state)) return META_KMS_RESOURCE_CHANGE_GAMMA; @@ -241,7 +244,7 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc, { MetaKmsCrtcState crtc_state = {0}; MetaKmsResourceChanges changes = META_KMS_RESOURCE_CHANGE_NONE; - MetaKmsProp *active_prop; + MetaKmsProp *prop; meta_kms_impl_device_update_prop_table (impl_device, drm_props->props, @@ -260,13 +263,17 @@ meta_kms_crtc_read_state (MetaKmsCrtc *crtc, crtc_state.is_drm_mode_valid = drm_crtc->mode_valid; crtc_state.drm_mode = drm_crtc->mode; - active_prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_ACTIVE]; + prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_ACTIVE]; - if (active_prop->prop_id) - crtc_state.is_active = !!active_prop->value; + if (prop->prop_id) + crtc_state.is_active = !!prop->value; else crtc_state.is_active = drm_crtc->mode_valid; + prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_VRR_ENABLED]; + if (prop->prop_id) + crtc_state.vrr_enabled = !!prop->value; + read_gamma_state (crtc, &crtc_state, impl_device, drm_crtc); if (!crtc_state.is_active) @@ -343,6 +350,7 @@ meta_kms_crtc_predict_state_in_impl (MetaKmsCrtc *crtc, MetaKmsUpdate *update) { GList *mode_sets; + GList *crtc_updates; GList *crtc_color_updates; GList *l; @@ -380,6 +388,20 @@ meta_kms_crtc_predict_state_in_impl (MetaKmsCrtc *crtc, break; } + crtc_updates = meta_kms_update_get_crtc_updates (update); + for (l = crtc_updates; l; l = l->next) + { + MetaKmsCrtcUpdate *crtc_update = l->data; + + if (crtc_update->crtc != crtc) + continue; + + if (crtc_update->vrr.has_update) + crtc->current_state.vrr_enabled = !!crtc_update->vrr.is_enabled; + + break; + } + crtc_color_updates = meta_kms_update_get_crtc_color_updates (update); for (l = crtc_color_updates; l; l = l->next) { @@ -430,6 +452,11 @@ init_properties (MetaKmsCrtc *crtc, .name = "GAMMA_LUT_SIZE", .type = DRM_MODE_PROP_RANGE, }, + [META_KMS_CRTC_PROP_VRR_ENABLED] = + { + .name = "VRR_ENABLED", + .type = DRM_MODE_PROP_RANGE, + }, } }; } diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h index b26b682dd..cb59042af 100644 --- a/src/backends/native/meta-kms-crtc.h +++ b/src/backends/native/meta-kms-crtc.h @@ -34,6 +34,8 @@ typedef struct _MetaKmsCrtcState gboolean is_drm_mode_valid; drmModeModeInfo drm_mode; + gboolean vrr_enabled; + struct { MetaGammaLut *value; int size; diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c index 35837f742..cd3f24e3b 100644 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ b/src/backends/native/meta-kms-impl-device-atomic.c @@ -362,6 +362,31 @@ add_crtc_property (MetaKmsImplDevice *impl_device, return TRUE; } +static gboolean +process_crtc_update (MetaKmsImplDevice *impl_device, + MetaKmsUpdate *update, + drmModeAtomicReq *req, + GArray *blob_ids, + gpointer update_entry, + gpointer user_data, + GError **error) +{ + MetaKmsCrtcUpdate *crtc_update = update_entry; + MetaKmsCrtc *crtc = crtc_update->crtc; + + if (crtc_update->vrr.has_update) + { + if (!add_crtc_property (impl_device, + crtc, req, + META_KMS_CRTC_PROP_VRR_ENABLED, + !!crtc_update->vrr.is_enabled, + error)) + return FALSE; + } + + return TRUE; +} + static gboolean process_mode_set (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, @@ -1086,6 +1111,16 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, &error)) goto err; + if (!process_entries (impl_device, + update, + req, + blob_ids, + meta_kms_update_get_crtc_updates (update), + NULL, + process_crtc_update, + &error)) + goto err; + if (!process_entries (impl_device, update, req, diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c index febcac01b..0e9dbaced 100644 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ b/src/backends/native/meta-kms-impl-device-simple.c @@ -179,6 +179,47 @@ set_connector_property (MetaKmsImplDevice *impl_device, return TRUE; } +static gboolean +set_crtc_property (MetaKmsImplDevice *impl_device, + MetaKmsCrtc *crtc, + MetaKmsCrtcProp prop, + uint64_t value, + GError **error) +{ + uint32_t prop_id; + int fd; + int ret; + + prop_id = meta_kms_crtc_get_prop_id (crtc, prop); + if (!prop_id) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Property (%s) not found on CRTC %u", + meta_kms_crtc_get_prop_name (crtc, prop), + meta_kms_crtc_get_id (crtc)); + return FALSE; + } + + fd = meta_kms_impl_device_get_fd (impl_device); + + ret = drmModeObjectSetProperty (fd, + meta_kms_crtc_get_id (crtc), + DRM_MODE_OBJECT_CRTC, + prop_id, + value); + if (ret != 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), + "Failed to set CRTC %u property %u: %s", + meta_kms_crtc_get_id (crtc), + prop_id, + g_strerror (-ret)); + return FALSE; + } + + return TRUE; +} + static gboolean process_connector_update (MetaKmsImplDevice *impl_device, MetaKmsUpdate *update, @@ -268,6 +309,28 @@ process_connector_update (MetaKmsImplDevice *impl_device, return TRUE; } +static gboolean +process_crtc_update (MetaKmsImplDevice *impl_device, + MetaKmsUpdate *update, + gpointer update_entry, + GError **error) +{ + MetaKmsCrtcUpdate *crtc_update = update_entry; + MetaKmsCrtc *crtc = crtc_update->crtc; + + if (crtc_update->vrr.has_update) + { + if (!set_crtc_property (impl_device, + crtc, + META_KMS_CRTC_PROP_VRR_ENABLED, + !!crtc_update->vrr.is_enabled, + error)) + return FALSE; + } + + return TRUE; +} + static CachedModeSet * cached_mode_set_new (GList *connectors, const drmModeModeInfo *drm_mode, @@ -1548,6 +1611,13 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, &error)) goto err; + if (!process_entries (impl_device, + update, + meta_kms_update_get_crtc_updates (update), + process_crtc_update, + &error)) + goto err; + if (!process_plane_assignments (impl_device, update, &failed_planes, &error)) goto err; diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 0dfa5ef27..fcd45d551 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -117,6 +117,16 @@ typedef struct _MetaKmsConnectorUpdate } broadcast_rgb; } MetaKmsConnectorUpdate; +typedef struct _MetaKmsCrtcUpdate +{ + MetaKmsCrtc *crtc; + + struct { + gboolean has_update; + gboolean is_enabled; + } vrr; +} MetaKmsCrtcUpdate; + typedef struct _MetaKmsPageFlipListener { gatomicrefcount ref_count; @@ -182,6 +192,9 @@ GList * meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update); META_EXPORT_TEST GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update); +META_EXPORT_TEST +GList * meta_kms_update_get_crtc_updates (MetaKmsUpdate *update); + META_EXPORT_TEST GList * meta_kms_update_get_crtc_color_updates (MetaKmsUpdate *update); diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index 8e23527ed..b8c4137f9 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -40,6 +40,7 @@ struct _MetaKmsUpdate GList *mode_sets; GList *plane_assignments; GList *connector_updates; + GList *crtc_updates; GList *crtc_color_updates; MetaKmsCustomPageFlip *custom_page_flip; @@ -481,6 +482,46 @@ meta_kms_update_set_broadcast_rgb (MetaKmsUpdate *update, connector_update->broadcast_rgb.value = rgb_range; } +static MetaKmsCrtcUpdate * +ensure_crtc_update (MetaKmsUpdate *update, + MetaKmsCrtc *crtc) +{ + GList *l; + MetaKmsCrtcUpdate *crtc_update; + + for (l = update->crtc_updates; l; l = l->next) + { + crtc_update = l->data; + + if (crtc_update->crtc == crtc) + return crtc_update; + } + + crtc_update = g_new0 (MetaKmsCrtcUpdate, 1); + crtc_update->crtc = crtc; + + update->crtc_updates = g_list_prepend (update->crtc_updates, + crtc_update); + + return crtc_update; +} + +void +meta_kms_update_set_vrr (MetaKmsUpdate *update, + MetaKmsCrtc *crtc, + gboolean enabled) +{ + MetaKmsCrtcUpdate *crtc_update; + + g_assert (meta_kms_crtc_get_device (crtc) == update->device); + + crtc_update = ensure_crtc_update (update, crtc); + crtc_update->vrr.has_update = TRUE; + crtc_update->vrr.is_enabled = enabled; + + update_latch_crtc (update, crtc); +} + static MetaKmsCrtcColorUpdate * ensure_color_update (MetaKmsUpdate *update, MetaKmsCrtc *crtc) @@ -746,6 +787,12 @@ meta_kms_update_get_connector_updates (MetaKmsUpdate *update) return update->connector_updates; } +GList * +meta_kms_update_get_crtc_updates (MetaKmsUpdate *update) +{ + return update->crtc_updates; +} + GList * meta_kms_update_get_crtc_color_updates (MetaKmsUpdate *update) { @@ -921,6 +968,55 @@ merge_crtc_color_updates_from (MetaKmsUpdate *update, } } +static GList * +find_crtc_update_link_for (MetaKmsUpdate *update, + MetaKmsCrtc *crtc) +{ + GList *l; + + for (l = update->crtc_updates; l; l = l->next) + { + MetaKmsCrtcUpdate *crtc_update = l->data; + + if (crtc_update->crtc == crtc) + return l; + } + + return NULL; +} + +static void +merge_crtc_updates_from (MetaKmsUpdate *update, + MetaKmsUpdate *other_update) +{ + while (other_update->crtc_updates) + { + GList *l = other_update->crtc_updates; + MetaKmsCrtcUpdate *other_crtc_update = l->data; + MetaKmsCrtc *crtc = other_crtc_update->crtc; + GList *el; + + other_update->crtc_updates = + g_list_remove_link (other_update->crtc_updates, l); + + el = find_crtc_update_link_for (update, crtc); + if (el) + { + MetaKmsCrtcUpdate *crtc_update = el->data; + + if (other_crtc_update->vrr.has_update) + crtc_update->vrr = other_crtc_update->vrr; + } + else + { + update->crtc_updates = + g_list_insert_before_link (update->crtc_updates, + update->crtc_updates, + l); + } + } +} + static GList * find_connector_update_link_for (MetaKmsUpdate *update, MetaKmsConnector *connector) @@ -1034,6 +1130,7 @@ meta_kms_update_merge_from (MetaKmsUpdate *update, merge_mode_sets (update, other_update); merge_plane_assignments_from (update, other_update); + merge_crtc_updates_from (update, other_update); merge_crtc_color_updates_from (update, other_update); merge_connector_updates_from (update, other_update); merge_custom_page_flip_from (update, other_update); @@ -1074,6 +1171,7 @@ meta_kms_update_free (MetaKmsUpdate *update) g_list_free_full (update->page_flip_listeners, (GDestroyNotify) meta_kms_page_flip_listener_unref); g_list_free_full (update->connector_updates, g_free); + g_list_free_full (update->crtc_updates, g_free); g_list_free_full (update->crtc_color_updates, (GDestroyNotify) meta_kms_crtc_color_updates_free); g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free); @@ -1108,5 +1206,6 @@ meta_kms_update_is_empty (MetaKmsUpdate *update) return (!update->mode_sets && !update->plane_assignments && !update->connector_updates && + !update->crtc_updates && !update->crtc_color_updates); } diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h index d50295d30..1951c80f6 100644 --- a/src/backends/native/meta-kms-update.h +++ b/src/backends/native/meta-kms-update.h @@ -147,6 +147,11 @@ void meta_kms_update_mode_set (MetaKmsUpdate *update, GList *connectors, MetaKmsMode *mode); +META_EXPORT_TEST +void meta_kms_update_set_vrr (MetaKmsUpdate *update, + MetaKmsCrtc *crtc, + gboolean enabled); + META_EXPORT_TEST void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, MetaKmsCrtc *crtc, diff --git a/src/tests/native-kms-device.c b/src/tests/native-kms-device.c index e2a13ec45..7a65c4c8f 100644 --- a/src/tests/native-kms-device.c +++ b/src/tests/native-kms-device.c @@ -111,6 +111,8 @@ assert_crtc_state_equals (const MetaKmsCrtcState *crtc_state1, crtc_state2->drm_mode.name); } + g_assert_true (crtc_state1->vrr_enabled == crtc_state2->vrr_enabled); + g_assert_true (meta_gamma_lut_equal (crtc_state1->gamma.value, crtc_state2->gamma.value)); } @@ -208,6 +210,9 @@ copy_crtc_state (const MetaKmsCrtcState *crtc_state) g_assert_nonnull (crtc_state); new_state = *crtc_state; + + new_state.vrr_enabled = crtc_state->vrr_enabled; + if (crtc_state->gamma.value) new_state.gamma.value = meta_gamma_lut_copy (crtc_state->gamma.value); else diff --git a/src/tests/native-kms-updates.c b/src/tests/native-kms-updates.c index 8a819bf51..f30428168 100644 --- a/src/tests/native-kms-updates.c +++ b/src/tests/native-kms-updates.c @@ -95,6 +95,7 @@ meta_test_kms_update_sanity (void) g_assert_null (meta_kms_update_get_mode_sets (update)); g_assert_null (meta_kms_update_get_page_flip_listeners (update)); g_assert_null (meta_kms_update_get_connector_updates (update)); + g_assert_null (meta_kms_update_get_crtc_updates (update)); g_assert_null (meta_kms_update_get_crtc_color_updates (update)); meta_kms_update_free (update); } @@ -430,6 +431,8 @@ meta_test_kms_update_merge (void) GList *plane_assignments; MetaKmsPlaneAssignment *plane_assignment; MetaGammaLut *crtc_gamma; + GList *crtc_updates; + MetaKmsCrtcUpdate *crtc_update; GList *connector_updates; MetaKmsConnectorUpdate *connector_update; @@ -475,6 +478,10 @@ meta_test_kms_update_merge (void) meta_kms_plane_assignment_set_cursor_hotspot (cursor_plane_assignment, 10, 11); + meta_kms_update_set_vrr (update1, + crtc, + TRUE); + meta_kms_update_set_underscanning (update1, connector, 123, 456); @@ -605,6 +612,14 @@ meta_test_kms_update_merge (void) } } + crtc_updates = meta_kms_update_get_crtc_updates (update1); + g_assert_cmpuint (g_list_length (crtc_updates), ==, 1); + crtc_update = crtc_updates->data; + g_assert_nonnull (crtc_update); + + g_assert_true (crtc_update->vrr.has_update); + g_assert_true (crtc_update->vrr.is_enabled); + connector_updates = meta_kms_update_get_connector_updates (update1); g_assert_cmpuint (g_list_length (connector_updates), ==, 1); connector_update = connector_updates->data;