From d16b2977f6b156e5b3a4ceb028cfbe70b9a350c1 Mon Sep 17 00:00:00 2001
From: Scott Anderson <ascent12@hotmail.com>
Date: Sat, 26 Aug 2017 14:50:16 +1200
Subject: Remove single GPU assumptions from wlr_session

---
 backend/session/direct.c      | 26 ++++++++++++++++++++------
 backend/session/logind.c      | 34 ++++++++++++++++++++++------------
 backend/session/session.c     | 20 ++++++--------------
 include/wlr/backend/session.h |  9 ++++++++-
 4 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/backend/session/direct.c b/backend/session/direct.c
index 4eff10e1..942dc552 100644
--- a/backend/session/direct.c
+++ b/backend/session/direct.c
@@ -48,7 +48,7 @@ static int direct_session_open(struct wlr_session *base, const char *path) {
 	}
 
 	if (major(st.st_rdev) == DRM_MAJOR) {
-		session->base.drm_fd = fd;
+		direct_ipc_setmaster(session->sock, fd);
 	}
 
 	return fd;
@@ -65,8 +65,7 @@ static void direct_session_close(struct wlr_session *base, int fd) {
 	}
 
 	if (major(st.st_rdev) == DRM_MAJOR) {
-		direct_ipc_dropmaster(session->sock, session->base.drm_fd);
-		session->base.drm_fd = -1;
+		direct_ipc_dropmaster(session->sock, fd);
 	} else if (major(st.st_rdev) == INPUT_MAJOR) {
 		ioctl(fd, EVIOCREVOKE, 0);
 	}
@@ -109,11 +108,27 @@ static int vt_handler(int signo, void *data) {
 	if (session->base.active) {
 		session->base.active = false;
 		wl_signal_emit(&session->base.session_signal, session);
-		direct_ipc_dropmaster(session->sock, session->base.drm_fd);
+
+		struct wlr_device *dev;
+		wl_list_for_each(dev, &session->base.devices, link) {
+			if (major(dev->dev) == DRM_MAJOR) {
+				direct_ipc_dropmaster(session->sock,
+					dev->fd);
+			}
+		}
+
 		ioctl(session->tty_fd, VT_RELDISP, 1);
 	} else {
 		ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ);
-		direct_ipc_setmaster(session->sock, session->base.drm_fd);
+
+		struct wlr_device *dev;
+		wl_list_for_each(dev, &session->base.devices, link) {
+			if (major(dev->dev) == DRM_MAJOR) {
+				direct_ipc_setmaster(session->sock,
+					dev->fd);
+			}
+		}
+
 		session->base.active = true;
 		wl_signal_emit(&session->base.session_signal, session);
 	}
@@ -221,7 +236,6 @@ static struct wlr_session *direct_session_create(struct wl_display *disp) {
 	wlr_log(L_INFO, "Successfully loaded direct session");
 
 	snprintf(session->base.seat, sizeof(session->base.seat), "%s", seat);
-	session->base.drm_fd = -1;
 	session->base.impl = &session_direct;
 	return &session->base;
 
diff --git a/backend/session/logind.c b/backend/session/logind.c
index c5465936..3b237360 100644
--- a/backend/session/logind.c
+++ b/backend/session/logind.c
@@ -1,4 +1,5 @@
 #define _POSIX_C_SOURCE 200809L
+#include <assert.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -67,10 +68,6 @@ static int logind_take_device(struct wlr_session *base, const char *path) {
 		goto error;
 	}
 
-	if (major(st.st_rdev) == DRM_MAJOR) {
-		session->base.drm_fd = fd;
-	}
-
 error:
 	sd_bus_error_free(&error);
 	sd_bus_message_unref(msg);
@@ -97,10 +94,6 @@ static void logind_release_device(struct wlr_session *base, int fd) {
 		wlr_log(L_ERROR, "Failed to release device '%d'", fd);
 	}
 
-	if (major(st.st_rdev) == DRM_MAJOR) {
-		session->base.drm_fd = -1;
-	}
-
 	sd_bus_error_free(&error);
 	sd_bus_message_unref(msg);
 }
@@ -221,6 +214,20 @@ static int session_removed(sd_bus_message *msg, void *userdata, sd_bus_error *re
 	return 0;
 }
 
+static struct wlr_device *find_device(struct wlr_session *session, dev_t devnum) {
+	struct wlr_device *dev;
+
+	wl_list_for_each(dev, &session->devices, link) {
+		if (dev->dev == devnum) {
+			return dev;
+		}
+	}
+
+	wlr_log(L_ERROR, "Tried to use dev_t %lu not opened by session",
+		(unsigned long)devnum);
+	assert(0);
+}
+
 static int pause_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) {
 	struct logind_session *session = userdata;
 	int ret;
@@ -267,9 +274,13 @@ static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_
 	}
 
 	if (major == DRM_MAJOR) {
-		dup2(fd, session->base.drm_fd);
-		session->base.active = true;
-		wl_signal_emit(&session->base.session_signal, session);
+		struct wlr_device *dev = find_device(&session->base, makedev(major, minor));
+		dup2(fd, dev->fd);
+
+		if (!session->base.active) {
+			session->base.active = true;
+			wl_signal_emit(&session->base.session_signal, session);
+		}
 	}
 
 error:
@@ -374,7 +385,6 @@ static struct wlr_session *logind_session_create(struct wl_display *disp) {
 
 	wlr_log(L_INFO, "Successfully loaded logind session");
 
-	session->base.drm_fd = -1;
 	session->base.impl = &session_logind;
 	return &session->base;
 
diff --git a/backend/session/session.c b/backend/session/session.c
index 26b9aa92..c9bc1397 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -12,14 +12,6 @@
 #include <wlr/backend/session/interface.h>
 #include <wlr/util/log.h>
 
-struct device {
-	int fd;
-	dev_t dev;
-	struct wl_signal signal;
-
-	struct wl_list link;
-};
-
 extern const struct session_impl session_logind;
 extern const struct session_impl session_direct;
 
@@ -49,7 +41,7 @@ static int udev_event(int fd, uint32_t mask, void *data) {
 	}
 
 	dev_t devnum = udev_device_get_devnum(udev_dev);
-	struct device *dev;
+	struct wlr_device *dev;
 
 	wl_list_for_each(dev, &session->devices, link) {
 		if (dev->dev == devnum) {
@@ -134,7 +126,7 @@ int wlr_session_open_file(struct wlr_session *session, const char *path) {
 		return fd;
 	}
 
-	struct device *dev = malloc(sizeof(*dev));
+	struct wlr_device *dev = malloc(sizeof(*dev));
 	if (!dev) {
 		wlr_log_errno(L_ERROR, "Allocation failed");
 		goto error;
@@ -158,8 +150,8 @@ error:
 	return fd;
 }
 
-static struct device *find_device(struct wlr_session *session, int fd) {
-	struct device *dev;
+static struct wlr_device *find_device(struct wlr_session *session, int fd) {
+	struct wlr_device *dev;
 
 	wl_list_for_each(dev, &session->devices, link) {
 		if (dev->fd == fd) {
@@ -172,7 +164,7 @@ static struct device *find_device(struct wlr_session *session, int fd) {
 }
 
 void wlr_session_close_file(struct wlr_session *session, int fd) {
-	struct device *dev = find_device(session, fd);
+	struct wlr_device *dev = find_device(session, fd);
 
 	session->impl->close(session, fd);
 	wl_list_remove(&dev->link);
@@ -181,7 +173,7 @@ void wlr_session_close_file(struct wlr_session *session, int fd) {
 
 void wlr_session_signal_add(struct wlr_session *session, int fd,
 		struct wl_listener *listener) {
-	struct device *dev = find_device(session, fd);
+	struct wlr_device *dev = find_device(session, fd);
 
 	wl_signal_add(&dev->signal, listener);
 }
diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h
index fbdc97fc..04e701b0 100644
--- a/include/wlr/backend/session.h
+++ b/include/wlr/backend/session.h
@@ -8,6 +8,14 @@
 
 struct session_impl;
 
+struct wlr_device {
+	int fd;
+	dev_t dev;
+	struct wl_signal signal;
+
+	struct wl_list link;
+};
+
 struct wlr_session {
 	const struct session_impl *impl;
 	/*
@@ -17,7 +25,6 @@ struct wlr_session {
 	struct wl_signal session_signal;
 	bool active;
 
-	int drm_fd;
 	unsigned vtnr;
 	char seat[8];
 
-- 
cgit v1.2.3