summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-08-18 16:23:39 +0900
committerMichel Dänzer <michel@daenzer.net>2017-08-22 18:33:25 +0900
commitb82d1b6063a36facc9cdd0e0189fdb6932be94e2 (patch)
tree4e233432907444060b5ca03303a7a9c5271694b6
parent2cbe7f2dff5eef159486f875b3ec67516c85862d (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.c27
-rw-r--r--src/drmmode_display.h3
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;