aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/CMakeLists.txt1
-rw-r--r--backend/drm/backend.c23
-rw-r--r--backend/drm/drm.c65
-rw-r--r--backend/drm/event.c93
-rw-r--r--backend/drm/udev.c69
-rw-r--r--include/backend/drm/backend.h17
-rw-r--r--include/backend/drm/event.h25
-rw-r--r--include/backend/drm/udev.h5
8 files changed, 114 insertions, 184 deletions
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index 2d6e734f..344dd3cc 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -11,7 +11,6 @@ add_library(wlr-backend
wayland/wl_output.c
drm/backend.c
drm/drm.c
- drm/event.c
drm/session.c
drm/udev.c
)
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index da7ca1e4..769a4a5c 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -6,7 +6,6 @@
#include "backend/drm/backend.h"
#include "backend/drm/drm.h"
-#include "backend/drm/event.h"
#include "backend/drm/session.h"
#include "backend/drm/udev.h"
#include "common/log.h"
@@ -19,12 +18,18 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
return NULL;
}
+ backend->event_loop = wl_event_loop_create();
+ if (!backend->event_loop) {
+ wlr_log(L_ERROR, "Failed to create event loop");
+ goto error_backend;
+ }
+
if (!wlr_session_start(&backend->session)) {
wlr_log(L_ERROR, "Failed to start session");
- goto error;
+ goto error_loop;
}
- if (!wlr_udev_init(&backend->udev)) {
+ if (!wlr_udev_init(backend)) {
wlr_log(L_ERROR, "Failed to start udev");
goto error_session;
}
@@ -40,6 +45,10 @@ struct wlr_drm_backend *wlr_drm_backend_init(void)
goto error_fd;
}
+ wl_signal_init(&backend->signals.display_add);
+ wl_signal_init(&backend->signals.display_rem);
+ wl_signal_init(&backend->signals.display_render);
+
wlr_drm_scan_connectors(backend);
return backend;
@@ -50,7 +59,9 @@ error_udev:
wlr_udev_free(&backend->udev);
error_session:
wlr_session_end(&backend->session);
-error:
+error_loop:
+ wl_event_loop_destroy(backend->event_loop);
+error_backend:
free(backend);
return NULL;
}
@@ -69,7 +80,9 @@ void wlr_drm_backend_free(struct wlr_drm_backend *backend)
wlr_session_release_device(&backend->session, backend->fd);
wlr_session_end(&backend->session);
- free(backend->events);
+ wl_event_source_remove(backend->event_src.drm);
+ wl_event_loop_destroy(backend->event_loop);
+
free(backend->displays);
free(backend);
}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 94d79e5c..d1d68224 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -11,10 +11,10 @@
#include <EGL/eglext.h>
#include <gbm.h>
#include <GLES3/gl3.h>
+#include <wayland-server.h>
#include "backend/drm/backend.h"
#include "backend/drm/drm.h"
-#include "backend/drm/event.h"
#include "common/log.h"
static const char *conn_name[] = {
@@ -134,6 +134,33 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out)
return false;
}
+static void page_flip_handler(int fd,
+ unsigned seq,
+ unsigned tv_sec,
+ unsigned tv_usec,
+ void *user)
+{
+ struct wlr_drm_display *disp = user;
+ struct wlr_drm_backend *backend = disp->renderer->backend;
+
+ disp->pageflip_pending = true;
+ if (!disp->cleanup)
+ wl_signal_emit(&backend->signals.display_render, disp);
+}
+
+
+static int drm_event(int fd, uint32_t mask, void *data)
+{
+ drmEventContext event = {
+ .version = DRM_EVENT_CONTEXT_VERSION,
+ .page_flip_handler = page_flip_handler,
+ };
+
+ drmHandleEvent(fd, &event);
+
+ return 1;
+}
+
bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
struct wlr_drm_backend *backend, int fd)
{
@@ -177,6 +204,13 @@ bool wlr_drm_renderer_init(struct wlr_drm_renderer *renderer,
goto error_egl;
}
+ backend->event_src.drm = wl_event_loop_add_fd(backend->event_loop,
+ backend->fd, WL_EVENT_READABLE, drm_event, NULL);
+ if (!backend->event_src.drm) {
+ wlr_log(L_ERROR, "Failed to create DRM event source");
+ goto error_egl;
+ }
+
renderer->fd = fd;
renderer->backend = backend;
@@ -252,13 +286,13 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *backend)
if (disp->state == DRM_DISP_DISCONNECTED &&
conn->connection == DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_NEEDS_MODESET;
- wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_ADD);
+ wl_signal_emit(&backend->signals.display_add, disp);
} else if (disp->state == DRM_DISP_CONNECTED &&
conn->connection != DRM_MODE_CONNECTED) {
disp->state = DRM_DISP_DISCONNECTED;
wlr_drm_display_free(disp, false);
- wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM);
+ wl_signal_emit(&backend->signals.display_rem, disp);
}
drmModeFreeConnector(conn);
@@ -488,24 +522,11 @@ error:
drmModeFreeConnector(conn);
free(disp->modes);
- wlr_drm_add_event(backend, disp, DRM_EV_DISPLAY_REM);
+ wl_signal_emit(&backend->signals.display_rem, disp);
return false;
}
-static void page_flip_handler(int fd,
- unsigned seq,
- unsigned tv_sec,
- unsigned tv_usec,
- void *user)
-{
- struct wlr_drm_display *disp = user;
-
- disp->pageflip_pending = true;
- if (!disp->cleanup)
- wlr_drm_add_event(disp->renderer->backend, disp, DRM_EV_RENDER);
-}
-
void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore)
{
if (!disp || disp->state != DRM_DISP_CONNECTED)
@@ -542,16 +563,6 @@ void wlr_drm_display_free(struct wlr_drm_display *disp, bool restore)
}
}
-void wlr_drm_event(int fd)
-{
- drmEventContext event = {
- .version = DRM_EVENT_CONTEXT_VERSION,
- .page_flip_handler = page_flip_handler,
- };
-
- drmHandleEvent(fd, &event);
-}
-
void wlr_drm_display_begin(struct wlr_drm_display *disp)
{
struct wlr_drm_renderer *renderer = disp->renderer;
diff --git a/backend/drm/event.c b/backend/drm/event.c
deleted file mode 100644
index db17b5b7..00000000
--- a/backend/drm/event.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <stdbool.h>
-#include <stdlib.h>
-#include <poll.h>
-
-#include "backend/drm/backend.h"
-#include "backend/drm/event.h"
-#include "backend/drm/drm.h"
-#include "backend/drm/udev.h"
-
-static inline void event_swap(struct wlr_drm_event *a, struct wlr_drm_event *b)
-{
- struct wlr_drm_event tmp = *a;
- *a = *b;
- *b = tmp;
-}
-
-bool wlr_drm_get_event(struct wlr_drm_backend *backend,
- struct wlr_drm_event *restrict ret)
-{
- struct pollfd fds[] = {
- { .fd = backend->fd, .events = POLLIN },
- { .fd = backend->udev.mon_fd, .events = POLLIN },
- };
-
- while (poll(fds, 2, 0) > 0) {
- if (fds[0].revents)
- wlr_drm_event(backend->fd);
- if (fds[1].revents)
- wlr_udev_event(backend);
- }
-
- if (backend->event_len == 0) {
- ret->type = DRM_EV_NONE;
- ret->display = NULL;
- return false;
- }
-
- struct wlr_drm_event *ev = backend->events;
-
- // Downheap
- *ret = ev[0];
- ev[0] = ev[--backend->event_len];
-
- size_t i = 0;
- while (i < backend->event_len / 2) {
- size_t left = i * 2 + 1;
- size_t right = i * 2 + 2;
- size_t max = (ev[left].type > ev[right].type) ? left : right;
-
- if (ev[i].type <= ev[max].type) {
- event_swap(&ev[i], &ev[max]);
- i = max;
- } else {
- break;
- }
- }
-
- return true;
-}
-
-bool wlr_drm_add_event(struct wlr_drm_backend *backend,
- struct wlr_drm_display *disp, enum wlr_drm_event_type type)
-{
- if (type == DRM_EV_NONE)
- return true;
-
- if (backend->event_len == backend->event_cap) {
- size_t new_size = (backend->event_cap == 0) ? 8 : backend->event_cap * 2;
-
- struct wlr_drm_event *new = realloc(backend->events, sizeof *new * new_size);
- if (!new) {
- return false;
- }
-
- backend->event_cap = new_size;
- backend->events = new;
- }
-
- struct wlr_drm_event *ev = backend->events;
-
- // Upheap
- size_t i = backend->event_len++;
- ev[i].type = type;
- ev[i].display = disp;
-
- size_t j;
- while (i > 0 && ev[i].type > ev[(j = (i - 1) / 2)].type) {
- event_swap(&ev[i], &ev[j]);
- i = j;
- }
-
- return true;
-}
diff --git a/backend/drm/udev.c b/backend/drm/udev.c
index ebc68c6b..6c4aa074 100644
--- a/backend/drm/udev.c
+++ b/backend/drm/udev.c
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include <wayland-server.h>
#include "backend/drm/backend.h"
#include "backend/drm/udev.h"
@@ -116,8 +117,34 @@ int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session)
return fd;
}
-bool wlr_udev_init(struct wlr_udev *udev)
+static int udev_event(int fd, uint32_t mask, void *data)
{
+ struct wlr_drm_backend *backend = data;
+ struct wlr_udev *udev = &backend->udev;
+
+ struct udev_device *dev = udev_monitor_receive_device(udev->mon);
+ if (!dev)
+ return 1;
+
+ const char *path = udev_device_get_devnode(dev);
+ if (!path || strcmp(path, udev->drm_path) != 0)
+ goto out;
+
+ const char *action = udev_device_get_action(dev);
+ if (!action || strcmp(action, "change") != 0)
+ goto out;
+
+ wlr_drm_scan_connectors(backend);
+
+out:
+ udev_device_unref(dev);
+ return 1;
+}
+
+bool wlr_udev_init(struct wlr_drm_backend *backend)
+{
+ struct wlr_udev *udev = &backend->udev;
+
udev->udev = udev_new();
if (!udev->udev) {
wlr_log(L_ERROR, "Failed to create udev context");
@@ -127,17 +154,29 @@ bool wlr_udev_init(struct wlr_udev *udev)
udev->mon = udev_monitor_new_from_netlink(udev->udev, "udev");
if (!udev->mon) {
wlr_log(L_ERROR, "Failed to create udev monitor");
- udev_unref(udev->udev);
- return false;
+ goto error_udev;
}
udev_monitor_filter_add_match_subsystem_devtype(udev->mon, "drm", NULL);
udev_monitor_enable_receiving(udev->mon);
- udev->mon_fd = udev_monitor_get_fd(udev->mon);
+ backend->event_src.udev = wl_event_loop_add_fd(backend->event_loop,
+ udev_monitor_get_fd(udev->mon), WL_EVENT_READABLE,
+ udev_event, backend);
+ if (!backend->event_src.udev) {
+ wlr_log(L_ERROR, "Failed to create udev event source");
+ goto error_mon;
+ }
+
udev->drm_path = NULL;
return true;
+
+error_mon:
+ udev_monitor_unref(udev->mon);
+error_udev:
+ udev_unref(udev->udev);
+ return false;
}
void wlr_udev_free(struct wlr_udev *udev)
@@ -150,25 +189,3 @@ void wlr_udev_free(struct wlr_udev *udev)
udev_unref(udev->udev);
free(udev->drm_path);
}
-
-void wlr_udev_event(struct wlr_drm_backend *backend)
-{
- struct wlr_udev *udev = &backend->udev;
-
- struct udev_device *dev = udev_monitor_receive_device(udev->mon);
- if (!dev)
- return;
-
- const char *path = udev_device_get_devnode(dev);
- if (!path || strcmp(path, udev->drm_path) != 0)
- goto out;
-
- const char *action = udev_device_get_action(dev);
- if (!action || strcmp(action, "change") != 0)
- goto out;
-
- wlr_drm_scan_connectors(backend);
-
-out:
- udev_device_unref(dev);
-}
diff --git a/include/backend/drm/backend.h b/include/backend/drm/backend.h
index caa18bcc..25a42c37 100644
--- a/include/backend/drm/backend.h
+++ b/include/backend/drm/backend.h
@@ -6,6 +6,7 @@
#include <EGL/egl.h>
#include <gbm.h>
#include <libudev.h>
+#include <wayland-server.h>
#include "session.h"
#include "udev.h"
@@ -16,10 +17,18 @@ struct wlr_drm_backend {
int fd;
bool paused;
- // Priority Queue (Max-heap)
- size_t event_cap;
- size_t event_len;
- struct wlr_drm_event *events;
+ struct wl_event_loop *event_loop;
+
+ struct {
+ struct wl_event_source *drm;
+ struct wl_event_source *udev;
+ } event_src;
+
+ struct {
+ struct wl_signal display_add;
+ struct wl_signal display_rem;
+ struct wl_signal display_render;
+ } signals;
size_t display_len;
struct wlr_drm_display *displays;
diff --git a/include/backend/drm/event.h b/include/backend/drm/event.h
deleted file mode 100644
index 2155bd32..00000000
--- a/include/backend/drm/event.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef EVENT_H
-#define EVENT_H
-
-#include <stdbool.h>
-#include "drm.h"
-
-enum wlr_drm_event_type {
- DRM_EV_NONE,
- DRM_EV_RENDER,
- DRM_EV_DISPLAY_REM,
- DRM_EV_DISPLAY_ADD,
-};
-
-struct wlr_drm_event {
- enum wlr_drm_event_type type;
- struct wlr_drm_display *display;
-};
-
-struct wlr_drm_backend;
-bool wlr_drm_get_event(struct wlr_drm_backend *backend,
- struct wlr_drm_event *restrict ret);
-bool wlr_drm_add_event(struct wlr_drm_backend *backend,
- struct wlr_drm_display *disp, enum wlr_drm_event_type type);
-
-#endif
diff --git a/include/backend/drm/udev.h b/include/backend/drm/udev.h
index 6b10c9ec..576b5d6e 100644
--- a/include/backend/drm/udev.h
+++ b/include/backend/drm/udev.h
@@ -8,15 +8,14 @@
struct wlr_udev {
struct udev *udev;
struct udev_monitor *mon;
- int mon_fd;
char *drm_path;
};
-bool wlr_udev_init(struct wlr_udev *udev);
+struct wlr_drm_backend;
+bool wlr_udev_init(struct wlr_drm_backend *backend);
void wlr_udev_free(struct wlr_udev *udev);
int wlr_udev_find_gpu(struct wlr_udev *udev, struct wlr_session *session);
-struct wlr_drm_backend;
void wlr_udev_event(struct wlr_drm_backend *backend);
#endif