aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/session/session.c65
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;