summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c103
1 files changed, 91 insertions, 12 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index df3e43b..9d0cdec 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -49,6 +49,7 @@ typedef struct {
drmModeResPtr mode_res;
int cpp;
drmEventContext event_context;
+ struct xorg_list events;
#ifdef HAVE_LIBUDEV
struct udev_monitor *uevent_monitor;
#endif
@@ -115,6 +116,92 @@ drmmode_swap(ScrnInfoPtr scrn, uint32_t next, uint32_t *prev)
drmmode->fb_id = next;
}
+struct drmmode_event {
+ struct xorg_list head;
+ drmmode_ptr drmmode;
+ uint64_t name;
+ void (*func)(void *, uint64_t, uint64_t, uint32_t);
+};
+
+static void
+drmmode_event_handler(int fd, unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *event_data)
+{
+ const uint64_t ust = (uint64_t)tv_sec * 1000000 + tv_usec;
+ struct drmmode_event *e = event_data;
+
+ if (!xorg_list_is_empty(&e->head)) {
+ xorg_list_del(&e->head);
+ e->func((void *)(e + 1), e->name, ust, frame);
+ }
+
+ free(e);
+}
+
+void
+drmmode_event_abort(ScrnInfoPtr scrn, uint64_t name, bool pending)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(scrn);
+ struct drmmode_event *e, *t;
+
+ xorg_list_for_each_entry_safe(e, t, &drmmode->events, head) {
+ if (e->name == name) {
+ xorg_list_del(&e->head);
+ if (!pending)
+ free(e);
+ break;
+ }
+ }
+}
+
+void *
+drmmode_event_queue(ScrnInfoPtr scrn, uint64_t name, unsigned size,
+ void (*func)(void *, uint64_t, uint64_t, uint32_t),
+ void **event_data)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(scrn);
+ struct drmmode_event *e;
+
+ e = *event_data = calloc(1, sizeof(*e) + size);
+ if (e) {
+ e->drmmode = drmmode;
+ e->name = name;
+ e->func = func;
+ xorg_list_add(&e->head, &drmmode->events);
+ return (void *)(e + 1);
+ }
+
+ return NULL;
+}
+
+int
+drmmode_event_flush(ScrnInfoPtr scrn)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(scrn);
+ return drmHandleEvent(drmmode->fd, &drmmode->event_context);
+}
+
+void
+drmmode_event_fini(ScrnInfoPtr scrn)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(scrn);
+ struct drmmode_event *e, *t;
+
+ xorg_list_for_each_entry_safe(e, t, &drmmode->events, head) {
+ xorg_list_del(&e->head);
+ }
+}
+
+void
+drmmode_event_init(ScrnInfoPtr scrn)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(scrn);
+ drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
+ drmmode->event_context.vblank_handler = drmmode_event_handler;
+ drmmode->event_context.page_flip_handler = drmmode_event_handler;
+ xorg_list_init(&drmmode->events);
+}
+
static PixmapPtr
drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth,
int bpp, int pitch, struct nouveau_bo *bo, void *data)
@@ -1451,17 +1538,9 @@ drmmode_screen_init(ScreenPtr pScreen)
drmmode_ptr drmmode = drmmode_from_scrn(scrn);
drmmode_uevent_init(scrn);
-
- /* Plug in a vblank event handler */
- drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
- drmmode->event_context.vblank_handler = nouveau_dri2_vblank_handler;
-
- /* Plug in a pageflip completion event handler */
- drmmode->event_context.page_flip_handler = drmmode_flip_handler;
+ drmmode_event_init(scrn);
AddGeneralSocket(drmmode->fd);
-
- /* Register a wakeup handler to get informed on DRM events */
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
drmmode_wakeup_handler, scrn);
}
@@ -1472,10 +1551,10 @@ drmmode_screen_fini(ScreenPtr pScreen)
ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
drmmode_ptr drmmode = drmmode_from_scrn(scrn);
- drmmode_uevent_fini(scrn);
-
- /* Register a wakeup handler to get informed on DRM events */
RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
drmmode_wakeup_handler, scrn);
RemoveGeneralSocket(drmmode->fd);
+
+ drmmode_event_fini(scrn);
+ drmmode_uevent_fini(scrn);
}