diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2017-08-18 16:23:39 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2017-08-22 18:33:25 +0900 |
commit | b82d1b6063a36facc9cdd0e0189fdb6932be94e2 (patch) | |
tree | 4e233432907444060b5ca03303a7a9c5271694b6 | |
parent | 2cbe7f2dff5eef159486f875b3ec67516c85862d (diff) |
Handle multiple "pending" Present flips
The xserver Present code can submit a flip in response to notifying it
that a vblank event arrived. This can happen before the completion event
of the previous flip is processed. In that case, we were clearing the
drmmode_crtc->flip_pending field prematurely.
Prevent this by only clearing drmmode_crtc->flip_pending when it matches
the framebuffer being scanned out since the flip whose completion event
we're processing.
(Ported from radeon commit 7c10ee9c88378d773c0bcf651fdc5d9f2c6dc5e5)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | src/drmmode_display.c | 27 | ||||
-rw-r--r-- | src/drmmode_display.h | 3 |
2 files changed, 18 insertions, 12 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 0d5aa26..eb701a8 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -2227,6 +2227,7 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) if (!flipdata->fe_crtc) flipdata->fe_crtc = crtc; flipdata->abort(flipdata->fe_crtc, flipdata->event_data); + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL); free(flipdata); } @@ -2248,6 +2249,13 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, + flipdata->fb); + if (drmmode_crtc->flip_pending == flipdata->fb) { + drmmode_fb_reference(pAMDGPUEnt->fd, + &drmmode_crtc->flip_pending, NULL); + } + if (--flipdata->flip_count == 0) { /* Deliver MSC & UST from reference/current CRTC to flip event * handler @@ -2258,13 +2266,9 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even else flipdata->handler(crtc, frame, usec, flipdata->event_data); + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL); free(flipdata); } - - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, - drmmode_crtc->flip_pending); - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, - NULL); } #if HAVE_NOTIFY_FD @@ -2761,7 +2765,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; uintptr_t drm_queue_seq = 0; - struct drmmode_fb *fb; flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); if (!flipdata) { @@ -2770,8 +2773,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto error; } - fb = amdgpu_pixmap_get_fb(new_front); - if (!fb) { + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, + amdgpu_pixmap_get_fb(new_front)); + if (!flipdata->fb) { ErrorF("Failed to get FB for flip\n"); goto error; } @@ -2813,7 +2817,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pAMDGPUEnt, drmmode_crtc, - fb->handle, + flipdata->fb->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -2821,14 +2825,14 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, - fb->handle, + flipdata->fb->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; } drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, - fb); + flipdata->fb); drm_queue_seq = 0; } @@ -2846,6 +2850,7 @@ error: drmmode_flip_abort(crtc, flipdata); else { abort(NULL, data); + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL); free(flipdata); } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 38bf144..b5788e2 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -52,8 +52,9 @@ typedef struct { } drmmode_rec, *drmmode_ptr; typedef struct { - int flip_count; + struct drmmode_fb *fb; void *event_data; + int flip_count; unsigned int fe_frame; uint64_t fe_usec; xf86CrtcPtr fe_crtc; |