[PATCH xf86-video-amdgpu 06/10] Handle multiple "pending" Present flips

Michel Dänzer michel at daenzer.net
Fri Aug 18 08:53:18 UTC 2017


From: Michel Dänzer <michel.daenzer at amd.com>

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)

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/drmmode_display.c | 27 ++++++++++++++++-----------
 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 0d5aa26d2..eb701a89a 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 38bf14494..b5788e295 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;
-- 
2.14.1



More information about the amd-gfx mailing list