diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index ef612639f..91f0f06ea 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -11,7 +11,7 @@ add_library(wlr-backend #wayland/wl_output.c drm/backend.c drm/drm.c - drm/udev.c + udev.c backend.c egl.c ) diff --git a/backend/backend.c b/backend/backend.c index e13f67ac8..9a3d81d88 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -39,7 +40,27 @@ void wlr_backend_destroy(struct wlr_backend *backend) { struct wlr_backend *wlr_backend_autocreate(struct wl_display *display, struct wlr_session *session) { // TODO: Choose the most appropriate backend for the situation + // Attempt DRM+libinput + struct wlr_udev *udev; + if (!(udev = wlr_udev_create(display))) { + wlr_log(L_ERROR, "Failed to start udev"); + goto error; + } + int gpu = wlr_udev_find_gpu(udev, session); + if (gpu == -1) { + wlr_log(L_ERROR, "Failed to open DRM device"); + goto error_udev; + } struct wlr_backend *wlr; - wlr = wlr_drm_backend_create(display, session); + wlr = wlr_drm_backend_create(display, session, udev, gpu); + if (!wlr) { + goto error_gpu; + } return wlr; +error_gpu: + close(gpu); +error_udev: + wlr_udev_destroy(udev); +error: + return NULL; } diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 255384fb3..bceb21840 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -3,17 +3,16 @@ #include #include #include +#include #include #include - #include #include #include - #include "backend.h" +#include "backend/udev.h" #include "backend/drm/backend.h" #include "backend/drm/drm.h" -#include "backend/drm/udev.h" #include "common/log.h" static bool wlr_drm_backend_init(struct wlr_backend_state *state) { @@ -30,7 +29,6 @@ static void wlr_drm_backend_destroy(struct wlr_backend_state *state) { wlr_output_destroy(output->wlr_output); } wlr_drm_renderer_free(&state->renderer); - wlr_udev_free(&state->udev); wlr_session_close_file(state->session, state->fd); wlr_session_finish(state->session); wl_event_source_remove(state->drm_event); @@ -75,8 +73,14 @@ static void device_resumed(struct wl_listener *listener, void *data) { } } +static void drm_invalidated(struct wl_listener *listener, void *state) { + struct wlr_backend_state *drm = wl_container_of(listener, drm, drm_invalidated); + wlr_drm_scan_connectors(drm); +} + struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session) { + struct wlr_session *session, struct wlr_udev *udev, int gpu_fd) { + assert(display && session && gpu_fd > 0); struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state)); if (!state) { wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno)); @@ -97,16 +101,10 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, goto error_backend; } - if (!wlr_udev_init(display, &state->udev)) { - wlr_log(L_ERROR, "Failed to start udev"); - goto error_list; - } - - state->fd = wlr_udev_find_gpu(&state->udev, state->session); - if (state->fd == -1) { - wlr_log(L_ERROR, "Failed to open DRM device"); - goto error_udev; - } + state->fd = gpu_fd; + wl_list_init(&state->drm_invalidated.link); + state->drm_invalidated.notify = drm_invalidated; + wl_signal_add(&udev->invalidate_drm, &state->drm_invalidated); struct stat st; if (fstat(state->fd, &st) < 0) { @@ -145,9 +143,6 @@ error_event: wl_event_source_remove(state->drm_event); error_fd: wlr_session_close_file(state->session, state->fd); -error_udev: - wlr_udev_free(&state->udev); -error_list: list_free(state->outputs); error_backend: free(state); diff --git a/backend/drm/udev.c b/backend/udev.c similarity index 91% rename from backend/drm/udev.c rename to backend/udev.c index 79e303d66..30c24e495 100644 --- a/backend/drm/udev.c +++ b/backend/udev.c @@ -1,5 +1,4 @@ #define _POSIX_C_SOURCE 200809L - #include #include #include @@ -8,13 +7,10 @@ #include #include #include - #include - #include "backend.h" #include "backend/drm/backend.h" -#include "backend/drm/udev.h" -#include "backend/drm/drm.h" +#include "backend/udev.h" #include "common/log.h" /* Tests if 'path' is KMS compatible by trying to open it. @@ -140,7 +136,6 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session) { static int udev_event(int fd, uint32_t mask, void *data) { struct wlr_udev *udev = data; - struct wlr_backend_state *state = wl_container_of(udev, state, udev); struct udev_device *dev = udev_monitor_receive_device(udev->mon); if (!dev) { @@ -161,19 +156,25 @@ static int udev_event(int fd, uint32_t mask, void *data) { goto out; } - wlr_drm_scan_connectors(state); + // TODO: Specify the GPU that's being invalidated + wl_signal_emit(&udev->invalidate_drm, udev); out: udev_device_unref(dev); return 1; } -bool wlr_udev_init(struct wl_display *display, struct wlr_udev *udev) { +struct wlr_udev *wlr_udev_create(struct wl_display *display) { + struct wlr_udev *udev = calloc(sizeof(struct wlr_udev), 1); + if (!udev) { + return NULL; + } udev->udev = udev_new(); if (!udev->udev) { wlr_log(L_ERROR, "Failed to create udev context"); - return false; + goto error; } + wl_signal_init(&udev->invalidate_drm); udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev"); if (!udev->mon) { @@ -195,16 +196,18 @@ bool wlr_udev_init(struct wl_display *display, struct wlr_udev *udev) { } wlr_log(L_DEBUG, "Successfully initialized udev"); - return true; + return udev; error_mon: udev_monitor_unref(udev->mon); error_udev: udev_unref(udev->udev); - return false; +error: + free(udev); + return NULL; } -void wlr_udev_free(struct wlr_udev *udev) { +void wlr_udev_destroy(struct wlr_udev *udev) { if (!udev) { return; } diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h index e603bccdf..3f0bce73b 100644 --- a/include/backend/drm/backend.h +++ b/include/backend/drm/backend.h @@ -13,7 +13,7 @@ #include #include "backend.h" -#include "udev.h" +#include "backend/udev.h" #include "event.h" #include "drm.h" @@ -26,13 +26,14 @@ struct wlr_backend_state { struct wl_listener device_paused; struct wl_listener device_resumed; + struct wl_listener drm_invalidated; uint32_t taken_crtcs; list_t *outputs; struct wlr_drm_renderer renderer; struct wlr_session *session; - struct wlr_udev udev; + struct wlr_udev *udev; }; #endif diff --git a/include/backend/drm/udev.h b/include/backend/udev.h similarity index 55% rename from include/backend/drm/udev.h rename to include/backend/udev.h index 99c2c4038..c50642798 100644 --- a/include/backend/drm/udev.h +++ b/include/backend/udev.h @@ -1,24 +1,19 @@ -#ifndef UDEV_H -#define UDEV_H +#ifndef _WLR_INTERNAL_UDEV_H +#define _WLR_INTERNAL_UDEV_H #include - #include #include +#include struct wlr_udev { struct udev *udev; struct udev_monitor *mon; char *drm_path; - struct wl_event_source *event; + struct wl_signal invalidate_drm; }; -struct wlr_drm_backend; -bool wlr_udev_init(struct wl_display *display, struct wlr_udev *udev); -void wlr_udev_free(struct wlr_udev *udev); int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session); -void wlr_udev_event(struct wlr_drm_backend *backend); - #endif diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 2863f926b..a486757db 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -4,8 +4,9 @@ #include #include #include +#include struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, - struct wlr_session *session); + struct wlr_session *session, struct wlr_udev *udev, int gpu_fd); #endif diff --git a/include/wlr/backend/udev.h b/include/wlr/backend/udev.h new file mode 100644 index 000000000..387a63e64 --- /dev/null +++ b/include/wlr/backend/udev.h @@ -0,0 +1,9 @@ +#ifndef _WLR_BACKEND_UDEV_H +#define _WLR_BACKEND_UDEV_H + +struct wlr_udev; + +struct wlr_udev *wlr_udev_create(struct wl_display *display); +void wlr_udev_destroy(struct wlr_udev *udev); + +#endif