kms/impl-device: Handle sync_fd in meta_kms_impl_device_handle_update
If the KMS thread is using the deadline timer, and a valid sync_file descriptor is passed in: 1. The update is deferred, and the deadline timer is left armed, until the sync_fd signals (becomes readable). 2. Implicit synchronization is disabled for the KMS update. This means cursor updates should no longer miss a display refresh cycle due to mutter's compositing GPU work finishing too late. v2: * Use g_autoptr for GSource in meta_kms_impl_device_handle_update. (Sebastian Wick) v3: * Use meta_kms_update_get_sync_fd, don't track sync_fd in CrtcFrame::submitted_update. (Jonas Ådahl) v4: * Clean up CrtcFrame::submitted_update members in crtc_frame_free. v5: * Coding style cleanup in meta_kms_impl_device_handle_update. (Jonas Ådahl) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958> Signed-off-by: Mingi Sung <sungmg@saltyming.net>
This commit is contained in:
parent
168839e317
commit
a9a221933e
1 changed files with 129 additions and 27 deletions
|
@ -76,6 +76,13 @@ typedef struct _CrtcDeadline
|
|||
int64_t expected_presentation_time_us;
|
||||
gboolean has_expected_presentation_time;
|
||||
} deadline;
|
||||
|
||||
struct {
|
||||
MetaKmsUpdate *kms_update;
|
||||
MetaKmsUpdateFlag flags;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
GSource *source;
|
||||
} submitted_update;
|
||||
} CrtcFrame;
|
||||
|
||||
typedef enum _MetaDeadlineTimerState
|
||||
|
@ -1469,6 +1476,8 @@ crtc_frame_free (CrtcFrame *crtc_frame)
|
|||
g_clear_fd (&crtc_frame->deadline.timer_fd, NULL);
|
||||
g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy);
|
||||
g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free);
|
||||
g_clear_pointer (&crtc_frame->submitted_update.kms_update, meta_kms_update_free);
|
||||
g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
||||
g_free (crtc_frame);
|
||||
}
|
||||
|
||||
|
@ -1577,6 +1586,79 @@ queue_update (MetaKmsImplDevice *impl_device,
|
|||
}
|
||||
}
|
||||
|
||||
static gpointer
|
||||
meta_kms_impl_device_update_ready (MetaThreadImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
CrtcFrame *crtc_frame = user_data;
|
||||
MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
|
||||
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsUpdate *update;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
MetaKmsFeedback *feedback;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
||||
|
||||
update = g_steal_pointer (&crtc_frame->submitted_update.kms_update);
|
||||
meta_kms_update_realize (update, impl_device);
|
||||
|
||||
latch_crtc = g_steal_pointer (&crtc_frame->submitted_update.latch_crtc);
|
||||
|
||||
if (crtc_frame->pending_page_flip &&
|
||||
!meta_kms_update_get_mode_sets (update))
|
||||
{
|
||||
g_assert (latch_crtc);
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"Queuing update on CRTC %u (%s): pending page flip",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
|
||||
queue_update (impl_device, crtc_frame, update);
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
if (crtc_frame->pending_update)
|
||||
{
|
||||
meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
||||
meta_kms_update_free (update);
|
||||
update = g_steal_pointer (&crtc_frame->pending_update);
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
}
|
||||
|
||||
meta_kms_device_handle_flush (priv->device, latch_crtc);
|
||||
|
||||
feedback = do_process (impl_device, latch_crtc, update, crtc_frame->submitted_update.flags);
|
||||
|
||||
if (meta_kms_feedback_did_pass (feedback) &&
|
||||
crtc_frame->deadline.armed)
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
|
||||
meta_kms_feedback_unref (feedback);
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_fd_readable (int fd)
|
||||
{
|
||||
GPollFD poll_fd;
|
||||
|
||||
poll_fd.fd = fd;
|
||||
poll_fd.events = G_IO_IN;
|
||||
poll_fd.revents = 0;
|
||||
|
||||
if (!g_poll (&poll_fd, 1, 0))
|
||||
return FALSE;
|
||||
|
||||
return (poll_fd.revents & (G_IO_IN | G_IO_NVAL)) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdate *update,
|
||||
|
@ -1584,10 +1666,15 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
|||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl);
|
||||
g_autoptr (GError) error = NULL;
|
||||
MetaKmsCrtc *latch_crtc;
|
||||
CrtcFrame *crtc_frame;
|
||||
MetaKmsFeedback *feedback;
|
||||
g_autoptr (GSource) source = NULL;
|
||||
g_autofree char *name = NULL;
|
||||
int sync_fd = -1;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
||||
|
||||
|
@ -1608,43 +1695,58 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
|||
if (!ensure_device_file (impl_device, &error))
|
||||
goto err;
|
||||
|
||||
meta_kms_update_realize (update, impl_device);
|
||||
|
||||
crtc_frame = ensure_crtc_frame (impl_device, latch_crtc);
|
||||
|
||||
crtc_frame->await_flush = FALSE;
|
||||
|
||||
if (crtc_frame->pending_page_flip &&
|
||||
!meta_kms_update_get_mode_sets (update))
|
||||
if (crtc_frame->submitted_update.kms_update)
|
||||
{
|
||||
g_assert (latch_crtc);
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_PENDING,
|
||||
"Previously-submitted update wasn't ready yet");
|
||||
goto err;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"Queuing update on CRTC %u (%s): pending page flip",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
crtc_frame->await_flush = FALSE;
|
||||
crtc_frame->submitted_update.kms_update = update;
|
||||
crtc_frame->submitted_update.flags = flags;
|
||||
crtc_frame->submitted_update.latch_crtc = latch_crtc;
|
||||
|
||||
queue_update (impl_device, crtc_frame, update);
|
||||
if (is_using_deadline_timer (impl_device))
|
||||
sync_fd = meta_kms_update_get_sync_fd (update);
|
||||
|
||||
if (sync_fd >= 0)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
||||
{
|
||||
MetaKmsPlaneAssignment *assignment = l->data;
|
||||
|
||||
assignment->flags |= META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
if (sync_fd < 0 ||
|
||||
is_fd_readable (sync_fd))
|
||||
{
|
||||
meta_kms_impl_device_update_ready (thread_impl,
|
||||
crtc_frame,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (crtc_frame->pending_update)
|
||||
{
|
||||
meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
||||
meta_kms_update_free (update);
|
||||
update = g_steal_pointer (&crtc_frame->pending_update);
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
}
|
||||
source = meta_thread_impl_register_fd (thread_impl,
|
||||
sync_fd,
|
||||
meta_kms_impl_device_update_ready,
|
||||
crtc_frame);
|
||||
|
||||
meta_kms_device_handle_flush (priv->device, latch_crtc);
|
||||
name = g_strdup_printf ("[mutter] KMS update sync_fd (crtc: %u, %s)",
|
||||
meta_kms_crtc_get_id (latch_crtc),
|
||||
priv->path);
|
||||
g_source_set_name (source, name);
|
||||
g_source_set_priority (source, G_PRIORITY_HIGH + 1);
|
||||
g_source_set_can_recurse (source, FALSE);
|
||||
g_source_set_ready_time (source, -1);
|
||||
|
||||
feedback = do_process (impl_device, latch_crtc, update, flags);
|
||||
|
||||
if (meta_kms_feedback_did_pass (feedback) &&
|
||||
crtc_frame->deadline.armed)
|
||||
disarm_crtc_frame_deadline_timer (crtc_frame);
|
||||
|
||||
meta_kms_feedback_unref (feedback);
|
||||
crtc_frame->submitted_update.source = source;
|
||||
return;
|
||||
|
||||
err:
|
||||
|
|
Loading…
Reference in a new issue