summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2018-08-16 17:44:45 +0200
committerMichel Dänzer <michel@daenzer.net>2018-08-17 09:59:42 +0200
commitba83a866af5a3784fc4822614375cc081e93197c (patch)
tree228610749b276700c692d573ee8364f6c208af2f
parent93621e408c17dd9e082236c17f051c06558d7f4d (diff)
Add radeon_drm_handle_event wrapper for drmHandleEvent
Instead of processing DRM events directly from drmHandleEvent's callbacks, there are three phases: 1. drmHandleEvent is called, and signalled events are re-queued to _signalled lists from its callbacks. 2. Signalled page flip completion events are processed. 3. Signalled vblank events are processed. This should make sure that we never call drmHandleEvent from one of its callbacks, which would usually result in blocking forever. (Ported from amdgpu commit 739181c8d3334ff14b5a607895dfdeb29b0d9020) Acked-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/drmmode_display.c13
-rw-r--r--src/radeon_drm_queue.c110
-rw-r--r--src/radeon_drm_queue.h1
-rw-r--r--src/radeon_present.c2
4 files changed, 96 insertions, 30 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 73eadeb1..b4c9783c 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2587,9 +2587,8 @@ static void
drm_wakeup_handler(pointer data, int err, pointer p)
#endif
{
- ScrnInfoPtr scrn = data;
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
- RADEONInfoPtr info = RADEONPTR(scrn);
+ drmmode_ptr drmmode = data;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn);
#if !HAVE_NOTIFY_FD
fd_set *read_mask = p;
@@ -2597,7 +2596,7 @@ drm_wakeup_handler(pointer data, int err, pointer p)
if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask))
#endif
{
- drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context);
+ radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context);
}
}
@@ -2747,11 +2746,13 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
info->drmmode_inited = TRUE;
if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
#if HAVE_NOTIFY_FD
- SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn);
+ SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ,
+ &info->drmmode);
#else
AddGeneralSocket(pRADEONEnt->fd);
RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
- drm_wakeup_handler, pScrn);
+ drm_wakeup_handler,
+ &info->drmmode);
#endif
pRADEONEnt->fd_wakeup_registered = serverGeneration;
pRADEONEnt->fd_wakeup_ref = 1;
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index 69474be2..3d2f4d15 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -40,6 +40,7 @@
struct radeon_drm_queue_entry {
struct xorg_list list;
+ uint64_t usec;
uint64_t id;
uintptr_t seq;
void *data;
@@ -47,36 +48,73 @@ struct radeon_drm_queue_entry {
xf86CrtcPtr crtc;
radeon_drm_handler_proc handler;
radeon_drm_abort_proc abort;
+ unsigned int frame;
};
static int radeon_drm_queue_refcnt;
static struct xorg_list radeon_drm_queue;
+static struct xorg_list radeon_drm_flip_signalled;
+static struct xorg_list radeon_drm_vblank_signalled;
static uintptr_t radeon_drm_queue_seq;
/*
- * Handle a DRM event
+ * Process a DRM event
*/
static void
-radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *user_ptr)
+radeon_drm_queue_handle_one(struct radeon_drm_queue_entry *e)
{
- uintptr_t seq = (uintptr_t)user_ptr;
- struct radeon_drm_queue_entry *e, *tmp;
-
- xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
- if (e->seq == seq) {
- xorg_list_del(&e->list);
- if (e->handler)
- e->handler(e->crtc, frame,
- (uint64_t)sec * 1000000 + usec,
- e->data);
- else
- e->abort(e->crtc, e->data);
- free(e);
- break;
- }
+ xorg_list_del(&e->list);
+ if (e->handler) {
+ e->handler(e->crtc, e->frame, e->usec, e->data);
+ } else
+ e->abort(e->crtc, e->data);
+ free(e);
+}
+
+static void
+radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
+ unsigned int sec, unsigned int usec, void *user_ptr)
+{
+ uintptr_t seq = (uintptr_t)user_ptr;
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->seq == seq) {
+ if (!e->handler) {
+ e->abort(e->crtc, e->data);
+ break;
+ }
+
+ xorg_list_del(&e->list);
+ e->usec = (uint64_t)sec * 1000000 + usec;
+ e->frame = frame;
+ xorg_list_append(&e->list, signalled);
+ break;
}
+ }
+}
+
+/*
+ * Signal a DRM page flip event
+ */
+static void
+radeon_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
+{
+ radeon_drm_queue_handler(&radeon_drm_flip_signalled, frame, sec, usec,
+ user_ptr);
+}
+
+/*
+ * Signal a DRM vblank event
+ */
+static void
+radeon_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
+{
+ radeon_drm_queue_handler(&radeon_drm_vblank_signalled, frame, sec, usec,
+ user_ptr);
}
/*
@@ -178,16 +216,40 @@ radeon_drm_abort_id(uint64_t id)
}
/*
+ * drmHandleEvent wrapper
+ */
+int
+radeon_drm_handle_event(int fd, drmEventContext *event_context)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+ int r;
+
+ r = drmHandleEvent(fd, event_context);
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
+ radeon_drm_queue_handle_one(e);
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list)
+ radeon_drm_queue_handle_one(e);
+
+ return r;
+}
+
+/*
* Wait for pending page flip on given CRTC to complete
*/
void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
+ radeon_drm_queue_handle_one(e);
- while (drmmode_crtc->flip_pending &&
- drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) > 0);
+ while (drmmode_crtc->flip_pending
+ && radeon_drm_handle_event(pRADEONEnt->fd,
+ &drmmode_crtc->drmmode->event_context) > 0);
}
/*
@@ -200,13 +262,15 @@ radeon_drm_queue_init(ScrnInfoPtr scrn)
drmmode_ptr drmmode = &info->drmmode;
drmmode->event_context.version = 2;
- drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
- drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
+ drmmode->event_context.vblank_handler = radeon_drm_vblank_handler;
+ drmmode->event_context.page_flip_handler = radeon_drm_page_flip_handler;
if (radeon_drm_queue_refcnt++)
return;
xorg_list_init(&radeon_drm_queue);
+ xorg_list_init(&radeon_drm_flip_signalled);
+ xorg_list_init(&radeon_drm_vblank_signalled);
}
/*
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index 96f88bd3..59343361 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -47,6 +47,7 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
void radeon_drm_abort_client(ClientPtr client);
void radeon_drm_abort_entry(uintptr_t seq);
void radeon_drm_abort_id(uint64_t id);
+int radeon_drm_handle_event(int fd, drmEventContext *event_context);
void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc);
void radeon_drm_queue_init(ScrnInfoPtr scrn);
void radeon_drm_queue_close(ScrnInfoPtr scrn);
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 2982d728..ffc14a0e 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -110,7 +110,7 @@ radeon_present_flush_drm_events(ScreenPtr screen)
if (r <= 0)
return 0;
- return drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) >= 0;
+ return radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context) >= 0;
}
/*