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
This commit is contained in:
parent
76bcddf071
commit
fbf11a41e1
|
@ -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;
|
||||
|
|
|
@ -40,6 +40,7 @@ struct wlr_session {
|
|||
|
||||
struct wl_list devices;
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
|
|
Loading…
Reference in New Issue