diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2015-05-01 19:02:36 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2015-06-11 18:55:35 +0900 |
commit | 49f5b0bc301414df049e00d226034e3d6e56421b (patch) | |
tree | 3f62962e2187fe2ffaf6fd5770731ba22999e4ca /src | |
parent | afab7839fc15722dbaa7203d00fe7f6ce5336b9d (diff) |
Don't attempt a DRI2/Present page flip while the other one is flipping
Fixes corrupted display and hangs when switching between DRI2 and DRI3
fullscreen apps, e.g. a compositor using DRI3 and a fullscreen app using
DRI2 or vice versa.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/drmmode_display.h | 3 | ||||
-rw-r--r-- | src/radeon_dri2.c | 23 | ||||
-rw-r--r-- | src/radeon_present.c | 17 |
3 files changed, 36 insertions, 7 deletions
diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 2fdd3e0d..ca42c7d8 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -54,6 +54,9 @@ typedef struct { int count_crtcs; Bool delete_dp_12_displays; + + Bool dri2_flipping; + Bool present_flipping; } drmmode_rec, *drmmode_ptr; typedef struct { diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index a1f01455..7587a0cc 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -584,6 +584,7 @@ static void radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data) { + RADEONInfoPtr info = RADEONPTR(scrn); DRI2FrameEventPtr flip = event_data; unsigned tv_sec, tv_usec; DrawablePtr drawable; @@ -627,6 +628,7 @@ radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec, DRI2_FLIP_COMPLETE, flip->event_complete, flip->event_data); + info->drmmode.dri2_flipping = FALSE; break; default: xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__); @@ -644,6 +646,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client, DRI2BufferPtr back, DRI2SwapEventPtr func, void *data, unsigned int target_msc) { + RADEONInfoPtr info = RADEONPTR(scrn); struct dri2_buffer_priv *back_priv; struct radeon_bo *bo; DRI2FrameEventPtr flip_info; @@ -670,11 +673,16 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client, back_priv = back->driverPrivate; bo = radeon_get_pixmap_bo(back_priv->pixmap); - return radeon_do_pageflip(scrn, client, bo->handle, - RADEON_DRM_QUEUE_ID_DEFAULT, flip_info, - ref_crtc_hw_id, - radeon_dri2_flip_event_handler, - radeon_dri2_flip_event_abort); + if (radeon_do_pageflip(scrn, client, bo->handle, + RADEON_DRM_QUEUE_ID_DEFAULT, flip_info, + ref_crtc_hw_id, + radeon_dri2_flip_event_handler, + radeon_dri2_flip_event_abort)) { + info->drmmode.dri2_flipping = TRUE; + return TRUE; + } + + return FALSE; } static Bool @@ -742,8 +750,11 @@ static Bool can_flip(ScrnInfoPtr pScrn, DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) { + RADEONInfoPtr info = RADEONPTR(pScrn); + return draw->type == DRAWABLE_WINDOW && - RADEONPTR(pScrn)->allowPageFlip && + info->allowPageFlip && + !info->drmmode.present_flipping && pScrn->vtSema && DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back); diff --git a/src/radeon_present.c b/src/radeon_present.c index 26260446..c48df13b 100644 --- a/src/radeon_present.c +++ b/src/radeon_present.c @@ -50,6 +50,7 @@ struct radeon_present_vblank_event { uint64_t event_id; + xf86CrtcPtr crtc; }; static uint32_t crtc_select(int crtc_id) @@ -238,6 +239,9 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, if (!sync_flip) return FALSE; + if (info->drmmode.dri2_flipping) + return FALSE; + /* The kernel driver doesn't handle flipping between BOs with different * tiling parameters correctly yet */ @@ -266,8 +270,12 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, static void radeon_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data) { + RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_present_vblank_event *event = pageflip_data; + if (!event->crtc) + info->drmmode.present_flipping = FALSE; + present_event_notify(event->event_id, ust, msc); free(event); } @@ -293,6 +301,7 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, { ScreenPtr screen = crtc->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_present_vblank_event *event; xf86CrtcPtr xf86_crtc = crtc->devPrivate; int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1; @@ -310,6 +319,7 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, return FALSE; event->event_id = event_id; + event->crtc = xf86_crtc; ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, event_id, event, crtc_id, @@ -317,6 +327,8 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, radeon_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); + else + info->drmmode.present_flipping = TRUE; return ret; } @@ -328,6 +340,7 @@ static void radeon_present_unflip(ScreenPtr screen, uint64_t event_id) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONInfoPtr info = RADEONPTR(scrn); struct radeon_present_vblank_event *event; PixmapPtr pixmap = screen->GetScreenPixmap(screen); uint32_t handle; @@ -348,8 +361,10 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id) ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle, event_id, event, -1, radeon_present_flip_event, radeon_present_flip_abort); - if (!ret) + if (!ret) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n"); + info->drmmode.present_flipping = FALSE; + } } static present_screen_info_rec radeon_present_screen_info = { |