kms/impl-device: Add/remove deadline timer as required
On a hybrid machine with i915 primary and nvidia-drm (470) secondary, `meta_render_device_egl_stream_initable_init` calls `meta_kms_inhibit_kernel_thread` to change from the default 'kernel' thread type to 'user'. And soon after that it would `meta_render_device_egl_stream_finalize` because I'm not actually using that GPU, and calls `meta_kms_uninhibit_kernel_thread`. So during startup Mutter would default to a realtime kernel thread, switch to a user thread (which doesn't support realtime), and then switch back to a realtime kernel thread. In the middle of all that, while the thread type was 'user' and realtime disabled, something was invoking `ensure_crtc_frame` which created a `CrtcFrame` without a deadline timer. Soon after that the thread type changed back to 'kernel' with deadline timers expected, but our existing `CrtcFrame` has no deadline timer associated with it. And so it would never fire, causing the cursor to freeze whenever the primary plane isn't changing. And the problem was permanent, not just the first frame because each `CrtcFrame` gets repeatedly reused (maybe shouldn't be called a "Frame"?). Now we adapt to switching between kernel and user thread types by adding and removing the deadline timer as required. Close: https://gitlab.gnome.org/GNOME/mutter/-/issues/3464 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3950>
This commit is contained in:
parent
82fa9e676a
commit
c436e7cb17
1 changed files with 18 additions and 11 deletions
|
@ -1664,18 +1664,22 @@ ensure_crtc_frame (MetaKmsImplDevice *impl_device,
|
|||
MetaKmsImpl *impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl);
|
||||
CrtcFrame *crtc_frame;
|
||||
gboolean want_deadline_timer, have_deadline_timer;
|
||||
|
||||
crtc_frame = get_crtc_frame (impl_device, latch_crtc);
|
||||
if (crtc_frame)
|
||||
return crtc_frame;
|
||||
|
||||
if (!crtc_frame)
|
||||
{
|
||||
crtc_frame = g_new0 (CrtcFrame, 1);
|
||||
crtc_frame->impl_device = impl_device;
|
||||
crtc_frame->crtc = latch_crtc;
|
||||
crtc_frame->deadline.timer_fd = -1;
|
||||
crtc_frame->await_flush = TRUE;
|
||||
g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame);
|
||||
}
|
||||
|
||||
if (is_using_deadline_timer (impl_device))
|
||||
want_deadline_timer = is_using_deadline_timer (impl_device);
|
||||
have_deadline_timer = crtc_frame->deadline.timer_fd >= 0;
|
||||
if (want_deadline_timer && !have_deadline_timer)
|
||||
{
|
||||
int timer_fd;
|
||||
GSource *source;
|
||||
|
@ -1700,8 +1704,11 @@ ensure_crtc_frame (MetaKmsImplDevice *impl_device,
|
|||
|
||||
g_source_unref (source);
|
||||
}
|
||||
|
||||
g_hash_table_insert (priv->crtc_frames, latch_crtc, crtc_frame);
|
||||
else if (!want_deadline_timer && have_deadline_timer)
|
||||
{
|
||||
g_clear_fd (&crtc_frame->deadline.timer_fd, NULL);
|
||||
g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy);
|
||||
}
|
||||
|
||||
return crtc_frame;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue