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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3428>
This commit is contained in:
Jonas Ådahl 2023-11-28 22:06:33 +01:00 committed by Marge Bot
parent 48145a91f9
commit cc7bca073b
5 changed files with 167 additions and 24 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -28,6 +28,7 @@
typedef struct _MetaKmsCrtcLayout
{
MetaKmsCrtc *crtc;
MetaKmsPlane *cursor_plane;
graphene_rect_t layout;
float scale;
} MetaKmsCrtcLayout;

View File

@ -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;