diff options
author | Simon Ser <contact@emersion.fr> | 2020-11-06 11:14:49 +0100 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-11-19 22:47:49 +0100 |
commit | fbf11a41e135c2b380ce51c9c90278dbcfc60c3d (patch) | |
tree | 4ac51ed85190c6b299b68b5d83f924b65c93e545 /backend/session | |
parent | 76bcddf071454cd373bd09e2619c0cb03a377350 (diff) |
backend/session: wait for DRM device if none found
Wait for a DRM device if none is found in wlr_session_find_gpus. This
can happen if the compositor is loaded before the display kernel driver.
This supersedes the logind CanGraphical property.
To test, e.g. with i915 and sway:
rmmod -f i915
sway &
modprobe i915
Closes: https://github.com/swaywm/wlroots/issues/2093
Diffstat (limited to 'backend/session')
-rw-r--r-- | backend/session/session.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/backend/session/session.c b/backend/session/session.c index a94793c8..c7808212 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -170,6 +170,8 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) { goto error_mon; } + session->display = disp; + session->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(disp, &session->display_destroy); @@ -301,6 +303,36 @@ static size_t explicit_find_gpus(struct wlr_session *session, return i; } +static struct udev_enumerate *enumerate_drm_cards(struct udev *udev) { + struct udev_enumerate *en = udev_enumerate_new(udev); + if (!en) { + wlr_log(WLR_ERROR, "udev_enumerate_new failed"); + return NULL; + } + + udev_enumerate_add_match_subsystem(en, "drm"); + udev_enumerate_add_match_sysname(en, "card[0-9]*"); + + if (udev_enumerate_scan_devices(en) != 0) { + wlr_log(WLR_ERROR, "udev_enumerate_scan_devices failed"); + udev_enumerate_unref(en); + return NULL; + } + + return en; +} + +struct find_gpus_add_handler { + bool added; + struct wl_listener listener; +}; + +static void find_gpus_handle_add(struct wl_listener *listener, void *data) { + struct find_gpus_add_handler *handler = + wl_container_of(listener, handler, listener); + handler->added = true; +} + /* Tries to find the primary GPU by checking for the "boot_vga" attribute. * If it's not found, it returns the first valid GPU it finds. */ @@ -311,15 +343,38 @@ size_t wlr_session_find_gpus(struct wlr_session *session, return explicit_find_gpus(session, ret_len, ret, explicit); } - struct udev_enumerate *en = udev_enumerate_new(session->udev); + struct udev_enumerate *en = enumerate_drm_cards(session->udev); if (!en) { - wlr_log(WLR_ERROR, "Failed to create udev enumeration"); return -1; } - udev_enumerate_add_match_subsystem(en, "drm"); - udev_enumerate_add_match_sysname(en, "card[0-9]*"); - udev_enumerate_scan_devices(en); + if (udev_enumerate_get_list_entry(en) == NULL) { + udev_enumerate_unref(en); + wlr_log(WLR_INFO, "Waiting for a DRM card device"); + + struct find_gpus_add_handler handler = {0}; + handler.listener.notify = find_gpus_handle_add; + wl_signal_add(&session->events.add_drm_card, &handler.listener); + + struct wl_event_loop *event_loop = + wl_display_get_event_loop(session->display); + while (!handler.added) { + int ret = wl_event_loop_dispatch(event_loop, -1); + if (ret < 0) { + wlr_log_errno(WLR_ERROR, "Failed to wait for DRM card device: " + "wl_event_loop_dispatch failed"); + udev_enumerate_unref(en); + return -1; + } + } + + wl_list_remove(&handler.listener.link); + + en = enumerate_drm_cards(session->udev); + if (!en) { + return -1; + } + } struct udev_list_entry *entry; size_t i = 0; |