1
0
Fork 0

kms: Always handle KMS update result via callback

Instead of using the "discarded" page flip callback when the
"discarding" happened during actual immediate processing, communicate
the same via the KMS update feedback.

The "discarded" page flip callback is instead used only for when a
posted page flip is discarded. In the atomic backend, this only happens
on shutdown, while in the simple backend, this also happens when a
asynchronous retry sequence eventually is abandoned.

This allows further improvements making KMS handling fully async.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2854>
This commit is contained in:
Jonas Ådahl 2022-06-10 20:01:49 +02:00 committed by Marge Bot
parent a2e442ab9d
commit 73fb64cbb6
7 changed files with 88 additions and 151 deletions

View file

@ -711,43 +711,6 @@ process_page_flip_listener (MetaKmsImplDevice *impl_device,
return TRUE;
}
static gboolean
discard_page_flip_listener (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
drmModeAtomicReq *req,
GArray *blob_ids,
gpointer update_entry,
gpointer user_data,
GError **error)
{
MetaKmsPageFlipListener *listener = update_entry;
GError *commit_error = user_data;
MetaKmsPageFlipData *page_flip_data;
gpointer listener_user_data;
GDestroyNotify listener_destroy_notify;
page_flip_data = meta_kms_page_flip_data_new (impl_device,
listener->crtc);
meta_topic (META_DEBUG_KMS,
"[atomic] Creating transient page flip data for (%u, %s): %p",
meta_kms_crtc_get_id (listener->crtc),
meta_kms_impl_device_get_path (impl_device),
page_flip_data);
listener_user_data = g_steal_pointer (&listener->user_data);
listener_destroy_notify = g_steal_pointer (&listener->destroy_notify);
meta_kms_page_flip_data_add_listener (page_flip_data,
listener->vtable,
listener->flags,
listener_user_data,
listener_destroy_notify);
meta_kms_page_flip_data_discard_in_impl (page_flip_data, commit_error);
return TRUE;
}
static gboolean
process_entries (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
@ -1046,15 +1009,6 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
err:
meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message);
process_entries (impl_device,
update,
req,
blob_ids,
meta_kms_update_get_page_flip_listeners (update),
error,
discard_page_flip_listener,
NULL);
if (req)
drmModeAtomicFree (req);

View file

@ -1131,15 +1131,14 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
MetaKmsUpdateFlag flags,
GError **error)
{
g_autoptr (GList) page_flip_datas = NULL;
GList *l;
g_autolist (MetaKmsPageFlipData) page_flip_datas = NULL;
page_flip_datas = generate_page_flip_datas (impl_device, update);
while (page_flip_datas)
{
g_autoptr (GList) l = NULL;
MetaKmsPageFlipData *page_flip_data;
g_autoptr (MetaKmsPageFlipData) page_flip_data = NULL;
l = page_flip_datas;
page_flip_datas = g_list_remove_link (page_flip_datas, l);
@ -1166,21 +1165,17 @@ maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device,
*failed_planes = g_list_prepend (*failed_planes, plane_feedback);
}
meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
goto err;
}
else
{
meta_kms_page_flip_data_ref (page_flip_data);
}
}
return TRUE;
err:
for (l = page_flip_datas; l; l = l->next)
{
MetaKmsPageFlipData *page_flip_data = l->data;
meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error);
}
g_list_free (page_flip_datas);
return FALSE;

View file

@ -62,4 +62,6 @@ void meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data,
void meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPageFlipData, meta_kms_page_flip_data_unref)
#endif /* META_KMS_PAGE_FLIP_H */

View file

@ -266,13 +266,13 @@ meta_kms_queue_result_callback (MetaKms *kms,
(GDestroyNotify) meta_kms_result_listener_free);
}
MetaKmsFeedback *
void
meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device,
MetaKmsUpdateFlag flags)
{
MetaKmsUpdate *update;
MetaKmsFeedback *feedback;
g_autoptr (MetaKmsFeedback) feedback = NULL;
GList *result_listeners;
COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync,
@ -280,7 +280,7 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
update = meta_kms_take_pending_update (kms, device);
if (!update)
return NULL;
return;
feedback = meta_kms_device_process_update_sync (device, update, flags);
@ -289,8 +289,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
meta_kms_update_free (update);
meta_kms_feedback_dispatch_result (feedback, kms, result_listeners);
return feedback;
}
static gpointer

View file

@ -42,7 +42,7 @@ MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms,
MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms,
MetaKmsDevice *device);
MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
void meta_kms_post_pending_update_sync (MetaKms *kms,
MetaKmsDevice *device,
MetaKmsUpdateFlag flags);

View file

@ -1017,6 +1017,35 @@ ensure_crtc_modes (CoglOnscreen *onscreen)
meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data);
}
static void
on_swap_buffer_update_result (const MetaKmsFeedback *kms_feedback,
gpointer user_data)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (user_data);
const GError *error;
CoglFrameInfo *frame_info;
/*
* Page flipping failed, but we want to fail gracefully, so to avoid freezing
* the frame clock, emit a symbolic flip.
*/
error = meta_kms_feedback_get_error (kms_feedback);
if (!error)
return;
if (!g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Page flip failed: %s", error->message);
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
meta_onscreen_native_notify_frame_complete (onscreen);
meta_onscreen_native_clear_next_fb (onscreen);
}
static void
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
@ -1051,9 +1080,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL;
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
const GError *feedback_error;
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
"Onscreen (swap-buffers)");
@ -1136,9 +1162,19 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
if (egl_context_changed)
_cogl_winsys_egl_ensure_current (cogl_display);
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
if (power_save_mode == META_POWER_SAVE_ON)
{
MetaKmsUpdate *kms_update;
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_kms_update_add_result_listener (kms_update,
on_swap_buffer_update_result,
onscreen_native);
ensure_crtc_modes (onscreen);
meta_onscreen_native_flip_crtc (onscreen,
onscreen_native->view,
@ -1158,8 +1194,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate,
"Onscreen (post pending update)");
kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
kms_device = meta_kms_crtc_get_device (kms_crtc);
switch (renderer_gpu_data->mode)
{
@ -1209,26 +1243,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
meta_kms_crtc_get_id (kms_crtc),
meta_kms_device_get_path (kms_device));
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
switch (meta_kms_feedback_get_result (kms_feedback))
{
case META_KMS_FEEDBACK_PASSED:
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
break;
case META_KMS_FEEDBACK_FAILED:
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
feedback_error = meta_kms_feedback_get_error (kms_feedback);
if (!g_error_matches (feedback_error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", feedback_error->message);
break;
}
meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE);
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
}
gboolean
@ -1473,10 +1489,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
MetaKms *kms = meta_kms_device_get_kms (kms_device);
MetaKmsUpdateFlag flags;
MetaKmsUpdate *kms_update;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
const GError *error;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
@ -1491,30 +1504,15 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE,
g_object_ref (onscreen_native->view),
g_object_unref);
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
switch (meta_kms_feedback_get_result (kms_feedback))
{
case META_KMS_FEEDBACK_PASSED:
add_onscreen_frame_info (crtc);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
break;
case META_KMS_FEEDBACK_FAILED:
add_onscreen_frame_info (crtc);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
error = meta_kms_feedback_get_error (kms_feedback);
if (!g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", error->message);
break;
}
meta_topic (META_DEBUG_KMS,
"Posting non-primary plane update for CRTC %u (%s)",
meta_kms_crtc_get_id (kms_crtc),
meta_kms_device_get_path (kms_device));
meta_kms_post_pending_update_sync (kms, kms_device, META_KMS_UPDATE_FLAG_NONE);
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
}
static gboolean

View file

@ -816,6 +816,20 @@ clear_detached_onscreens (MetaRendererNative *renderer_native)
g_object_unref);
}
static void
on_mode_sets_update_result (const MetaKmsFeedback *kms_feedback,
gpointer user_data)
{
const GError *feedback_error;
feedback_error = meta_kms_feedback_get_error (kms_feedback);
if (feedback_error &&
!g_error_matches (feedback_error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", feedback_error->message);
}
void
meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native)
{
@ -828,9 +842,6 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native)
{
MetaKmsDevice *kms_device = l->data;
MetaKmsUpdate *kms_update;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
const GError *feedback_error;
configure_disabled_crtcs (kms_device);
@ -838,21 +849,12 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native)
if (!kms_update)
continue;
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
meta_kms_update_add_result_listener (kms_update,
on_mode_sets_update_result,
NULL);
switch (meta_kms_feedback_get_result (kms_feedback))
{
case META_KMS_FEEDBACK_PASSED:
break;
case META_KMS_FEEDBACK_FAILED:
feedback_error = meta_kms_feedback_get_error (kms_feedback);
if (!g_error_matches (feedback_error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", feedback_error->message);
break;
}
meta_kms_post_pending_update_sync (kms, kms_device,
META_KMS_UPDATE_FLAG_NONE);
}
clear_detached_onscreens (renderer_native);
@ -876,40 +878,28 @@ unset_disabled_crtcs (MetaBackend *backend,
MetaKmsDevice *kms_device =
meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu));
GList *k;
gboolean did_mode_set = FALSE;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
MetaKmsUpdate *kms_update = NULL;
for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
{
MetaCrtc *crtc = k->data;
MetaKmsUpdate *kms_update;
if (meta_crtc_get_config (crtc))
continue;
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update);
did_mode_set = TRUE;
}
if (!did_mode_set)
if (!kms_update)
continue;
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
if (meta_kms_feedback_get_result (kms_feedback) !=
META_KMS_FEEDBACK_PASSED)
{
const GError *error = meta_kms_feedback_get_error (kms_feedback);
if (!g_error_matches (error, G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", error->message);
}
meta_kms_update_add_result_listener (kms_update,
on_mode_sets_update_result,
NULL);
meta_kms_post_pending_update_sync (kms, kms_device,
META_KMS_UPDATE_FLAG_NONE);
}
}