From cc7bca073b816eebc0a9249e7ca514e091cd2585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 28 Nov 2023 22:06:33 +0100 Subject: [PATCH] crtc/kms: Dynamically assign primary and cursor planes When there are a set of primary planes, and a set of CRTCs, where each plane can be used on multiple CRTCs, we need to make sure that when we mode set and page flip, each CRTC gets assigned an individual plane that isn't used with any other CRTC. Do this during the monitor resource assignments that sets up later to be applied configurations of the mode setting objects, but with the new hooks into the backend, so that we don't need to teach the monitor config manager about planes. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2398 Part-of: --- src/backends/native/meta-crtc-kms.c | 162 ++++++++++++++++-- src/backends/native/meta-crtc-kms.h | 2 + src/backends/native/meta-kms-cursor-manager.c | 7 +- src/backends/native/meta-kms-cursor-manager.h | 1 + src/backends/native/meta-renderer-native.c | 19 +- 5 files changed, 167 insertions(+), 24 deletions(-) diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index bad9f72e9..81ebce901 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -51,7 +51,8 @@ struct _MetaCrtcKms MetaKmsCrtc *kms_crtc; - MetaKmsPlane *primary_plane; + MetaKmsPlane *assigned_primary_plane; + MetaKmsPlane *assigned_cursor_plane; }; static GQuark kms_crtc_crtc_kms_quark; @@ -205,14 +206,132 @@ meta_crtc_kms_set_gamma_lut (MetaCrtc *crtc, clutter_stage_schedule_update (CLUTTER_STAGE (stage)); } +typedef struct _CrtcKmsAssignment +{ + MetaKmsPlane *primary_plane; + MetaKmsPlane *cursor_plane; +} CrtcKmsAssignment; + +static gboolean +is_plane_assigned (MetaKmsPlane *plane, + MetaKmsPlaneType plane_type, + GPtrArray *crtc_assignments) +{ + size_t i; + + for (i = 0; i < crtc_assignments->len; i++) + { + MetaCrtcAssignment *assigned_crtc_assignment = + g_ptr_array_index (crtc_assignments, i); + CrtcKmsAssignment *kms_assignment; + + if (!META_IS_CRTC_KMS (assigned_crtc_assignment->crtc)) + continue; + + kms_assignment = assigned_crtc_assignment->backend_private; + switch (plane_type) + { + case META_KMS_PLANE_TYPE_PRIMARY: + if (kms_assignment->primary_plane == plane) + return TRUE; + break; + case META_KMS_PLANE_TYPE_CURSOR: + if (kms_assignment->cursor_plane == plane) + return TRUE; + break; + case META_KMS_PLANE_TYPE_OVERLAY: + g_assert_not_reached (); + } + } + + return FALSE; +} + +static MetaKmsPlane * +find_unassigned_plane (MetaCrtcKms *crtc_kms, + MetaKmsPlaneType kms_plane_type, + GPtrArray *crtc_assignments) +{ + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + GList *l; + + for (l = meta_kms_device_get_planes (kms_device); l; l = l->next) + { + MetaKmsPlane *kms_plane = l->data; + + if (meta_kms_plane_get_plane_type (kms_plane) != kms_plane_type) + continue; + + if (!meta_kms_plane_is_usable_with (kms_plane, kms_crtc)) + continue; + + if (is_plane_assigned (kms_plane, kms_plane_type, + crtc_assignments)) + continue; + + return kms_plane; + } + + return NULL; +} + +static gboolean +meta_crtc_kms_assign_extra (MetaCrtc *crtc, + MetaCrtcAssignment *crtc_assignment, + GPtrArray *crtc_assignments, + GError **error) +{ + MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); + MetaKmsPlane *primary_plane; + MetaKmsPlane *cursor_plane; + CrtcKmsAssignment *kms_assignment; + + primary_plane = find_unassigned_plane (crtc_kms, META_KMS_PLANE_TYPE_PRIMARY, + crtc_assignments); + if (!primary_plane) + { + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "No available primary plane found for CRTC %u (%s)", + meta_kms_crtc_get_id (kms_crtc), + meta_kms_device_get_path (kms_device)); + return FALSE; + } + + cursor_plane = find_unassigned_plane (crtc_kms, META_KMS_PLANE_TYPE_CURSOR, + crtc_assignments); + + kms_assignment = g_new0 (CrtcKmsAssignment, 1); + kms_assignment->primary_plane = primary_plane; + kms_assignment->cursor_plane = cursor_plane; + + crtc_assignment->backend_private = kms_assignment; + crtc_assignment->backend_private_destroy = g_free; + + return TRUE; +} + +static void +meta_crtc_kms_set_config (MetaCrtc *crtc, + const MetaCrtcConfig *config, + gpointer backend_private) +{ + MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); + CrtcKmsAssignment *kms_assignment = backend_private; + + crtc_kms->assigned_primary_plane = kms_assignment->primary_plane; + crtc_kms->assigned_cursor_plane = kms_assignment->cursor_plane; +} + static gboolean is_transform_handled (MetaCrtcKms *crtc_kms, MetaMonitorTransform transform) { - if (!crtc_kms->primary_plane) - return FALSE; - return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane, + return meta_kms_plane_is_transform_handled (crtc_kms->assigned_primary_plane, transform); } @@ -222,6 +341,8 @@ meta_crtc_kms_is_transform_handled (MetaCrtcNative *crtc_native, { MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native); + g_return_val_if_fail (crtc_kms->assigned_primary_plane, FALSE); + return is_transform_handled (crtc_kms, transform); } @@ -251,7 +372,7 @@ meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms, if (!is_transform_handled (crtc_kms, hw_transform)) return; - meta_kms_plane_update_set_rotation (crtc_kms->primary_plane, + meta_kms_plane_update_set_rotation (crtc_kms->assigned_primary_plane, kms_plane_assignment, hw_transform); } @@ -268,7 +389,6 @@ meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, MetaFixed16Rectangle src_rect; MtkRectangle dst_rect; MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; MetaKmsPlane *primary_kms_plane; MetaKmsPlaneAssignment *plane_assignment; @@ -289,9 +409,7 @@ meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, }; kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - primary_kms_plane = meta_kms_device_get_primary_plane_for (kms_device, - kms_crtc); + primary_kms_plane = crtc_kms->assigned_primary_plane; plane_assignment = meta_kms_update_assign_plane (kms_update, kms_crtc, primary_kms_plane, @@ -304,6 +422,12 @@ meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, return plane_assignment; } +MetaKmsPlane * +meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms) +{ + return crtc_kms->assigned_cursor_plane; +} + static GList * generate_crtc_connector_list (MetaGpu *gpu, MetaCrtc *crtc) @@ -390,7 +514,9 @@ GArray * meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, uint32_t format) { - return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane, + g_return_val_if_fail (crtc_kms->assigned_primary_plane, NULL); + + return meta_kms_plane_get_modifiers_for_format (crtc_kms->assigned_primary_plane, format); } @@ -405,7 +531,9 @@ meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, GArray * meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms) { - return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane); + g_return_val_if_fail (crtc_kms->assigned_primary_plane, NULL); + + return meta_kms_plane_copy_drm_format_list (crtc_kms->assigned_primary_plane); } /** @@ -419,7 +547,9 @@ gboolean meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms, uint32_t drm_format) { - return meta_kms_plane_is_format_supported (crtc_kms->primary_plane, + g_return_val_if_fail (crtc_kms->assigned_primary_plane, FALSE); + + return meta_kms_plane_is_format_supported (crtc_kms->assigned_primary_plane, drm_format); } @@ -434,13 +564,8 @@ meta_crtc_kms_new (MetaGpuKms *gpu_kms, MetaKmsCrtc *kms_crtc) { MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device; MetaCrtcKms *crtc_kms; - MetaKmsPlane *primary_plane; - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - primary_plane = meta_kms_device_get_primary_plane_for (kms_device, - kms_crtc); crtc_kms = g_object_new (META_TYPE_CRTC_KMS, "id", (uint64_t) meta_kms_crtc_get_id (kms_crtc), "backend", meta_gpu_get_backend (gpu), @@ -448,7 +573,6 @@ meta_crtc_kms_new (MetaGpuKms *gpu_kms, NULL); crtc_kms->kms_crtc = kms_crtc; - crtc_kms->primary_plane = primary_plane; if (!kms_crtc_crtc_kms_quark) { @@ -475,6 +599,8 @@ meta_crtc_kms_class_init (MetaCrtcKmsClass *klass) crtc_class->get_gamma_lut_size = meta_crtc_kms_get_gamma_lut_size; crtc_class->get_gamma_lut = meta_crtc_kms_get_gamma_lut; crtc_class->set_gamma_lut = meta_crtc_kms_set_gamma_lut; + crtc_class->assign_extra = meta_crtc_kms_assign_extra; + crtc_class->set_config = meta_crtc_kms_set_config; crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled; crtc_native_class->is_hw_cursor_supported = meta_crtc_kms_is_hw_cursor_supported; diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index e45598afc..2df420e73 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -45,6 +45,8 @@ MetaKmsPlaneAssignment * meta_crtc_kms_assign_primary_plane (MetaCrtcKms MetaKmsUpdate *kms_update, MetaKmsAssignPlaneFlag flags); +MetaKmsPlane * meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms); + void meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, MetaKmsUpdate *kms_update); diff --git a/src/backends/native/meta-kms-cursor-manager.c b/src/backends/native/meta-kms-cursor-manager.c index 3fbd2d9f0..b996ff712 100644 --- a/src/backends/native/meta-kms-cursor-manager.c +++ b/src/backends/native/meta-kms-cursor-manager.c @@ -45,6 +45,7 @@ typedef struct _CrtcStateImpl MetaKmsCursorManagerImpl *cursor_manager_impl; MetaKmsCrtc *crtc; + MetaKmsPlane *cursor_plane; graphene_rect_t layout; float scale; MetaMonitorTransform transform; @@ -97,6 +98,7 @@ find_crtc_state (MetaKmsCursorManagerImpl *cursor_manager_impl, static CrtcStateImpl * crtc_state_impl_new (MetaKmsCursorManagerImpl *cursor_manager_impl, MetaKmsCrtc *crtc, + MetaKmsPlane *cursor_plane, graphene_rect_t layout, float scale, MetaDrmBuffer *buffer) @@ -107,6 +109,7 @@ crtc_state_impl_new (MetaKmsCursorManagerImpl *cursor_manager_impl, g_atomic_ref_count_init (&crtc_state_impl->ref_count); crtc_state_impl->cursor_manager_impl = cursor_manager_impl; crtc_state_impl->crtc = crtc; + crtc_state_impl->cursor_plane = cursor_plane; crtc_state_impl->layout = layout; crtc_state_impl->scale = scale; crtc_state_impl->buffer = buffer; @@ -365,7 +368,7 @@ maybe_update_cursor_plane (MetaKmsCursorManagerImpl *cursor_manager_impl, meta_kms_update_realize (update, impl_device); } - cursor_plane = meta_kms_device_get_cursor_plane_for (device, crtc); + cursor_plane = crtc_state_impl->cursor_plane; if (should_have_cursor) { @@ -838,6 +841,7 @@ update_viewports_in_impl (MetaThreadImpl *thread_impl, crtc_state_impl = crtc_state_impl_new (cursor_manager_impl, crtc_layout->crtc, + crtc_layout->cursor_plane, crtc_layout->layout, crtc_layout->scale, g_steal_pointer (&old_crtc_state->buffer)); @@ -847,6 +851,7 @@ update_viewports_in_impl (MetaThreadImpl *thread_impl, crtc_state_impl = crtc_state_impl_new (cursor_manager_impl, crtc_layout->crtc, + crtc_layout->cursor_plane, crtc_layout->layout, crtc_layout->scale, NULL); diff --git a/src/backends/native/meta-kms-cursor-manager.h b/src/backends/native/meta-kms-cursor-manager.h index f4d35ed1a..0f4774ca4 100644 --- a/src/backends/native/meta-kms-cursor-manager.h +++ b/src/backends/native/meta-kms-cursor-manager.h @@ -28,6 +28,7 @@ typedef struct _MetaKmsCrtcLayout { MetaKmsCrtc *crtc; + MetaKmsPlane *cursor_plane; graphene_rect_t layout; float scale; } MetaKmsCrtcLayout; diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 55a48f667..7494563ca 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1122,23 +1122,27 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (framebuffer); MetaCrtc *crtc; + MetaCrtcKms *crtc_kms; MetaKmsCrtc *kms_crtc; + MetaKmsPlane *kms_plane; MtkRectangle view_layout; float view_scale; MetaKmsCrtcLayout crtc_layout; - renderer_native->pending_mode_set_views = - g_list_prepend (renderer_native->pending_mode_set_views, - stage_view); - meta_onscreen_native_invalidate (onscreen_native); crtc = meta_onscreen_native_get_crtc (onscreen_native); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); + crtc_kms = META_CRTC_KMS (crtc); + + kms_plane = meta_crtc_kms_get_assigned_cursor_plane (crtc_kms); + if (!kms_plane) + continue; + kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); clutter_stage_view_get_layout (stage_view, &view_layout); view_scale = clutter_stage_view_get_scale (stage_view); crtc_layout = (MetaKmsCrtcLayout) { .crtc = kms_crtc, + .cursor_plane = kms_plane, .layout = GRAPHENE_RECT_INIT (view_layout.x, view_layout.y, view_layout.width, @@ -1146,6 +1150,11 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) .scale = view_scale, }; g_array_append_val (crtc_layouts, crtc_layout); + + meta_onscreen_native_invalidate (onscreen_native); + renderer_native->pending_mode_set_views = + g_list_prepend (renderer_native->pending_mode_set_views, + stage_view); } } renderer_native->pending_mode_set = TRUE;