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;