kms: Add update test API
This API can be used to construct a MetaKmsUpdate with plane assignments that in isolation will be tested against the current KMS state. How it is tested depends on the KMS implementation; in the simple / legacy KMS backend, the tests are identical to the current scanout requirements (dimension, stride, format, modifiers, all must match), and with atomic KMS, it uses the TEST_ONLY on a real constructed atomic mode setting commit. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2146>
This commit is contained in:
parent
4bcd4a6fab
commit
a14923e993
@ -785,6 +785,8 @@ commit_flags_string (uint32_t commit_flags)
|
|||||||
commit_flag_strings[i++] = "ATOMIC_ALLOW_MODESET";
|
commit_flag_strings[i++] = "ATOMIC_ALLOW_MODESET";
|
||||||
if (commit_flags & DRM_MODE_PAGE_FLIP_EVENT)
|
if (commit_flags & DRM_MODE_PAGE_FLIP_EVENT)
|
||||||
commit_flag_strings[i++] = "PAGE_FLIP_EVENT";
|
commit_flag_strings[i++] = "PAGE_FLIP_EVENT";
|
||||||
|
if (commit_flags & DRM_MODE_ATOMIC_TEST_ONLY)
|
||||||
|
commit_flag_strings[i++] = "TEST_ONLY";
|
||||||
|
|
||||||
commit_flags_string = g_strjoinv ("|", (char **) commit_flag_strings);
|
commit_flags_string = g_strjoinv ("|", (char **) commit_flag_strings);
|
||||||
strncpy (static_commit_flags_string, commit_flags_string,
|
strncpy (static_commit_flags_string, commit_flags_string,
|
||||||
@ -996,6 +998,9 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
|
|||||||
if (meta_kms_update_get_page_flip_listeners (update))
|
if (meta_kms_update_get_page_flip_listeners (update))
|
||||||
commit_flags |= DRM_MODE_PAGE_FLIP_EVENT;
|
commit_flags |= DRM_MODE_PAGE_FLIP_EVENT;
|
||||||
|
|
||||||
|
if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY)
|
||||||
|
commit_flags |= DRM_MODE_ATOMIC_TEST_ONLY;
|
||||||
|
|
||||||
commit:
|
commit:
|
||||||
meta_topic (META_DEBUG_KMS,
|
meta_topic (META_DEBUG_KMS,
|
||||||
"[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s",
|
"[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s",
|
||||||
|
@ -41,6 +41,12 @@ typedef struct _CachedModeSet
|
|||||||
{
|
{
|
||||||
GList *connectors;
|
GList *connectors;
|
||||||
drmModeModeInfo *drm_mode;
|
drmModeModeInfo *drm_mode;
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int stride;
|
||||||
|
uint32_t format;
|
||||||
|
uint64_t modifier;
|
||||||
} CachedModeSet;
|
} CachedModeSet;
|
||||||
|
|
||||||
struct _MetaKmsImplDeviceSimple
|
struct _MetaKmsImplDeviceSimple
|
||||||
@ -259,14 +265,21 @@ process_connector_update (MetaKmsImplDevice *impl_device,
|
|||||||
|
|
||||||
static CachedModeSet *
|
static CachedModeSet *
|
||||||
cached_mode_set_new (GList *connectors,
|
cached_mode_set_new (GList *connectors,
|
||||||
const drmModeModeInfo *drm_mode)
|
const drmModeModeInfo *drm_mode,
|
||||||
|
MetaDrmBuffer *buffer)
|
||||||
{
|
{
|
||||||
CachedModeSet *cached_mode_set;
|
CachedModeSet *cached_mode_set;
|
||||||
|
|
||||||
|
|
||||||
cached_mode_set = g_new0 (CachedModeSet, 1);
|
cached_mode_set = g_new0 (CachedModeSet, 1);
|
||||||
*cached_mode_set = (CachedModeSet) {
|
*cached_mode_set = (CachedModeSet) {
|
||||||
.connectors = g_list_copy (connectors),
|
.connectors = g_list_copy (connectors),
|
||||||
.drm_mode = g_memdup2 (drm_mode, sizeof *drm_mode),
|
.drm_mode = g_memdup2 (drm_mode, sizeof *drm_mode),
|
||||||
|
.width = meta_drm_buffer_get_width (buffer),
|
||||||
|
.height = meta_drm_buffer_get_height (buffer),
|
||||||
|
.stride = meta_drm_buffer_get_stride (buffer),
|
||||||
|
.format = meta_drm_buffer_get_format (buffer),
|
||||||
|
.modifier = meta_drm_buffer_get_modifier (buffer),
|
||||||
};
|
};
|
||||||
|
|
||||||
return cached_mode_set;
|
return cached_mode_set;
|
||||||
@ -353,6 +366,7 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
|||||||
g_autofree uint32_t *connectors = NULL;
|
g_autofree uint32_t *connectors = NULL;
|
||||||
int n_connectors;
|
int n_connectors;
|
||||||
MetaKmsPlaneAssignment *plane_assignment;
|
MetaKmsPlaneAssignment *plane_assignment;
|
||||||
|
MetaDrmBuffer *buffer;
|
||||||
drmModeModeInfo *drm_mode;
|
drmModeModeInfo *drm_mode;
|
||||||
uint32_t x, y;
|
uint32_t x, y;
|
||||||
uint32_t fb_id;
|
uint32_t fb_id;
|
||||||
@ -363,7 +377,6 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
|||||||
|
|
||||||
if (mode_set->mode)
|
if (mode_set->mode)
|
||||||
{
|
{
|
||||||
MetaDrmBuffer *buffer;
|
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
drm_mode = g_alloca (sizeof *drm_mode);
|
drm_mode = g_alloca (sizeof *drm_mode);
|
||||||
@ -437,6 +450,7 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
buffer = NULL;
|
||||||
drm_mode = NULL;
|
drm_mode = NULL;
|
||||||
x = y = 0;
|
x = y = 0;
|
||||||
n_connectors = 0;
|
n_connectors = 0;
|
||||||
@ -471,7 +485,8 @@ process_mode_set (MetaKmsImplDevice *impl_device,
|
|||||||
g_hash_table_replace (impl_device_simple->cached_mode_sets,
|
g_hash_table_replace (impl_device_simple->cached_mode_sets,
|
||||||
crtc,
|
crtc,
|
||||||
cached_mode_set_new (mode_set->connectors,
|
cached_mode_set_new (mode_set->connectors,
|
||||||
drm_mode));
|
drm_mode,
|
||||||
|
buffer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1397,6 +1412,71 @@ meta_kms_impl_device_simple_setup_drm_event_context (MetaKmsImplDevice *impl_dev
|
|||||||
drm_event_context->page_flip_handler = page_flip_handler;
|
drm_event_context->page_flip_handler = page_flip_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaKmsFeedback *
|
||||||
|
perform_update_test (MetaKmsImplDevice *impl_device,
|
||||||
|
MetaKmsUpdate *update)
|
||||||
|
{
|
||||||
|
MetaKmsImplDeviceSimple *impl_device_simple =
|
||||||
|
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
|
||||||
|
GList *failed_planes = NULL;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaKmsPlaneAssignment *plane_assignment = l->data;
|
||||||
|
MetaKmsPlane *plane = plane_assignment->plane;
|
||||||
|
MetaKmsCrtc *crtc = plane_assignment->crtc;
|
||||||
|
MetaDrmBuffer *buffer = plane_assignment->buffer;
|
||||||
|
CachedModeSet *cached_mode_set;
|
||||||
|
|
||||||
|
if (!plane_assignment->crtc ||
|
||||||
|
!plane_assignment->buffer)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cached_mode_set = get_cached_mode_set (impl_device_simple,
|
||||||
|
plane_assignment->crtc);
|
||||||
|
if (!cached_mode_set)
|
||||||
|
{
|
||||||
|
MetaKmsPlaneFeedback *plane_feedback;
|
||||||
|
|
||||||
|
plane_feedback =
|
||||||
|
meta_kms_plane_feedback_new_failed (plane, crtc,
|
||||||
|
"No existing mode set");
|
||||||
|
failed_planes = g_list_append (failed_planes, plane_feedback);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_drm_buffer_get_width (buffer) != cached_mode_set->width ||
|
||||||
|
meta_drm_buffer_get_height (buffer) != cached_mode_set->height ||
|
||||||
|
meta_drm_buffer_get_stride (buffer) != cached_mode_set->stride ||
|
||||||
|
meta_drm_buffer_get_format (buffer) != cached_mode_set->format ||
|
||||||
|
meta_drm_buffer_get_modifier (buffer) != cached_mode_set->modifier)
|
||||||
|
{
|
||||||
|
MetaKmsPlaneFeedback *plane_feedback;
|
||||||
|
|
||||||
|
plane_feedback =
|
||||||
|
meta_kms_plane_feedback_new_failed (plane, crtc,
|
||||||
|
"Incompatible buffer");
|
||||||
|
failed_planes = g_list_append (failed_planes, plane_feedback);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed_planes)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
error = g_error_new_literal (G_IO_ERROR,
|
||||||
|
G_IO_ERROR_FAILED,
|
||||||
|
"One or more buffers incompatible");
|
||||||
|
return meta_kms_feedback_new_failed (failed_planes, error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return meta_kms_feedback_new_passed (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static MetaKmsFeedback *
|
static MetaKmsFeedback *
|
||||||
meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
||||||
MetaKmsUpdate *update,
|
MetaKmsUpdate *update,
|
||||||
@ -1409,6 +1489,9 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
|
|||||||
"[simple] Processing update %" G_GUINT64_FORMAT,
|
"[simple] Processing update %" G_GUINT64_FORMAT,
|
||||||
meta_kms_update_get_sequence_number (update));
|
meta_kms_update_get_sequence_number (update));
|
||||||
|
|
||||||
|
if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY)
|
||||||
|
return perform_update_test (impl_device, update);
|
||||||
|
|
||||||
if (meta_kms_update_is_power_save (update))
|
if (meta_kms_update_is_power_save (update))
|
||||||
{
|
{
|
||||||
if (!process_power_save (impl_device, &error))
|
if (!process_power_save (impl_device, &error))
|
||||||
|
@ -106,6 +106,10 @@ MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_take_error (MetaKmsPlane *pla
|
|||||||
MetaKmsCrtc *crtc,
|
MetaKmsCrtc *crtc,
|
||||||
GError *error);
|
GError *error);
|
||||||
|
|
||||||
|
MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_failed (MetaKmsPlane *plane,
|
||||||
|
MetaKmsCrtc *crtc,
|
||||||
|
const char *error_message);
|
||||||
|
|
||||||
MetaKmsFeedback * meta_kms_feedback_new_passed (GList *failed_planes);
|
MetaKmsFeedback * meta_kms_feedback_new_passed (GList *failed_planes);
|
||||||
|
|
||||||
MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes,
|
MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes,
|
||||||
|
@ -72,6 +72,17 @@ meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane,
|
|||||||
return plane_feedback;
|
return plane_feedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaKmsPlaneFeedback *
|
||||||
|
meta_kms_plane_feedback_new_failed (MetaKmsPlane *plane,
|
||||||
|
MetaKmsCrtc *crtc,
|
||||||
|
const char *error_message)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, error_message);
|
||||||
|
return meta_kms_plane_feedback_new_take_error (plane, crtc, error);
|
||||||
|
}
|
||||||
|
|
||||||
MetaKmsFeedback *
|
MetaKmsFeedback *
|
||||||
meta_kms_feedback_new_passed (GList *failed_planes)
|
meta_kms_feedback_new_passed (GList *failed_planes)
|
||||||
{
|
{
|
||||||
|
@ -257,8 +257,13 @@ meta_kms_process_update_in_impl (MetaKmsImpl *impl,
|
|||||||
MetaKmsFeedback *feedback;
|
MetaKmsFeedback *feedback;
|
||||||
|
|
||||||
feedback = meta_kms_impl_process_update (impl, data->update, data->flags);
|
feedback = meta_kms_impl_process_update (impl, data->update, data->flags);
|
||||||
meta_kms_device_predict_states_in_impl (meta_kms_update_get_device (update),
|
|
||||||
update);
|
if (!(data->flags & META_KMS_UPDATE_FLAG_TEST_ONLY))
|
||||||
|
{
|
||||||
|
MetaKmsDevice *device = meta_kms_update_get_device (update);
|
||||||
|
|
||||||
|
meta_kms_device_predict_states_in_impl (device, update);
|
||||||
|
}
|
||||||
|
|
||||||
return feedback;
|
return feedback;
|
||||||
}
|
}
|
||||||
@ -329,6 +334,34 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
|
|||||||
return feedback;
|
return feedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
meta_kms_test_update_in_impl (MetaKmsImpl *impl,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaKmsUpdate *update = user_data;
|
||||||
|
MetaKmsUpdateFlag flags;
|
||||||
|
|
||||||
|
flags = META_KMS_UPDATE_FLAG_TEST_ONLY;
|
||||||
|
return meta_kms_impl_process_update (impl, update, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaKmsFeedback *
|
||||||
|
meta_kms_post_test_update_sync (MetaKms *kms,
|
||||||
|
MetaKmsUpdate *update)
|
||||||
|
{
|
||||||
|
g_assert (!meta_kms_update_get_page_flip_listeners (update));
|
||||||
|
g_assert (!meta_kms_update_get_mode_sets (update));
|
||||||
|
g_assert (!meta_kms_update_get_connector_updates (update));
|
||||||
|
|
||||||
|
meta_kms_update_lock (update);
|
||||||
|
|
||||||
|
return meta_kms_run_impl_task_sync (kms,
|
||||||
|
meta_kms_test_update_in_impl,
|
||||||
|
update,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
meta_kms_discard_pending_page_flips_in_impl (MetaKmsImpl *impl,
|
meta_kms_discard_pending_page_flips_in_impl (MetaKmsImpl *impl,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
|
@ -35,6 +35,7 @@ typedef enum _MetaKmsUpdateFlag
|
|||||||
{
|
{
|
||||||
META_KMS_UPDATE_FLAG_NONE = 0,
|
META_KMS_UPDATE_FLAG_NONE = 0,
|
||||||
META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR = 1 << 0,
|
META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR = 1 << 0,
|
||||||
|
META_KMS_UPDATE_FLAG_TEST_ONLY = 1 << 1,
|
||||||
} MetaKmsUpdateFlag;
|
} MetaKmsUpdateFlag;
|
||||||
|
|
||||||
#define META_TYPE_KMS (meta_kms_get_type ())
|
#define META_TYPE_KMS (meta_kms_get_type ())
|
||||||
@ -50,6 +51,9 @@ MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
|
|||||||
MetaKmsDevice *device,
|
MetaKmsDevice *device,
|
||||||
MetaKmsUpdateFlag flags);
|
MetaKmsUpdateFlag flags);
|
||||||
|
|
||||||
|
MetaKmsFeedback * meta_kms_post_test_update_sync (MetaKms *kms,
|
||||||
|
MetaKmsUpdate *update);
|
||||||
|
|
||||||
void meta_kms_discard_pending_page_flips (MetaKms *kms);
|
void meta_kms_discard_pending_page_flips (MetaKms *kms);
|
||||||
|
|
||||||
void meta_kms_notify_modes_set (MetaKms *kms);
|
void meta_kms_notify_modes_set (MetaKms *kms);
|
||||||
|
Loading…
Reference in New Issue
Block a user