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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1154>
This commit is contained in:
Dor Askayo 2022-07-02 17:10:36 +03:00 committed by Marge Bot
parent b7128b1d12
commit 4ad282cf26
10 changed files with 276 additions and 4 deletions

View File

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

View File

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

View File

@ -34,6 +34,8 @@ typedef struct _MetaKmsCrtcState
gboolean is_drm_mode_valid;
drmModeModeInfo drm_mode;
gboolean vrr_enabled;
struct {
MetaGammaLut *value;
int size;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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