diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2015-10-05 10:37:50 -0400 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2015-10-06 16:47:22 +0900 |
commit | bac21dfc8e60a07f08158b13fab1f3a9b9d27d1b (patch) | |
tree | f711b54a27ac314fda5cd03c6bff3c0900d774c2 | |
parent | a5f7f2e68bad1935f5ad52286033237467f77302 (diff) |
Don't attempt a DRI2/Present page flip while the other one is flipping
Based on radeon commit 49f5b0bc301414df049e00d226034e3d6e56421b
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.
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
-rw-r--r-- | src/amdgpu_dri2.c | 20 | ||||
-rw-r--r-- | src/amdgpu_present.c | 17 | ||||
-rw-r--r-- | src/drmmode_display.h | 3 |
3 files changed, 34 insertions, 6 deletions
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c index 1370551..756d6ad 100644 --- a/src/amdgpu_dri2.c +++ b/src/amdgpu_dri2.c @@ -528,6 +528,7 @@ static void amdgpu_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data) { + AMDGPUInfoPtr info = AMDGPUPTR(scrn); DRI2FrameEventPtr flip = event_data; unsigned tv_sec, tv_usec; DrawablePtr drawable; @@ -572,6 +573,7 @@ amdgpu_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, @@ -590,6 +592,7 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client, DRI2BufferPtr back, DRI2SwapEventPtr func, void *data, unsigned int target_msc) { + AMDGPUInfoPtr info = AMDGPUPTR(scrn); struct dri2_buffer_priv *back_priv; struct amdgpu_buffer *bo = NULL; DRI2FrameEventPtr flip_info; @@ -616,10 +619,14 @@ 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, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT, - flip_info, ref_crtc_hw_id, - amdgpu_dri2_flip_event_handler, - amdgpu_dri2_flip_event_abort); + if (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)) { + info->drmmode.dri2_flipping = TRUE; + return TRUE; + } + return FALSE; } static Bool update_front(DrawablePtr draw, DRI2BufferPtr front) @@ -698,8 +705,11 @@ static Bool can_flip(ScrnInfoPtr pScrn, DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) { + AMDGPUInfoPtr info = AMDGPUPTR(pScrn); + return draw->type == DRAWABLE_WINDOW && - AMDGPUPTR(pScrn)->allowPageFlip && + info->allowPageFlip && + !info->drmmode.present_flipping && pScrn->vtSema && DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back); } diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c index 75a4ba3..3db8cad 100644 --- a/src/amdgpu_present.c +++ b/src/amdgpu_present.c @@ -50,6 +50,7 @@ struct amdgpu_present_vblank_event { uint64_t event_id; + xf86CrtcPtr crtc; }; static uint32_t crtc_select(int crtc_id) @@ -222,6 +223,9 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, if (!sync_flip) return FALSE; + if (info->drmmode.dri2_flipping) + return FALSE; + if (crtc) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; @@ -242,8 +246,12 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, static void amdgpu_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data) { + AMDGPUInfoPtr info = AMDGPUPTR(scrn); struct amdgpu_present_vblank_event *event = pageflip_data; + if (!event->crtc) + info->drmmode.present_flipping = FALSE; + present_event_notify(event->event_id, ust, msc); free(event); } @@ -269,6 +277,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, { ScreenPtr screen = crtc->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + AMDGPUInfoPtr info = AMDGPUPTR(scrn); struct amdgpu_present_vblank_event *event; xf86CrtcPtr xf86_crtc = crtc->devPrivate; int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1; @@ -287,6 +296,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, return FALSE; event->event_id = event_id; + event->crtc = xf86_crtc; ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo, event_id, event, crtc_id, @@ -294,6 +304,8 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, amdgpu_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); + else + info->drmmode.present_flipping = TRUE; return ret; } @@ -305,6 +317,7 @@ static void amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + AMDGPUInfoPtr info = AMDGPUPTR(scrn); struct amdgpu_present_vblank_event *event; PixmapPtr pixmap = screen->GetScreenPixmap(screen); struct amdgpu_buffer *bo; @@ -326,8 +339,10 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id) ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo, event_id, event, -1, amdgpu_present_flip_event, amdgpu_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 amdgpu_present_screen_info = { diff --git a/src/drmmode_display.h b/src/drmmode_display.h index d541d47..78ac9b7 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 { |