From 115d4ae637673e348d5542740a158e6dcee0cf80 Mon Sep 17 00:00:00 2001
From: Scott Anderson <ascent12@hotmail.com>
Date: Tue, 2 May 2017 14:08:34 +1200
Subject: Changed events to use wayland functions.

---
 backend/CMakeLists.txt |  1 -
 backend/drm/backend.c  | 23 ++++++++++---
 backend/drm/drm.c      | 65 ++++++++++++++++++++---------------
 backend/drm/event.c    | 93 --------------------------------------------------
 backend/drm/udev.c     | 69 +++++++++++++++++++++++--------------
 5 files changed, 99 insertions(+), 152 deletions(-)
 delete mode 100644 backend/drm/event.c

(limited to 'backend')

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);
-}
-- 
cgit v1.2.3