diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2015-06-01 17:32:56 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2015-06-08 17:04:02 +0900 |
commit | 9a554a683b970660b467566cf05b921393705a20 (patch) | |
tree | 5783e5a2c49a090beb748d9bc6bdd88fc78ea723 /src | |
parent | e6164ad340f65ff8ee6f6a6934302591af875a43 (diff) |
DRI2: Use helper functions for DRM event queue management
This is mostly in preparation for Present support, but it also simplifies
the DRI2 specific code a little.
(Cherry picked from radeon commit 6c3a721cde9317233072b573f9502348dcd21b16)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/amdgpu_dri2.c | 271 | ||||
-rw-r--r-- | src/amdgpu_dri2.h | 37 | ||||
-rw-r--r-- | src/drmmode_display.c | 90 | ||||
-rw-r--r-- | src/drmmode_display.h | 13 |
4 files changed, 165 insertions, 246 deletions
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c index c139dec..95db216 100644 --- a/src/amdgpu_dri2.c +++ b/src/amdgpu_dri2.c @@ -49,6 +49,8 @@ #include "amdgpu_list.h" +#include <xf86Priv.h> + #if DRI2INFOREC_VERSION >= 9 #define USE_DRI2_PRIME #endif @@ -370,65 +372,20 @@ typedef struct _DRI2FrameEvent { XID drawable_id; ClientPtr client; enum DRI2FrameEventType type; - int frame; + unsigned frame; xf86CrtcPtr crtc; + OsTimerPtr timer; + struct amdgpu_drm_queue_entry *drm_queue; /* for swaps & flips only */ DRI2SwapEventPtr event_complete; void *event_data; DRI2BufferPtr front; DRI2BufferPtr back; - - Bool valid; - - struct xorg_list link; } DRI2FrameEventRec, *DRI2FrameEventPtr; -typedef struct _DRI2ClientEvents { - struct xorg_list reference_list; -} DRI2ClientEventsRec, *DRI2ClientEventsPtr; - -#if HAS_DEVPRIVATEKEYREC - static int DRI2InfoCnt; -static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec; -#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec) - -#else - -static int DRI2ClientEventsPrivateKeyIndex; -DevPrivateKey DRI2ClientEventsPrivateKey = &DRI2ClientEventsPrivateKeyIndex; - -#endif /* HAS_DEVPRIVATEKEYREC */ - -#define GetDRI2ClientEvents(pClient) ((DRI2ClientEventsPtr) \ - dixLookupPrivate(&(pClient)->devPrivates, DRI2ClientEventsPrivateKey)) - -static int ListAddDRI2ClientEvents(ClientPtr client, struct xorg_list *entry) -{ - DRI2ClientEventsPtr pClientPriv; - pClientPriv = GetDRI2ClientEvents(client); - - if (!pClientPriv) { - return BadAlloc; - } - - xorg_list_add(entry, &pClientPriv->reference_list); - return 0; -} - -static void ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry) -{ - DRI2ClientEventsPtr pClientPriv; - pClientPriv = GetDRI2ClientEvents(client); - - if (!pClientPriv) { - return; - } - xorg_list_del(entry); -} - static void amdgpu_dri2_ref_buffer(BufferPtr buffer) { struct dri2_buffer_priv *private = buffer->driverPrivate; @@ -448,30 +405,13 @@ static void amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback, pointer data, pointer calldata) { - DRI2ClientEventsPtr pClientEventsPriv; - DRI2FrameEventPtr ref; NewClientInfoRec *clientinfo = calldata; ClientPtr pClient = clientinfo->client; - pClientEventsPriv = GetDRI2ClientEvents(pClient); switch (pClient->clientState) { - case ClientStateInitial: - xorg_list_init(&pClientEventsPriv->reference_list); - break; - case ClientStateRunning: - break; - case ClientStateRetained: case ClientStateGone: - if (pClientEventsPriv) { - xorg_list_for_each_entry(ref, - &pClientEventsPriv-> - reference_list, link) { - ref->valid = FALSE; - amdgpu_dri2_unref_buffer(ref->front); - amdgpu_dri2_unref_buffer(ref->back); - } - } + amdgpu_drm_abort_client(pClient); break; default: break; @@ -497,37 +437,42 @@ xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled) return NULL; } -void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) +static void +amdgpu_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data) +{ + free(event_data); +} + +static void +amdgpu_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, + void *event_data) { DRI2FrameEventPtr flip = event_data; + unsigned tv_sec, tv_usec; DrawablePtr drawable; ScreenPtr screen; - ScrnInfoPtr scrn; int status; PixmapPtr pixmap; status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient, M_ANY, DixWriteAccess); - if (status != Success) { - free(flip); - return; - } - if (!flip->crtc) { - free(flip); - return; - } - frame += amdgpu_get_interpolated_vblanks(flip->crtc); + if (status != Success) + goto abort; - screen = drawable->pScreen; - scrn = xf86ScreenToScrn(screen); + if (!flip->crtc) + goto abort; + frame += amdgpu_get_interpolated_vblanks(flip->crtc); + screen = scrn->pScreen; pixmap = screen->GetScreenPixmap(screen); xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n", __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind / 4); + tv_sec = usec / 1000000; + tv_usec = usec % 1000000; + /* We assume our flips arrive in order, so we don't check the frame */ switch (flip->type) { case DRI2_SWAP: @@ -537,7 +482,7 @@ void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, */ if ((frame < flip->frame) && (flip->frame - frame < 5)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "%s: Pageflip completion event has impossible msc %d < target_msc %d\n", + "%s: Pageflip completion event has impossible msc %u < target_msc %u\n", __func__, frame, flip->frame); /* All-Zero values signal failure of (msc, ust) timestamping to client. */ frame = tv_sec = tv_usec = 0; @@ -554,7 +499,8 @@ void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, break; } - free(flip); +abort: + amdgpu_dri2_flip_event_abort(scrn, event_data); } static Bool @@ -589,7 +535,10 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client, back_priv = back->driverPrivate; bo = amdgpu_get_pixmap_bo(back_priv->pixmap); - return amdgpu_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id); + return amdgpu_do_pageflip(scrn, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT, + flip_info, ref_crtc_hw_id, + amdgpu_dri2_flip_event_handler, + amdgpu_dri2_flip_event_abort); } static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) @@ -719,31 +668,36 @@ amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DamageRegionProcessPending(&front_priv->pixmap->drawable); } -void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) +static void amdgpu_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data) +{ + DRI2FrameEventPtr event = event_data; + + TimerCancel(event->timer); + TimerFree(event->timer); + amdgpu_dri2_unref_buffer(event->front); + amdgpu_dri2_unref_buffer(event->back); + free(event); +} + +static void amdgpu_dri2_frame_event_handler(ScrnInfoPtr scrn, uint32_t seq, + uint64_t usec, void *event_data) { DRI2FrameEventPtr event = event_data; DrawablePtr drawable; - ScreenPtr screen; - ScrnInfoPtr scrn; int status; int swap_type; BoxRec box; RegionRec region; - if (!event->valid) + if (!event->crtc) goto cleanup; status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, M_ANY, DixWriteAccess); if (status != Success) goto cleanup; - if (!event->crtc) - goto cleanup; - frame += amdgpu_get_interpolated_vblanks(event->crtc); - screen = drawable->pScreen; - scrn = xf86ScreenToScrn(screen); + seq += amdgpu_get_interpolated_vblanks(event->crtc); switch (event->type) { case DRI2_FLIP: @@ -778,14 +732,14 @@ void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, swap_type = DRI2_BLIT_COMPLETE; } - DRI2SwapComplete(event->client, drawable, frame, tv_sec, - tv_usec, swap_type, event->event_complete, + DRI2SwapComplete(event->client, drawable, seq, usec / 1000000, + usec % 1000000, swap_type, event->event_complete, event->event_data); break; case DRI2_WAITMSC: - DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, - tv_usec); + DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000, + usec % 1000000); break; default: /* Unknown type */ @@ -795,12 +749,7 @@ void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, } cleanup: - if (event->valid) { - amdgpu_dri2_unref_buffer(event->front); - amdgpu_dri2_unref_buffer(event->back); - ListDelDRI2ClientEvents(event->client, &event->link); - } - free(event); + amdgpu_dri2_frame_event_abort(scrn, event_data); } drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc) @@ -972,17 +921,13 @@ static CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) { DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data; - DrawablePtr drawable; - ScreenPtr screen; + xf86CrtcPtr crtc = event_info->crtc; ScrnInfoPtr scrn; AMDGPUInfoPtr info; - int status; CARD64 drm_now; int ret; - unsigned int tv_sec, tv_usec; CARD64 delta_t, delta_seq, frame; drmmode_crtc_private_ptr drmmode_crtc; - TimerFree(timer); /* * This is emulated event, so its time is current time, which we @@ -993,29 +938,26 @@ CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) */ if (!event_info->crtc) { ErrorF("%s no crtc\n", __func__); - amdgpu_dri2_frame_event_handler(0, 0, 0, data); + if (event_info->drm_queue) + amdgpu_drm_abort_entry(event_info->drm_queue); + else + amdgpu_dri2_frame_event_abort(NULL, data); return 0; } - status = - dixLookupDrawable(&drawable, event_info->drawable_id, serverClient, - M_ANY, DixWriteAccess); - if (status != Success) { - ErrorF("%s cannot lookup drawable\n", __func__); - amdgpu_dri2_frame_event_handler(0, 0, 0, data); - return 0; - } - screen = drawable->pScreen; - scrn = xf86ScreenToScrn(screen); + + scrn = crtc->scrn; info = AMDGPUPTR(scrn); ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); - amdgpu_dri2_frame_event_handler(0, 0, 0, data); + if (event_info->drm_queue) + amdgpu_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0, + event_info->drm_queue); + else + amdgpu_dri2_frame_event_handler(scrn, 0, 0, data); return 0; } - tv_sec = (unsigned int)(drm_now / 1000000); - tv_usec = (unsigned int)(drm_now - (CARD64) tv_sec * 1000000); /* * calculate the frame number from current time * that would come from CRTC if it were running @@ -1025,21 +967,22 @@ CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) delta_seq = delta_t * drmmode_crtc->dpms_last_fps; delta_seq /= 1000000; frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq; - frame &= 0xffffffff; - amdgpu_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec, - data); + if (event_info->drm_queue) + amdgpu_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000, + drm_now % 1000000, event_info->drm_queue); + else + amdgpu_dri2_frame_event_handler(scrn, frame, drm_now, data); return 0; } static -void amdgpu_dri2_schedule_event(CARD32 delay, pointer arg) +void amdgpu_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info) { - OsTimerPtr timer; - - timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event, arg); + event_info->timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event, + event_info); if (delay == 0) { CARD32 now = GetTimeInMillis(); - amdgpu_dri2_deferred_event(timer, now, arg); + amdgpu_dri2_deferred_event(event_info->timer, now, event_info); } } @@ -1057,6 +1000,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, ScrnInfoPtr scrn = xf86ScreenToScrn(screen); AMDGPUInfoPtr info = AMDGPUPTR(scrn); DRI2FrameEventPtr wait_info = NULL; + struct amdgpu_drm_queue_entry *wait = NULL; xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE); drmVBlank vbl; int ret; @@ -1079,17 +1023,8 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, wait_info->drawable_id = draw->id; wait_info->client = client; wait_info->type = DRI2_WAITMSC; - wait_info->valid = TRUE; wait_info->crtc = crtc; - if (ListAddDRI2ClientEvents(client, &wait_info->link)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "add events to client private failed.\n"); - free(wait_info); - wait_info = NULL; - goto out_complete; - } - /* * CRTC is in DPMS off state, calculate wait time from current time, * target_msc and last vblank time/sequence when CRTC was turned off @@ -1118,6 +1053,16 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, vbl.reply.sequence + amdgpu_get_interpolated_vblanks(crtc); current_msc &= 0xffffffff; + wait = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT, + wait_info, amdgpu_dri2_frame_event_handler, + amdgpu_dri2_frame_event_abort); + if (!wait) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Allocating DRM queue event entry failed.\n"); + goto out_complete; + } + wait_info->drm_queue = wait; + /* * If divisor is zero, or current_msc is smaller than target_msc, * we just need to make sure target_msc passes before waking up the @@ -1136,7 +1081,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); vbl.request.sequence = target_msc; vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc); - vbl.request.signal = (unsigned long)wait_info; + vbl.request.signal = (unsigned long)wait; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1169,7 +1114,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, vbl.request.sequence += divisor; vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc); - vbl.request.signal = (unsigned long)wait_info; + vbl.request.signal = (unsigned long)wait; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1182,11 +1127,8 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, return TRUE; out_complete: - if (wait_info) { - ListDelDRI2ClientEvents(wait_info->client, &wait_info->link); - free(wait_info); - } - DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); + if (wait_info) + amdgpu_dri2_deferred_event(NULL, 0, wait_info); return TRUE; } @@ -1223,6 +1165,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, drmVBlank vbl; int ret, flip = 0; DRI2FrameEventPtr swap_info = NULL; + struct amdgpu_drm_queue_entry *swap; CARD64 current_msc; BoxRec box; RegionRec region; @@ -1255,15 +1198,17 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, swap_info->event_data = data; swap_info->front = front; swap_info->back = back; - swap_info->valid = TRUE; swap_info->crtc = crtc; - if (ListAddDRI2ClientEvents(client, &swap_info->link)) { + + swap = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT, + swap_info, amdgpu_dri2_frame_event_handler, + amdgpu_dri2_frame_event_abort); + if (!swap) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "add events to client private failed.\n"); - free(swap_info); - swap_info = NULL; + "Allocating DRM queue entry failed.\n"); goto blit_fallback; } + swap_info->drm_queue = swap; /* * CRTC is in DPMS off state, fallback to blit, but calculate @@ -1331,7 +1276,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, vbl.request.sequence = *target_msc; vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc); - vbl.request.signal = (unsigned long)swap_info; + vbl.request.signal = (unsigned long)swap; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1378,7 +1323,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, /* Account for 1 frame extra pageflip delay if flip > 0 */ vbl.request.sequence -= flip; - vbl.request.signal = (unsigned long)swap_info; + vbl.request.signal = (unsigned long)swap; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -1472,26 +1417,6 @@ Bool amdgpu_dri2_screen_init(ScreenPtr pScreen) driverNames[0] = driverNames[1] = dri2_info.driverName; if (DRI2InfoCnt == 0) { -#if HAS_DIXREGISTERPRIVATEKEY - if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey, - PRIVATE_CLIENT, - sizeof(DRI2ClientEventsRec))) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "DRI2 registering " - "private key to client failed\n"); - return FALSE; - } -#else - if (!dixRequestPrivate(DRI2ClientEventsPrivateKey, - sizeof(DRI2ClientEventsRec))) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "DRI2 requesting " - "private key to client failed\n"); - return FALSE; - } -#endif - AddCallback(&ClientStateCallback, amdgpu_dri2_client_state_changed, 0); } diff --git a/src/amdgpu_dri2.h b/src/amdgpu_dri2.h index 3ca9dd2..d9bec91 100644 --- a/src/amdgpu_dri2.h +++ b/src/amdgpu_dri2.h @@ -43,12 +43,6 @@ struct amdgpu_dri2 { Bool amdgpu_dri2_screen_init(ScreenPtr pScreen); void amdgpu_dri2_close_screen(ScreenPtr pScreen); -int drmmode_get_crtc_id(xf86CrtcPtr crtc); -void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); -void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); - #else static inline Bool amdgpu_dri2_screen_init(ScreenPtr pScreen) @@ -60,37 +54,6 @@ static inline void amdgpu_dri2_close_screen(ScreenPtr pScreen) { } -static inline void -amdgpu_dri2_dummy_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data, - const char *name) -{ - static Bool warned; - - if (!warned) { - ErrorF("%s called but DRI2 disabled at build time\n", name); - warned = TRUE; - } - - free(event_data); -} - -static inline void -amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - amdgpu_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data, - __func__); -} - -static inline void -amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - amdgpu_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data, - __func__); -} - #endif #endif /* AMDGPU_DRI2_H */ diff --git a/src/drmmode_display.c b/src/drmmode_display.c index bb93833..aa7c8c4 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -1391,46 +1391,52 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { }; static void -drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) +drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier) { - amdgpu_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data); + drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + + free(flipcarrier); + + if (--flipdata->flip_count > 0) + return; + + /* Release framebuffer */ + drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id); + + free(flipdata); +} + +static void +drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data) +{ + drmmode_flipevtcarrier_ptr flipcarrier = event_data; + drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; + + if (flipdata->flip_count == 1) + flipcarrier->abort(scrn, flipdata->event_data); + + drmmode_flip_free(flipcarrier); } static void -drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) +drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data) { drmmode_flipevtcarrier_ptr flipcarrier = event_data; drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; - drmmode_ptr drmmode = flipdata->drmmode; /* Is this the event whose info shall be delivered to higher level? */ if (flipcarrier->dispatch_me) { /* Yes: Cache msc, ust for later delivery. */ flipdata->fe_frame = frame; - flipdata->fe_tv_sec = tv_sec; - flipdata->fe_tv_usec = tv_usec; + flipdata->fe_usec = usec; } - free(flipcarrier); - - /* Last crtc completed flip? */ - flipdata->flip_count--; - if (flipdata->flip_count > 0) - return; - - /* Release framebuffer */ - drmModeRmFB(drmmode->fd, flipdata->old_fb_id); - - if (flipdata->event_data == NULL) - return; /* Deliver cached msc, ust from reference crtc to flip event handler */ - amdgpu_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, - flipdata->fe_tv_usec, - flipdata->event_data); + if (flipdata->event_data && flipdata->flip_count == 1) + flipcarrier->handler(scrn, flipdata->fe_frame, flipdata->fe_usec, + flipdata->event_data); - free(flipdata); + drmmode_flip_free(flipcarrier); } static void drm_wakeup_handler(pointer data, int err, pointer p) @@ -1475,8 +1481,8 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) xf86InitialConfiguration(pScrn, TRUE); drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; - drmmode->event_context.vblank_handler = drmmode_vblank_handler; - drmmode->event_context.page_flip_handler = drmmode_flip_handler; + drmmode->event_context.vblank_handler = amdgpu_drm_queue_handler; + drmmode->event_context.page_flip_handler = amdgpu_drm_queue_handler; return TRUE; } @@ -1743,8 +1749,10 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) #endif } -Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front, - void *data, int ref_crtc_hw_id) +Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, + struct amdgpu_buffer *new_front, uint64_t id, void *data, + int ref_crtc_hw_id, amdgpu_drm_handler_proc handler, + amdgpu_drm_abort_proc abort) { AMDGPUInfoPtr info = AMDGPUPTR(scrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); @@ -1754,7 +1762,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front, int i, old_fb_id; int height, emitted = 0; drmmode_flipdata_ptr flipdata; - drmmode_flipevtcarrier_ptr flipcarrier; + drmmode_flipevtcarrier_ptr flipcarrier = NULL; + struct amdgpu_drm_queue_entry *drm_queue = 0; union gbm_bo_handle bo_handle; uint32_t handle; @@ -1823,10 +1832,22 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front, flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id); flipcarrier->flipdata = flipdata; + flipcarrier->handler = handler; + flipcarrier->abort = abort; + + drm_queue = amdgpu_drm_queue_alloc(scrn, client, id, + flipcarrier, + drmmode_flip_handler, + drmmode_flip_abort); + if (!drm_queue) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Allocating DRM queue event entry failed.\n"); + goto error_undo; + } - if (drmModePageFlip - (drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) { + if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, + drm_queue)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n", strerror(errno)); free(flipcarrier); @@ -1841,6 +1862,11 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front, return TRUE; error_undo: + if (drm_queue) + amdgpu_drm_abort_entry(drm_queue); + else + drmmode_flip_abort(scrn, flipcarrier); + drmModeRmFB(drmmode->fd, drmmode->fb_id); drmmode->fb_id = old_fb_id; diff --git a/src/drmmode_display.h b/src/drmmode_display.h index c2ec683..9cf6932 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -32,6 +32,7 @@ #include "libudev.h" #endif +#include "amdgpu_drm_queue.h" #include "amdgpu_probe.h" #include "amdgpu.h" @@ -59,13 +60,14 @@ typedef struct { int flip_count; void *event_data; unsigned int fe_frame; - unsigned int fe_tv_sec; - unsigned int fe_tv_usec; + uint64_t fe_usec; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; typedef struct { drmmode_flipdata_ptr flipdata; Bool dispatch_me; + amdgpu_drm_handler_proc handler; + amdgpu_drm_abort_proc abort; } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr; typedef struct { @@ -117,9 +119,12 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode); extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode); +extern int drmmode_get_crtc_id(xf86CrtcPtr crtc); extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe); -Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, struct amdgpu_buffer *new_front, - void *data, int ref_crtc_hw_id); +Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, + struct amdgpu_buffer *new_front, uint64_t id, void *data, + int ref_crtc_hw_id, amdgpu_drm_handler_proc handler, + amdgpu_drm_abort_proc abort); int drmmode_get_current_ust(int drm_fd, CARD64 * ust); #endif |