diff options
Diffstat (limited to 'src/radeon_drm_queue.c')
-rw-r--r-- | src/radeon_drm_queue.c | 110 |
1 files changed, 87 insertions, 23 deletions
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); } /* |