Signed-off-by: Qiang Yu <Qiang.Yu at amd.com> Reviewed-by: Michel Dänzer <michel.daenzer at amd.com> --- hw/xfree86/drivers/modesetting/dri2.c | 11 +++++++++-- hw/xfree86/drivers/modesetting/driver.h | 5 +++-- hw/xfree86/drivers/modesetting/drmmode_display.h | 3 +++ hw/xfree86/drivers/modesetting/pageflip.c | 7 +++++-- hw/xfree86/drivers/modesetting/present.c | 20 ++++++++++++++++++-- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/hw/xfree86/drivers/modesetting/dri2.c b/hw/xfree86/drivers/modesetting/dri2.c index acbb980..125c413 100644 --- a/hw/xfree86/drivers/modesetting/dri2.c +++ b/hw/xfree86/drivers/modesetting/dri2.c @@ -408,15 +408,17 @@ struct ms_dri2_vblank_event { }; static void -ms_dri2_flip_abort(void *data) +ms_dri2_flip_abort(modesettingPtr ms, void *data) { struct ms_present_vblank_event *event = data; + ms->drmmode.dri2_flipping = FALSE; free(event); } static void -ms_dri2_flip_handler(uint64_t msc, uint64_t ust, void *data) +ms_dri2_flip_handler(modesettingPtr ms, uint64_t msc, + uint64_t ust, void *data) { struct ms_dri2_vblank_event *event = data; uint32_t frame = msc; @@ -432,6 +434,7 @@ ms_dri2_flip_handler(uint64_t msc, uint64_t ust, void *data) DRI2_FLIP_COMPLETE, event->event_complete, event->event_data); + ms->drmmode.dri2_flipping = FALSE; free(event); } @@ -440,6 +443,8 @@ ms_dri2_schedule_flip(ms_dri2_frame_event_ptr info) { DrawablePtr draw = info->drawable; ScreenPtr screen = draw->pScreen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); ms_dri2_buffer_private_ptr back_priv = info->back->driverPrivate; struct ms_dri2_vblank_event *event; drmmode_crtc_private_ptr drmmode_crtc = info->crtc->driver_private; @@ -457,6 +462,7 @@ ms_dri2_schedule_flip(ms_dri2_frame_event_ptr info) drmmode_crtc->vblank_pipe, FALSE, ms_dri2_flip_handler, ms_dri2_flip_abort)) { + ms->drmmode.dri2_flipping = TRUE; return TRUE; } return FALSE; @@ -542,6 +548,7 @@ can_flip(ScrnInfoPtr scrn, DrawablePtr draw, return draw->type == DRAWABLE_WINDOW && ms->drmmode.pageflip && + !ms->drmmode.present_flipping && scrn->vtSema && DRI2CanFlip(draw) && can_exchange(scrn, draw, front, back); } diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h index 38f0ec0..761490a 100644 --- a/hw/xfree86/drivers/modesetting/driver.h +++ b/hw/xfree86/drivers/modesetting/driver.h @@ -156,11 +156,12 @@ Bool ms_present_screen_init(ScreenPtr screen); #ifdef GLAMOR -typedef void (*ms_pageflip_handler_proc)(uint64_t frame, +typedef void (*ms_pageflip_handler_proc)(modesettingPtr ms, + uint64_t frame, uint64_t usec, void *data); -typedef void (*ms_pageflip_abort_proc)(void *data); +typedef void (*ms_pageflip_abort_proc)(modesettingPtr ms, void *data); int ms_flush_drm_events(ScreenPtr screen); diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h index 5499c16..f774250 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -80,6 +80,9 @@ typedef struct { Bool is_secondary; PixmapPtr fbcon_pixmap; + + Bool dri2_flipping; + Bool present_flipping; } drmmode_rec, *drmmode_ptr; typedef struct { diff --git a/hw/xfree86/drivers/modesetting/pageflip.c b/hw/xfree86/drivers/modesetting/pageflip.c index 5f35999..a82e0d6 100644 --- a/hw/xfree86/drivers/modesetting/pageflip.c +++ b/hw/xfree86/drivers/modesetting/pageflip.c @@ -98,7 +98,7 @@ ms_pageflip_handler(uint64_t msc, uint64_t ust, void *data) } if (flipdata->flip_count == 1) { - flipdata->event_handler(flipdata->fe_msc, + flipdata->event_handler(ms, flipdata->fe_msc, flipdata->fe_usec, flipdata->event); @@ -115,9 +115,12 @@ ms_pageflip_abort(void *data) { struct ms_crtc_pageflip *flip = data; struct ms_flipdata *flipdata = flip->flipdata; + ScreenPtr screen = flipdata->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); if (flipdata->flip_count == 1) - flipdata->abort_handler(flipdata->event); + flipdata->abort_handler(ms, flipdata->event); ms_pageflip_free(flip); } diff --git a/hw/xfree86/drivers/modesetting/present.c b/hw/xfree86/drivers/modesetting/present.c index deee1f1..c0bb221 100644 --- a/hw/xfree86/drivers/modesetting/present.c +++ b/hw/xfree86/drivers/modesetting/present.c @@ -53,6 +53,7 @@ struct ms_present_vblank_event { uint64_t event_id; + Bool unflip; }; static RRCrtcPtr @@ -196,7 +197,8 @@ ms_present_flush(WindowPtr window) * extension code telling it when that happened */ static void -ms_present_flip_handler(uint64_t msc, uint64_t ust, void *data) +ms_present_flip_handler(modesettingPtr ms, uint64_t msc, + uint64_t ust, void *data) { struct ms_present_vblank_event *event = data; @@ -204,6 +206,9 @@ ms_present_flip_handler(uint64_t msc, uint64_t ust, void *data) (long long) event->event_id, (long long) msc, (long long) ust)); + if (event->unflip) + ms->drmmode.present_flipping = FALSE; + ms_present_vblank_handler(msc, ust, event); } @@ -211,7 +216,7 @@ ms_present_flip_handler(uint64_t msc, uint64_t ust, void *data) * Callback for the flip has been aborted. */ static void -ms_present_flip_abort(void *data) +ms_present_flip_abort(modesettingPtr ms, void *data) { struct ms_present_vblank_event *event = data; @@ -237,6 +242,9 @@ ms_present_check_flip(RRCrtcPtr crtc, if (!ms->drmmode.pageflip) return FALSE; + if (ms->drmmode.dri2_flipping) + return FALSE; + if (!scrn->vtSema) return FALSE; @@ -283,6 +291,7 @@ ms_present_flip(RRCrtcPtr crtc, { ScreenPtr screen = crtc->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); xf86CrtcPtr xf86_crtc = crtc->devPrivate; drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; Bool ret; @@ -298,10 +307,14 @@ ms_present_flip(RRCrtcPtr crtc, DebugPresent(("\t\tms:fq %lld\n", event_id)); event->event_id = event_id; + event->unflip = FALSE; + ret = ms_do_pageflip(screen, pixmap, event, drmmode_crtc->vblank_pipe, !sync_flip, ms_present_flip_handler, ms_present_flip_abort); if (!ret) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); + else + ms->drmmode.present_flipping = TRUE; return ret; } @@ -313,6 +326,7 @@ static void ms_present_unflip(ScreenPtr screen, uint64_t event_id) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + modesettingPtr ms = modesettingPTR(scrn); PixmapPtr pixmap = screen->GetScreenPixmap(screen); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int i; @@ -323,6 +337,7 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id) return; event->event_id = event_id; + event->unflip = TRUE; if (ms_present_check_flip(NULL, screen->root, pixmap, TRUE) && ms_do_pageflip(screen, pixmap, event, -1, FALSE, @@ -354,6 +369,7 @@ ms_present_unflip(ScreenPtr screen, uint64_t event_id) } present_event_notify(event_id, 0, 0); + ms->drmmode.present_flipping = FALSE; } #endif -- 2.7.4