aboutsummaryrefslogtreecommitdiff
path: root/backend/drm/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/drm/event.c')
-rw-r--r--backend/drm/event.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/backend/drm/event.c b/backend/drm/event.c
new file mode 100644
index 00000000..f20cb282
--- /dev/null
+++ b/backend/drm/event.c
@@ -0,0 +1,91 @@
+#include "otd.h"
+#include "event.h"
+#include "drm.h"
+#include "udev.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <poll.h>
+
+static inline void event_swap(struct otd_event *a, struct otd_event *b)
+{
+ struct otd_event tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+bool otd_get_event(struct otd *otd, struct otd_event *restrict ret)
+{
+ struct pollfd fds[] = {
+ { .fd = otd->fd, .events = POLLIN },
+ { .fd = otd->udev_fd, .events = POLLIN },
+ };
+
+ while (poll(fds, 2, 0) > 0) {
+ if (fds[0].revents)
+ get_drm_event(otd);
+ if (fds[1].revents)
+ otd_udev_event(otd);
+ }
+
+ if (otd->event_len == 0) {
+ ret->type = OTD_EV_NONE;
+ ret->display = NULL;
+ return false;
+ }
+
+ struct otd_event *ev = otd->events;
+
+ // Downheap
+ *ret = ev[0];
+ ev[0] = ev[--otd->event_len];
+
+ size_t i = 0;
+ while (i < otd->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 event_add(struct otd *otd, struct otd_display *disp, enum otd_event_type type)
+{
+ if (type == OTD_EV_NONE)
+ return true;
+
+ if (otd->event_len == otd->event_cap) {
+ size_t new_size = (otd->event_cap == 0) ? 8 : otd->event_cap * 2;
+
+ struct otd_event *new = realloc(otd->events, sizeof *new * new_size);
+ if (!new) {
+ return false;
+ }
+
+ otd->event_cap = new_size;
+ otd->events = new;
+ }
+
+ struct otd_event *ev = otd->events;
+
+ // Upheap
+ size_t i = otd->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;
+}