Commit bac21dfc authored by Tom Denis's avatar Tom Denis Committed by Michel Dänzer
Browse files

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 Denis's avatarTom St Denis <tom.stdenis@amd.com>
Reviewed-by: Michel Dänzer's avatarMichel Dänzer <michel.daenzer@amd.com>
parent a5f7f2e6
......@@ -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);
}
......
......@@ -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 = {
......
......@@ -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 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment