xf86-video-amdgpu: Branch 'master' - 13 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Tue Aug 22 09:36:33 UTC 2017


 man/amdgpu.man         |    6 -
 src/amdgpu_dri2.c      |  103 +++++---------------
 src/amdgpu_drm_queue.c |    2 
 src/amdgpu_drv.h       |    5 
 src/amdgpu_kms.c       |  171 ++++++++++++++++------------------
 src/amdgpu_list.h      |    7 +
 src/amdgpu_present.c   |  106 +++++++++++++--------
 src/amdgpu_video.c     |    2 
 src/drmmode_display.c  |  246 ++++++++++++++++++++++++++-----------------------
 src/drmmode_display.h  |   28 +++--
 10 files changed, 352 insertions(+), 324 deletions(-)

New commits:
commit a2ee5c36c7d4fdcd067fdc1ef424be474f1ad2cb
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 17:24:45 2017 +0900

    Make amdgpu_scanout_do_update take a PixmapPtr instead of a DrawablePtr
    
    All callers were already passing in a pixmap.
    
    This allows simplifying the rotated scanout case slightly.
    
    (Ported from radeon commit d822a0f47070374ad0c1a97b559bae27724dc52a)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 1323747..75c2a26 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -341,7 +341,7 @@ Bool amdgpu_dri3_screen_init(ScreenPtr screen);
 
 /* amdgpu_kms.c */
 Bool amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
-			       DrawablePtr src_draw, BoxPtr extents);
+			      PixmapPtr src_pix, BoxPtr extents);
 void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
 				   , RegionPtr pBSRegion
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index f665a01..e0b7358 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -806,7 +806,7 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
 
 Bool
 amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
-			 DrawablePtr src_draw, BoxPtr extents)
+			 PixmapPtr src_pix, BoxPtr extents)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	RegionRec region = { .extents = *extents, .data = NULL };
@@ -834,10 +834,9 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
 		PictFormatPtr format = PictureWindowFormat(pScreen->root);
 		int error;
 		PicturePtr src, dst;
-		XID include_inferiors = IncludeInferiors;
 
-		src = CreatePicture(None, src_draw, format, CPSubwindowMode,
-				    &include_inferiors, serverClient, &error);
+		src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL,
+				    serverClient, &error);
 		if (!src) {
 			ErrorF("Failed to create source picture for transformed scanout "
 			       "update\n");
@@ -880,7 +879,7 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
 		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
 
 		ValidateGC(pDraw, gc);
-		(*gc->ops->CopyArea)(src_draw, pDraw, gc,
+		(*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc,
 				     xf86_crtc->x + extents->x1, xf86_crtc->y + extents->y1,
 				     extents->x2 - extents->x1, extents->y2 - extents->y1,
 				     extents->x1, extents->y1);
@@ -912,7 +911,7 @@ amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 	    !drmmode_crtc->flip_pending &&
 	    drmmode_crtc->dpms_mode == DPMSModeOn) {
 		if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
-					     &screen->GetWindowPixmap(screen->root)->drawable,
+					     screen->GetWindowPixmap(screen->root),
 					     &region->extents))
 			RegionEmpty(region);
 	}
@@ -993,7 +992,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 
 	scanout_id = drmmode_crtc->scanout_id ^ 1;
 	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id,
-				      &pScreen->GetWindowPixmap(pScreen->root)->drawable,
+				      pScreen->GetWindowPixmap(pScreen->root),
 				      &region->extents))
 		return;
 	RegionEmpty(region);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index edd955e..ad3325b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -779,7 +779,7 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*x = *y = 0;
 
 		amdgpu_scanout_do_update(crtc, scanout_id,
-					 &screen->GetWindowPixmap(screen->root)->drawable,
+					 screen->GetWindowPixmap(screen->root),
 					 box);
 		amdgpu_glamor_finish(scrn);
 	}
@@ -2850,8 +2850,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 				goto error;
 			}
 
-			amdgpu_scanout_do_update(crtc, scanout_id,
-						 &new_front->drawable, &extents);
+			amdgpu_scanout_do_update(crtc, scanout_id, new_front,
+						 &extents);
 
 			drmmode_crtc_wait_pending_event(drmmode_crtc, pAMDGPUEnt->fd,
 							drmmode_crtc->scanout_update_pending);
commit 828fb44cf953f78bd65d8f391bdabe2b1b3d53ae
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 17:22:12 2017 +0900

    Use xorg_list_append for the DRM event list
    
    We were adding entries at the start of the list, i.e. the list was
    ordered from most recently added to least recently added. However, the
    corresponding DRM events are generally expected to arrive in the same
    order as they are queued, which means that amdgpu_drm_queue_alloc would
    generally have to traverse the whole list to find the entry
    corresponding to an arrived event. Fix this by adding entries at the end
    of the list.
    
    (Ported from radeon commit 3e24770b1b472fc15df56d06f5f04778c9db63dd)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index e8810fd..eb3ca63 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -105,7 +105,7 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 	e->handler = handler;
 	e->abort = abort;
 
-	xorg_list_add(&e->list, &amdgpu_drm_queue);
+	xorg_list_append(&e->list, &amdgpu_drm_queue);
 
 	return e->seq;
 }
diff --git a/src/amdgpu_list.h b/src/amdgpu_list.h
index a2b1d3c..eb28835 100644
--- a/src/amdgpu_list.h
+++ b/src/amdgpu_list.h
@@ -35,6 +35,13 @@
 #define xorg_list_del			list_del
 #define xorg_list_for_each_entry	list_for_each_entry
 #define xorg_list_for_each_entry_safe	list_for_each_entry_safe
+
+static inline void
+xorg_list_append(struct list *entry, struct list *head)
+{
+	__list_add(entry, head->prev, head);
+}
+
 #endif
 
 #endif /* _AMDGPU_LIST_H_ */
commit 22740f86d028cdd0f556543df7444516a86f923b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 17:15:54 2017 +0900

    Consolidate amdgpu_scanout_flip_abort/handler helpers
    
    While at it, make them use crtc->driver_private.
    
    (Ported from radeon commit 36ce7920136c0d723c9397a84e7dd5926a9c7943)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index b0f1a3d..f665a01 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -420,6 +420,38 @@ amdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
 	RegionUninit(&remaining);
 }
 
+static void
+amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
+{
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->scanout_update_pending = FALSE;
+	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
+}
+
+static void
+amdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
+			    void *event_data)
+{
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
+			     drmmode_crtc->flip_pending);
+	amdgpu_scanout_flip_abort(crtc, event_data);
+
+#ifdef HAVE_PRESENT_H
+	if (drmmode_crtc->present_vblank_event_id) {
+		present_event_notify(drmmode_crtc->present_vblank_event_id,
+				     drmmode_crtc->present_vblank_usec,
+				     drmmode_crtc->present_vblank_msc);
+		drmmode_crtc->present_vblank_event_id = 0;
+	}
+#endif
+}
+
 #ifdef AMDGPU_PIXMAP_SHARING
 
 static RegionPtr
@@ -665,38 +697,6 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 }
 
 static void
-amdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
-{
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
-	drmmode_crtc_private_ptr drmmode_crtc = event_data;
-
-	drmmode_crtc->scanout_update_pending = FALSE;
-	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
-			     NULL);
-}
-
-static void
-amdgpu_prime_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
-				  void *event_data)
-{
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
-	drmmode_crtc_private_ptr drmmode_crtc = event_data;
-
-	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
-			     drmmode_crtc->flip_pending);
-	amdgpu_prime_scanout_flip_abort(crtc, event_data);
-
-#ifdef HAVE_PRESENT_H
-	if (drmmode_crtc->present_vblank_event_id) {
-		present_event_notify(drmmode_crtc->present_vblank_event_id,
-				     drmmode_crtc->present_vblank_usec,
-				     drmmode_crtc->present_vblank_msc);
-		drmmode_crtc->present_vblank_event_id = 0;
-	}
-#endif
-}
-
-static void
 amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
 {
 	ScreenPtr screen = ent->slave_dst->drawable.pScreen;
@@ -723,9 +723,9 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
-					       drmmode_crtc,
-					       amdgpu_prime_scanout_flip_handler,
-					       amdgpu_prime_scanout_flip_abort);
+					       NULL,
+					       amdgpu_scanout_flip_handler,
+					       amdgpu_scanout_flip_abort);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM event queue entry failed for PRIME flip.\n");
@@ -976,19 +976,6 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 }
 
 static void
-amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
-{
-	amdgpu_prime_scanout_flip_abort(crtc, event_data);
-}
-
-static void
-amdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
-			    void *event_data)
-{
-	amdgpu_prime_scanout_flip_handler(crtc, msc, usec, event_data);
-}
-
-static void
 amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 					xf86CrtcPtr xf86_crtc)
 {
@@ -1014,7 +1001,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
-					       drmmode_crtc,
+					       NULL,
 					       amdgpu_scanout_flip_handler,
 					       amdgpu_scanout_flip_abort);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
commit 2692508ae8920ce62f488a9384444c1645964913
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 17:12:15 2017 +0900

    Always allow DRI2 page flipping with TearFree
    
    Even if TearFree is enabled for the CRTC we're synchronizing to.
    
    (Ported from radeon commit d314cbfb228bb4b8762714f98d0c114a8ee3f061)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/man/amdgpu.man b/man/amdgpu.man
index ebb472a..c38defe 100644
--- a/man/amdgpu.man
+++ b/man/amdgpu.man
@@ -77,10 +77,8 @@ Set the default value of the per-output 'TearFree' property, which controls
 tearing prevention using the hardware page flipping mechanism. TearFree is
 on for any CRTC associated with one or more outputs with TearFree on. Two
 separate scanout buffers need to be allocated for each CRTC with TearFree
-on. While TearFree is on for any CRTC, it may prevent clients from using
-DRI page flipping. If this option is set, the default value of the property
-is 'on' or 'off' accordingly. If this option isn't set, the default value of the
-property is
+on. If this option is set, the default value of the property is 'on' or 'off'
+accordingly. If this option isn't set, the default value of the property is
 .B auto,
 which means that TearFree is on for outputs with rotation or other RandR
 transforms, and for RandR 1.4 slave outputs, otherwise off.
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index bf85dfa..ccf5477 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -641,8 +641,6 @@ can_flip(xf86CrtcPtr crtc, DrawablePtr draw,
 	for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
 		if (drmmode_crtc_can_flip(config->crtc[i]))
 			num_crtcs_on++;
-		else if (config->crtc[i] == crtc)
-			return FALSE;
 	}
 
 	return num_crtcs_on > 0 && can_exchange(pScrn, draw, front, back);
commit 8c82878c6ef1b984ba289383dc17152192c916ee
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:57:13 2017 +0900

    Always allow Present page flipping with TearFree
    
    Even if TearFree is active for the the CRTC we're synchronizing to. In
    that case, for Present flips synchronized to vertical blank, the other
    scanout buffer is immediately synchronized and flipped to during the
    target vertical blank period. For Present flips not synchronized to
    vertical blank, we simply use the MSC and timestamp values of the last
    vertical blank period for timing purposes, and let the normal TearFree
    mechanism handle display updates.
    
    (Ported from radeon commit 4445765af5b97d0cfd10889fe6d6f58f2ce85659)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index aedb3f0..b0f1a3d 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -41,6 +41,10 @@
 #include "shadow.h"
 #include <xf86Priv.h>
 
+#if HAVE_PRESENT_H
+#include <present.h>
+#endif
+
 /* DPMS */
 #ifdef HAVE_XEXTPROTO_71
 #include <X11/extensions/dpmsconst.h>
@@ -681,6 +685,15 @@ amdgpu_prime_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
 	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
 			     drmmode_crtc->flip_pending);
 	amdgpu_prime_scanout_flip_abort(crtc, event_data);
+
+#ifdef HAVE_PRESENT_H
+	if (drmmode_crtc->present_vblank_event_id) {
+		present_event_notify(drmmode_crtc->present_vblank_event_id,
+				     drmmode_crtc->present_vblank_usec,
+				     drmmode_crtc->present_vblank_msc);
+		drmmode_crtc->present_vblank_event_id = 0;
+	}
+#endif
 }
 
 static void
@@ -895,10 +908,14 @@ amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 	ScreenPtr screen = crtc->scrn->pScreen;
 	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
 
-	amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
-				 &screen->GetWindowPixmap(screen->root)->drawable,
-				 &region->extents);
-	RegionEmpty(region);
+	if (crtc->enabled &&
+	    !drmmode_crtc->flip_pending &&
+	    drmmode_crtc->dpms_mode == DPMSModeOn) {
+		if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
+					     &screen->GetWindowPixmap(screen->root)->drawable,
+					     &region->extents))
+			RegionEmpty(region);
+	}
 
 	amdgpu_scanout_update_abort(crtc, event_data);
 }
@@ -915,6 +932,7 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 
 	if (!xf86_crtc->enabled ||
 	    drmmode_crtc->scanout_update_pending ||
+	    drmmode_crtc->flip_pending ||
 	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
@@ -982,6 +1000,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 	unsigned scanout_id;
 
 	if (drmmode_crtc->scanout_update_pending ||
+	    drmmode_crtc->flip_pending ||
 	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index c7fc402..cef93c0 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -52,6 +52,7 @@ static present_screen_info_rec amdgpu_present_screen_info;
 
 struct amdgpu_present_vblank_event {
 	uint64_t event_id;
+	Bool vblank_for_flip;
 	Bool unflip;
 };
 
@@ -119,9 +120,26 @@ static void
 amdgpu_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc,
 			      uint64_t usec, void *data)
 {
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	struct amdgpu_present_vblank_event *event = data;
 
-	present_event_notify(event->event_id, usec, msc);
+	if (event->vblank_for_flip &&
+	    drmmode_crtc->tear_free &&
+	    drmmode_crtc->scanout_update_pending) {
+		if (drmmode_crtc->present_vblank_event_id != 0) {
+			xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING,
+				   "Need to handle previously deferred vblank event\n");
+			present_event_notify(drmmode_crtc->present_vblank_event_id,
+					     drmmode_crtc->present_vblank_usec,
+					     drmmode_crtc->present_vblank_msc);
+		}
+
+		drmmode_crtc->present_vblank_event_id = event->event_id;
+		drmmode_crtc->present_vblank_msc = msc;
+		drmmode_crtc->present_vblank_usec = usec;
+	} else
+		present_event_notify(event->event_id, usec, msc);
+
 	free(event);
 }
 
@@ -144,6 +162,7 @@ static int
 amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 {
 	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	ScreenPtr screen = crtc->pScreen;
 	struct amdgpu_present_vblank_event *event;
 	uintptr_t drm_queue_seq;
@@ -152,6 +171,9 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 	if (!event)
 		return BadAlloc;
 	event->event_id = event_id;
+	event->vblank_for_flip = drmmode_crtc->present_flip_expected;
+	drmmode_crtc->present_flip_expected = FALSE;
+
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       event_id, event,
@@ -211,8 +233,17 @@ amdgpu_present_check_unflip(ScrnInfoPtr scrn)
 		return FALSE;
 
 	for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
-		if (drmmode_crtc_can_flip(config->crtc[i]))
-			num_crtcs_on++;
+		xf86CrtcPtr crtc = config->crtc[i];
+
+		if (drmmode_crtc_can_flip(crtc)) {
+			drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+			if (drmmode_crtc->flip_pending)
+				return FALSE;
+
+			if (!drmmode_crtc->tear_free)
+				num_crtcs_on++;
+		}
 	}
 
 	return num_crtcs_on > 0;
@@ -225,9 +256,19 @@ static Bool
 amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 			  Bool sync_flip)
 {
+	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	ScreenPtr screen = window->drawable.pScreen;
-	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	ScrnInfoPtr scrn = xf86_crtc->scrn;
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	int num_crtcs_on;
+	int i;
+
+	drmmode_crtc->present_flip_expected = FALSE;
+
+	if (!scrn->vtSema)
+		return FALSE;
 
 	if (!info->allowPageFlip)
 		return FALSE;
@@ -245,10 +286,18 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	    amdgpu_pixmap_get_tiling_info(screen->GetScreenPixmap(screen)))
 		return FALSE;
 
-	if (!drmmode_crtc_can_flip(crtc->devPrivate))
+	for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
+		if (drmmode_crtc_can_flip(config->crtc[i]))
+			num_crtcs_on++;
+		else if (config->crtc[i] == crtc->devPrivate)
+			return FALSE;
+	}
+
+	if (num_crtcs_on == 0)
 		return FALSE;
 
-	return amdgpu_present_check_unflip(scrn);
+	drmmode_crtc->present_flip_expected = TRUE;
+	return TRUE;
 }
 
 /*
@@ -287,18 +336,20 @@ static Bool
 amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
                    PixmapPtr pixmap, Bool sync_flip)
 {
+	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	ScreenPtr screen = crtc->pScreen;
-	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	ScrnInfoPtr scrn = xf86_crtc->scrn;
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct amdgpu_present_vblank_event *event;
-	Bool ret;
+	Bool ret = FALSE;
 
 	if (!amdgpu_present_check_flip(crtc, screen->root, pixmap, sync_flip))
-		return FALSE;
+		goto out;
 
 	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
 	if (!event)
-		return FALSE;
+		goto out;
 
 	event->event_id = event_id;
 
@@ -315,6 +366,8 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 	else
 		info->drmmode.present_flipping = TRUE;
 
+ out:
+	drmmode_crtc->present_flip_expected = FALSE;
 	return ret;
 }
 
@@ -358,7 +411,7 @@ modeset:
 		xf86CrtcPtr crtc = config->crtc[i];
 		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 
-		if (!crtc->enabled)
+		if (!crtc->enabled || drmmode_crtc->tear_free)
 			continue;
 
 		if (drmmode_crtc->dpms_mode == DPMSModeOn)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index fa19fd7..edd955e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -550,6 +550,14 @@ error:
 static void
 amdgpu_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
 {
+	drmmode_crtc_private_ptr drmmode_crtc = closure;
+
+	if (drmmode_crtc->ignore_damage) {
+		RegionEmpty(&damage->damage);
+		drmmode_crtc->ignore_damage = FALSE;
+		return;
+	}
+
 	/* Only keep track of the extents */
 	RegionUninit(&damage->damage);
 	damage->damage.data = NULL;
@@ -2253,7 +2261,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 
 	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
 			     flipdata->fb);
-	if (drmmode_crtc->flip_pending == flipdata->fb) {
+	if (drmmode_crtc->tear_free ||
+	    drmmode_crtc->flip_pending == flipdata->fb) {
 		drmmode_fb_reference(pAMDGPUEnt->fd,
 				     &drmmode_crtc->flip_pending, NULL);
 	}
@@ -2798,13 +2807,16 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	flipdata->fe_crtc = ref_crtc;
 
 	for (i = 0; i < config->num_crtc; i++) {
+		struct drmmode_fb *fb = flipdata->fb;
+
 		crtc = config->crtc[i];
+		drmmode_crtc = crtc->driver_private;
 
-		if (!drmmode_crtc_can_flip(crtc))
+		if (!drmmode_crtc_can_flip(crtc) ||
+		    (drmmode_crtc->tear_free && crtc != ref_crtc))
 			continue;
 
 		flipdata->flip_count++;
-		drmmode_crtc = crtc->driver_private;
 
 		drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, id,
 						       flipdata,
@@ -2816,10 +2828,39 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			goto error;
 		}
 
+		if (drmmode_crtc->tear_free) {
+			BoxRec extents = { .x1 = 0, .y1 = 0,
+					   .x2 = new_front->drawable.width,
+					   .y2 = new_front->drawable.height };
+			int scanout_id = drmmode_crtc->scanout_id ^ 1;
+
+			if (flip_sync == FLIP_ASYNC) {
+				if (!drmmode_wait_vblank(crtc,
+							 DRM_VBLANK_RELATIVE |
+							 DRM_VBLANK_EVENT,
+							 0, drm_queue_seq,
+							 NULL, NULL))
+					goto flip_error;
+				goto next;
+			}
+
+			fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+			if (!fb) {
+				ErrorF("Failed to get FB for TearFree flip\n");
+				goto error;
+			}
+
+			amdgpu_scanout_do_update(crtc, scanout_id,
+						 &new_front->drawable, &extents);
+
+			drmmode_crtc_wait_pending_event(drmmode_crtc, pAMDGPUEnt->fd,
+							drmmode_crtc->scanout_update_pending);
+		}
+
 		if (crtc == ref_crtc) {
 			if (drmmode_page_flip_target_absolute(pAMDGPUEnt,
 							      drmmode_crtc,
-							      flipdata->fb->handle,
+							      fb->handle,
 							      flip_flags,
 							      drm_queue_seq,
 							      target_msc) != 0)
@@ -2827,14 +2868,20 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		} else {
 			if (drmmode_page_flip_target_relative(pAMDGPUEnt,
 							      drmmode_crtc,
-							      flipdata->fb->handle,
+							      fb->handle,
 							      flip_flags,
 							      drm_queue_seq, 0) != 0)
 				goto flip_error;
 		}
 
-		drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
-				     flipdata->fb);
+		if (drmmode_crtc->tear_free) {
+			drmmode_crtc->scanout_id ^= 1;
+			drmmode_crtc->ignore_damage = TRUE;
+		}
+
+	next:
+		drmmode_fb_reference(pAMDGPUEnt->fd,
+				     &drmmode_crtc->flip_pending, fb);
 		drm_queue_seq = 0;
 	}
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index b5788e2..1a6454c 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -81,6 +81,7 @@ typedef struct {
 	struct drmmode_scanout rotate;
 	struct drmmode_scanout scanout[2];
 	DamagePtr scanout_damage;
+	Bool ignore_damage;
 	RegionRec scanout_last_region;
 	unsigned scanout_id;
 	Bool scanout_update_pending;
@@ -100,6 +101,14 @@ typedef struct {
 	struct drmmode_fb *flip_pending;
 	/* The FB currently being scanned out by this CRTC, if any */
 	struct drmmode_fb *fb;
+
+#ifdef HAVE_PRESENT_H
+	/* Deferred processing of Present vblank event */
+	uint64_t present_vblank_event_id;
+	uint64_t present_vblank_usec;
+	unsigned present_vblank_msc;
+	Bool present_flip_expected;
+#endif
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
@@ -139,7 +148,8 @@ drmmode_crtc_can_flip(xf86CrtcPtr crtc)
 	return crtc->enabled &&
 		drmmode_crtc->dpms_mode == DPMSModeOn &&
 		!drmmode_crtc->rotate.bo &&
-		!drmmode_crtc->scanout[drmmode_crtc->scanout_id].bo;
+		(drmmode_crtc->tear_free ||
+		 !drmmode_crtc->scanout[drmmode_crtc->scanout_id].bo);
 }
 
 
commit d8e8f0107bb3e83a787917f4db16a7a54ce4768b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:46:18 2017 +0900

    Pass extents to amdgpu_scanout_do_update
    
    Preparation for following change, no functional change intended yet.
    
    (Ported from radeon commit 65e0c5ea1b4adff21d673dbf54af99704c429627)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 515d466..1323747 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -341,7 +341,7 @@ Bool amdgpu_dri3_screen_init(ScreenPtr screen);
 
 /* amdgpu_kms.c */
 Bool amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
-			       DrawablePtr src_draw);
+			       DrawablePtr src_draw, BoxPtr extents);
 void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
 				   , RegionPtr pBSRegion
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 230a779..aedb3f0 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -793,32 +793,27 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
 
 Bool
 amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
-			  DrawablePtr src_draw)
+			 DrawablePtr src_draw, BoxPtr extents)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
-	RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
+	RegionRec region = { .extents = *extents, .data = NULL };
 	ScrnInfoPtr scrn = xf86_crtc->scrn;
 	ScreenPtr pScreen = scrn->pScreen;
 	DrawablePtr pDraw;
-	BoxRec extents;
 
 	if (!xf86_crtc->enabled ||
-	    !drmmode_crtc->scanout[scanout_id].pixmap)
-		return FALSE;
-
-	if (!RegionNotEmpty(pRegion))
+	    !drmmode_crtc->scanout[scanout_id].pixmap ||
+	    extents->x1 >= extents->x2 || extents->y1 >= extents->y2)
 		return FALSE;
 
 	pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
-	extents = *RegionExtents(pRegion);
-	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
+	if (!amdgpu_scanout_extents_intersect(xf86_crtc, extents))
 		return FALSE;
 
 	if (drmmode_crtc->tear_free) {
-		amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
-		RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
+		amdgpu_sync_scanout_pixmaps(xf86_crtc, &region, scanout_id);
+		RegionCopy(&drmmode_crtc->scanout_last_region, &region);
 	}
-	RegionEmpty(pRegion);
 
 #if XF86_CRTC_VERSION >= 4
 	if (xf86_crtc->driverIsPerformingTransform) {
@@ -856,9 +851,9 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
 		pScreen->SourceValidate = NULL;
 		CompositePicture(PictOpSrc,
 				 src, NULL, dst,
-				 extents.x1, extents.y1, 0, 0, extents.x1,
-				 extents.y1, extents.x2 - extents.x1,
-				 extents.y2 - extents.y1);
+				 extents->x1, extents->y1, 0, 0, extents->x1,
+				 extents->y1, extents->x2 - extents->x1,
+				 extents->y2 - extents->y1);
 		pScreen->SourceValidate = SourceValidate;
 
  free_dst:
@@ -873,9 +868,9 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
 
 		ValidateGC(pDraw, gc);
 		(*gc->ops->CopyArea)(src_draw, pDraw, gc,
-				     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
-				     extents.x2 - extents.x1, extents.y2 - extents.y1,
-				     extents.x1, extents.y1);
+				     xf86_crtc->x + extents->x1, xf86_crtc->y + extents->y1,
+				     extents->x2 - extents->x1, extents->y2 - extents->y1,
+				     extents->x1, extents->y1);
 		FreeScratchGC(gc);
 	}
 
@@ -898,9 +893,12 @@ amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 {
 	drmmode_crtc_private_ptr drmmode_crtc = event_data;
 	ScreenPtr screen = crtc->scrn->pScreen;
+	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
 
 	amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
-				 &screen->GetWindowPixmap(screen->root)->drawable);
+				 &screen->GetWindowPixmap(screen->root)->drawable,
+				 &region->extents);
+	RegionEmpty(region);
 
 	amdgpu_scanout_update_abort(crtc, event_data);
 }
@@ -977,6 +975,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 					xf86CrtcPtr xf86_crtc)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
 	ScrnInfoPtr scrn = xf86_crtc->scrn;
 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	uintptr_t drm_queue_seq;
@@ -988,8 +987,10 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 
 	scanout_id = drmmode_crtc->scanout_id ^ 1;
 	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id,
-				      &pScreen->GetWindowPixmap(pScreen->root)->drawable))
+				      &pScreen->GetWindowPixmap(pScreen->root)->drawable,
+				      &region->extents))
 		return;
+	RegionEmpty(region);
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 972a6f2..fa19fd7 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -771,7 +771,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*x = *y = 0;
 
 		amdgpu_scanout_do_update(crtc, scanout_id,
-					 &screen->GetWindowPixmap(screen->root)->drawable);
+					 &screen->GetWindowPixmap(screen->root)->drawable,
+					 box);
 		amdgpu_glamor_finish(scrn);
 	}
 }
commit cc1dfb88eb6714fcdcb9b576a70f400a5d0d58ca
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:34:50 2017 +0900

    Add source drawable parameter to amdgpu_scanout_do_update
    
    Preparation for following changes, no functional change intended yet.
    
    (Ported from radeon commit 1443270e52e8562bd8dc3603f301963bd4027cef)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index da71ce8..515d466 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -340,7 +340,8 @@ typedef struct {
 Bool amdgpu_dri3_screen_init(ScreenPtr screen);
 
 /* amdgpu_kms.c */
-Bool amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id);
+Bool amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
+			       DrawablePtr src_draw);
 void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
 				   , RegionPtr pBSRegion
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index d8f667d..230a779 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -792,7 +792,8 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
 #endif
 
 Bool
-amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
+amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
+			  DrawablePtr src_draw)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
@@ -827,10 +828,7 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 		PicturePtr src, dst;
 		XID include_inferiors = IncludeInferiors;
 
-		src = CreatePicture(None,
-				    &pScreen->root->drawable,
-				    format,
-				    CPSubwindowMode,
+		src = CreatePicture(None, src_draw, format, CPSubwindowMode,
 				    &include_inferiors, serverClient, &error);
 		if (!src) {
 			ErrorF("Failed to create source picture for transformed scanout "
@@ -874,8 +872,7 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
 
 		ValidateGC(pDraw, gc);
-		(*gc->ops->CopyArea)(&pScreen->GetWindowPixmap(pScreen->root)->drawable,
-				     pDraw, gc,
+		(*gc->ops->CopyArea)(src_draw, pDraw, gc,
 				     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
 				     extents.x2 - extents.x1, extents.y2 - extents.y1,
 				     extents.x1, extents.y1);
@@ -900,8 +897,10 @@ amdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
 							  void *event_data)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = event_data;
+	ScreenPtr screen = crtc->scrn->pScreen;
 
-	amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id);
+	amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
+				 &screen->GetWindowPixmap(screen->root)->drawable);
 
 	amdgpu_scanout_update_abort(crtc, event_data);
 }
@@ -988,7 +987,8 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 		return;
 
 	scanout_id = drmmode_crtc->scanout_id ^ 1;
-	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id))
+	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id,
+				      &pScreen->GetWindowPixmap(pScreen->root)->drawable))
 		return;
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index eb701a8..972a6f2 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -770,7 +770,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
 		*x = *y = 0;
 
-		amdgpu_scanout_do_update(crtc, scanout_id);
+		amdgpu_scanout_do_update(crtc, scanout_id,
+					 &screen->GetWindowPixmap(screen->root)->drawable);
 		amdgpu_glamor_finish(scrn);
 	}
 }
commit b82d1b6063a36facc9cdd0e0189fdb6932be94e2
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:23:39 2017 +0900

    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 at amd.com>

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;
commit 2cbe7f2dff5eef159486f875b3ec67516c85862d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:13:17 2017 +0900

    Wait for pending flips synchronously before turning off a CRTC
    
    Allows removing drmmode_clear_pending_flip and the pending_dpms_mode
    field and cleaning up the code considerably.
    
    (Ported from radeon commit e6d7dc2070f4d21a6900916bb70a31839112882c)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 3e21125..d8f667d 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -634,7 +634,7 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 	drmmode_crtc = xf86_crtc->driver_private;
 	if (drmmode_crtc->scanout_update_pending ||
 	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
-	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
@@ -663,10 +663,12 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 static void
 amdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
 {
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
 	drmmode_crtc_private_ptr drmmode_crtc = event_data;
 
 	drmmode_crtc->scanout_update_pending = FALSE;
-	drmmode_clear_pending_flip(crtc);
+	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
 }
 
 static void
@@ -698,7 +700,7 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
 	drmmode_crtc = crtc->driver_private;
 	if (drmmode_crtc->scanout_update_pending ||
 	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
-	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
 	scanout_id = drmmode_crtc->scanout_id ^ 1;
@@ -916,7 +918,7 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 
 	if (!xf86_crtc->enabled ||
 	    drmmode_crtc->scanout_update_pending ||
-	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
 	pDamage = drmmode_crtc->scanout_damage;
@@ -982,7 +984,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 	unsigned scanout_id;
 
 	if (drmmode_crtc->scanout_update_pending ||
-	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
+	    drmmode_crtc->dpms_mode != DPMSModeOn)
 		return;
 
 	scanout_id = drmmode_crtc->scanout_id ^ 1;
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index b6792f3..c7fc402 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -361,7 +361,7 @@ modeset:
 		if (!crtc->enabled)
 			continue;
 
-		if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
+		if (drmmode_crtc->dpms_mode == DPMSModeOn)
 			crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 						    crtc->x, crtc->y);
 		else
diff --git a/src/amdgpu_video.c b/src/amdgpu_video.c
index 3f441e7..8f9a2b9 100644
--- a/src/amdgpu_video.c
+++ b/src/amdgpu_video.c
@@ -67,7 +67,7 @@ static int amdgpu_box_area(BoxPtr box)
 Bool amdgpu_crtc_is_enabled(xf86CrtcPtr crtc)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-	return drmmode_crtc->pending_dpms_mode == DPMSModeOn;
+	return drmmode_crtc->dpms_mode == DPMSModeOn;
 }
 
 xf86CrtcPtr
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bdd3866..0d5aa26 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -284,14 +284,11 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	CARD64 ust;
 	int ret;
 
-	drmmode_crtc->pending_dpms_mode = mode;
-
 	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
 		uint32_t seq;
 
-		/* Wait for any pending flip to finish */
-		if (drmmode_crtc->flip_pending)
-			return;
+		drmmode_crtc_wait_pending_event(drmmode_crtc, pAMDGPUEnt->fd,
+						drmmode_crtc->flip_pending);
 
 		/*
 		 * On->Off transition: record the last vblank time,
@@ -345,10 +342,8 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 
 	/* Disable unused CRTCs and enable/disable active CRTCs */
 	if (!crtc->enabled || mode != DPMSModeOn) {
-		/* Wait for any pending flip to finish */
-		if (drmmode_crtc->flip_pending)
-			return;
-
+		drmmode_crtc_wait_pending_event(drmmode_crtc, pAMDGPUEnt->fd,
+						drmmode_crtc->flip_pending);
 		drmModeSetCrtc(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
 			       0, 0, 0, NULL, 0, NULL);
 		drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL);
@@ -1369,7 +1364,6 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 	    drmModeGetCrtc(pAMDGPUEnt->fd, mode_res->crtcs[num]);
 	drmmode_crtc->drmmode = drmmode;
 	drmmode_crtc->dpms_mode = DPMSModeOff;
-	drmmode_crtc->pending_dpms_mode = DPMSModeOff;
 	crtc->driver_private = drmmode_crtc;
 	drmmode_crtc_hw_id(crtc);
 
@@ -1497,16 +1491,9 @@ static void drmmode_output_dpms(xf86OutputPtr output, int mode)
 	if (!koutput)
 		return;
 
-	if (mode != DPMSModeOn && crtc) {
-		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-
+	if (mode != DPMSModeOn && crtc)
 		drmmode_do_crtc_dpms(crtc, mode);
 
-		/* Wait for any pending flip to finish */
-		if (drmmode_crtc->flip_pending)
-			return;
-	}
-
 	drmModeConnectorSetProperty(pAMDGPUEnt->fd, koutput->connector_id,
 				    drmmode_output->dpms_enum_id, mode);
 
@@ -2229,38 +2216,11 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 	drmmode_xf86crtc_resize
 };
 
-void
-drmmode_clear_pending_flip(xf86CrtcPtr crtc)
-{
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-	ScrnInfoPtr scrn = crtc->scrn;
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
-
-	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
-			     NULL);
-
-	if (!crtc->enabled ||
-	    (drmmode_crtc->pending_dpms_mode != DPMSModeOn &&
-	     drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode)) {
-		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
-		int o;
-
-		for (o = 0; o < xf86_config->num_output; o++) {
-			xf86OutputPtr output = xf86_config->output[o];
-
-			if (output->crtc != crtc)
-				continue;
-
-			drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode);
-		}
-
-		drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
-	}
-}
-
 static void
 drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 {
+	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
 	drmmode_flipdata_ptr flipdata = event_data;
 
 	if (--flipdata->flip_count == 0) {
@@ -2270,7 +2230,8 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 		free(flipdata);
 	}
 
-	drmmode_clear_pending_flip(crtc);
+	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
 }
 
 static void
@@ -2302,7 +2263,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 
 	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
 			     drmmode_crtc->flip_pending);
-	drmmode_clear_pending_flip(crtc);
+	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
 }
 
 #if HAVE_NOTIFY_FD
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index ba7ec68..38bf144 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -88,8 +88,6 @@ typedef struct {
 	PixmapPtr prime_scanout_pixmap;
 
 	int dpms_mode;
-	/* For when a flip is pending when DPMS off requested */
-	int pending_dpms_mode;
 	CARD64 dpms_last_ust;
 	uint32_t dpms_last_seq;
 	int dpms_last_fps;
@@ -138,7 +136,7 @@ drmmode_crtc_can_flip(xf86CrtcPtr crtc)
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 
 	return crtc->enabled &&
-		drmmode_crtc->pending_dpms_mode == DPMSModeOn &&
+		drmmode_crtc->dpms_mode == DPMSModeOn &&
 		!drmmode_crtc->rotate.bo &&
 		!drmmode_crtc->scanout[drmmode_crtc->scanout_id].bo;
 }
@@ -206,7 +204,6 @@ extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
 
 extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
 extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe);
-extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc);
 Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
 			xf86CrtcPtr ref_crtc, amdgpu_drm_handler_proc handler,
commit e8d0bfab276d47338c337955b9d2fcbff3af225f
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 16:11:41 2017 +0900

    Create drmmode_crtc_wait_pending_event helper macro
    
    Preparation for following change, no functional change intended yet.
    
    (Ported from radeon commit f87acdbfb1b0b6d2769764772a52ea8b81675e20)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1a805b8..bdd3866 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -96,6 +96,14 @@ AMDGPUZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
 	return FALSE;
 }
 
+
+/* Wait for the boolean condition to be FALSE */
+#define drmmode_crtc_wait_pending_event(drmmode_crtc, fd, condition) \
+	do {} while ((condition) && \
+		     drmHandleEvent(fd, &drmmode_crtc->drmmode->event_context) \
+		     > 0);
+
+
 static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
 					  int width, int height,
 					  int depth, int bpp,
@@ -891,10 +899,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			goto done;
 		}
 
-		/* Wait for any pending flip to finish */
-		do {} while (drmmode_crtc->flip_pending &&
-			     drmHandleEvent(pAMDGPUEnt->fd,
-					    &drmmode->event_context) > 0);
+		drmmode_crtc_wait_pending_event(drmmode_crtc, pAMDGPUEnt->fd,
+						drmmode_crtc->flip_pending);
 
 		if (drmModeSetCrtc(pAMDGPUEnt->fd,
 				   drmmode_crtc->mode_crtc->crtc_id,
commit fd5b78b7edff2021111bca37642b8b508f0c3328
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 15:12:35 2017 +0900

    Create drmmode_wait_vblank helper
    
    Allows cleaning up the code considerably.
    
    (Ported from radeon commit 99f1d7a474af3683fe1a66f50c0bb8935478ff0a)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 52fac03..bf85dfa 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -778,20 +778,6 @@ cleanup:
 	amdgpu_dri2_frame_event_abort(crtc, event_data);
 }
 
-drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc)
-{
-	drmVBlankSeqType type = 0;
-	int crtc_id = drmmode_get_crtc_id(crtc);
-
-	if (crtc_id == 1)
-		type |= DRM_VBLANK_SECONDARY;
-	else if (crtc_id > 1)
-		type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
-		    DRM_VBLANK_HIGH_CRTC_MASK;
-
-	return type;
-}
-
 /*
  * This function should be called on a disabled CRTC only (i.e., CRTC
  * in DPMS-off state). It will calculate the delay necessary to reach
@@ -971,13 +957,11 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 {
 	ScreenPtr screen = draw->pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	DRI2FrameEventPtr wait_info = NULL;
 	uintptr_t drm_queue_seq = 0;
 	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
 	uint32_t msc_delta;
-	drmVBlank vbl;
-	int ret;
+	uint32_t seq;
 	CARD64 current_msc;
 
 	/* Truncate to match kernel interfaces; means occasional overflow
@@ -1016,17 +1000,13 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	}
 
 	/* Get current count */
-	vbl.request.type = DRM_VBLANK_RELATIVE;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-	vbl.request.sequence = 0;
-	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-	if (ret) {
+	if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "get vblank counter failed: %s\n", strerror(errno));
 		goto out_complete;
 	}
 
-	current_msc = vbl.reply.sequence + msc_delta;
+	current_msc = seq + msc_delta;
 	current_msc &= 0xffffffff;
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
@@ -1053,12 +1033,9 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 		 */
 		if (current_msc >= target_msc)
 			target_msc = current_msc;
-		vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
-		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-		vbl.request.sequence = target_msc - msc_delta;
-		vbl.request.signal = drm_queue_seq;
-		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-		if (ret) {
+		if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT,
+					 target_msc - msc_delta, drm_queue_seq, NULL,
+					 NULL)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "get vblank counter failed: %s\n",
 				   strerror(errno));
@@ -1073,11 +1050,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	 * If we get here, target_msc has already passed or we don't have one,
 	 * so we queue an event that will satisfy the divisor/remainder equation.
 	 */
-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-
-	vbl.request.sequence = current_msc - (current_msc % divisor) +
-	    remainder - msc_delta;
+	target_msc = current_msc - (current_msc % divisor) + remainder - msc_delta;
 
 	/*
 	 * If calculated remainder is larger than requested remainder,
@@ -1086,11 +1059,10 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 	 * that will happen.
 	 */
 	if ((current_msc % divisor) >= remainder)
-		vbl.request.sequence += divisor;
+		target_msc += divisor;
 
-	vbl.request.signal = drm_queue_seq;
-	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-	if (ret) {
+	if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT,
+				 target_msc, drm_queue_seq, NULL, NULL)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "get vblank counter failed: %s\n", strerror(errno));
 		goto out_complete;
@@ -1134,14 +1106,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 {
 	ScreenPtr screen = draw->pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
 	uint32_t msc_delta;
-	drmVBlank vbl;
-	int ret, flip = 0;
+	drmVBlankSeqType type;
+	uint32_t seq;
+	int flip = 0;
 	DRI2FrameEventPtr swap_info = NULL;
 	uintptr_t drm_queue_seq;
-	CARD64 current_msc;
+	CARD64 current_msc, event_msc;
 	BoxRec box;
 	RegionRec region;
 
@@ -1204,18 +1176,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	}
 
 	/* Get current count */
-	vbl.request.type = DRM_VBLANK_RELATIVE;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-	vbl.request.sequence = 0;
-	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-	if (ret) {
+	if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "first get vblank counter failed: %s\n",
 			   strerror(errno));
 		goto blit_fallback;
 	}
 
-	current_msc = vbl.reply.sequence + msc_delta;
+	current_msc = seq + msc_delta;
 	current_msc &= 0xffffffff;
 
 	/* Flips need to be submitted one frame before */
@@ -1237,14 +1205,13 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	 * the swap.
 	 */
 	if (divisor == 0 || current_msc < *target_msc) {
-		vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+		type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 		/* If non-pageflipping, but blitting/exchanging, we need to use
 		 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
 		 * on.
 		 */
 		if (flip == 0)
-			vbl.request.type |= DRM_VBLANK_NEXTONMISS;
-		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
+			type |= DRM_VBLANK_NEXTONMISS;
 
 		/* If target_msc already reached or passed, set it to
 		 * current_msc to ensure we return a reasonable value back
@@ -1253,17 +1220,15 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 		if (current_msc >= *target_msc)
 			*target_msc = current_msc;
 
-		vbl.request.sequence = *target_msc - msc_delta;
-		vbl.request.signal = drm_queue_seq;
-		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-		if (ret) {
+		if (!drmmode_wait_vblank(crtc, type, *target_msc - msc_delta,
+					 drm_queue_seq, NULL, &seq)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "divisor 0 get vblank counter failed: %s\n",
 				   strerror(errno));
 			goto blit_fallback;
 		}
 
-		*target_msc = vbl.reply.sequence + flip + msc_delta;
+		*target_msc = seq + flip + msc_delta;
 		*target_msc &= 0xffffffff;
 		swap_info->frame = *target_msc;
 
@@ -1275,13 +1240,11 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	 * and we need to queue an event that will satisfy the divisor/remainder
 	 * equation.
 	 */
-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+	type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 	if (flip == 0)
-		vbl.request.type |= DRM_VBLANK_NEXTONMISS;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
+		type |= DRM_VBLANK_NEXTONMISS;
 
-	vbl.request.sequence = current_msc - (current_msc % divisor) +
-	    remainder - msc_delta;
+	event_msc = current_msc - (current_msc % divisor) + remainder - msc_delta;
 
 	/*
 	 * If the calculated deadline vbl.request.sequence is smaller than
@@ -1294,15 +1257,13 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	 * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
 	 * if we are blitting/exchanging instead of flipping.
 	 */
-	if (vbl.request.sequence <= current_msc)
-		vbl.request.sequence += divisor;
+	if (event_msc <= current_msc)
+		event_msc += divisor;
 
 	/* Account for 1 frame extra pageflip delay if flip > 0 */
-	vbl.request.sequence -= flip;
+	event_msc -= flip;
 
-	vbl.request.signal = drm_queue_seq;
-	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-	if (ret) {
+	if (!drmmode_wait_vblank(crtc, type, event_msc, drm_queue_seq, NULL, &seq)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "final get vblank counter failed: %s\n",
 			   strerror(errno));
@@ -1310,7 +1271,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 	}
 
 	/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
-	*target_msc = vbl.reply.sequence + flip + msc_delta;
+	*target_msc = seq + flip + msc_delta;
 	*target_msc &= 0xffffffff;
 	swap_info->frame = *target_msc;
 
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 9e088e7..da71ce8 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -363,6 +363,4 @@ extern xf86CrtcPtr amdgpu_pick_best_crtc(ScrnInfoPtr pScrn,
 
 extern AMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn);
 
-drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc);
-
 #endif /* _AMDGPU_DRV_H_ */
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 20a552b..3e21125 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -624,11 +624,9 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 {
 	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty);
 	drmmode_crtc_private_ptr drmmode_crtc;
 	uintptr_t drm_queue_seq;
-	drmVBlank vbl;
 
 	if (!xf86_crtc || !xf86_crtc->enabled)
 		return;
@@ -650,13 +648,10 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 		return;
 	}
 
-	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
-	vbl.request.sequence = 1;
-	vbl.request.signal = drm_queue_seq;
-	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
+	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+				 1, drm_queue_seq, NULL, NULL)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "drmWaitVBlank failed for PRIME update: %s\n",
+			   "drmmode_wait_vblank failed for PRIME update: %s\n",
 			   strerror(errno));
 		amdgpu_drm_abort_entry(drm_queue_seq);
 		return;
@@ -915,8 +910,6 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
 	uintptr_t drm_queue_seq;
 	ScrnInfoPtr scrn;
-	AMDGPUEntPtr pAMDGPUEnt;
-	drmVBlank vbl;
 	DamagePtr pDamage;
 	RegionPtr pRegion;
 	BoxRec extents;
@@ -953,14 +946,10 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 		return;
 	}
 
-	pAMDGPUEnt = AMDGPUEntPriv(scrn);
-	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
-	vbl.request.sequence = 1;
-	vbl.request.signal = drm_queue_seq;
-	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
+	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+				 1, drm_queue_seq, NULL, NULL)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "drmWaitVBlank failed for scanout update: %s\n",
+			   "drmmode_wait_vblank failed for scanout update: %s\n",
 			   strerror(errno));
 		amdgpu_drm_abort_entry(drm_queue_seq);
 		return;
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 7769e1f..b6792f3 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -55,16 +55,6 @@ struct amdgpu_present_vblank_event {
 	Bool unflip;
 };
 
-static uint32_t crtc_select(int crtc_id)
-{
-	if (crtc_id > 1)
-		return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
-	else if (crtc_id > 0)
-		return DRM_VBLANK_SECONDARY;
-	else
-		return 0;
-}
-
 static RRCrtcPtr
 amdgpu_present_get_crtc(WindowPtr window)
 {
@@ -155,13 +145,8 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 {
 	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
 	ScreenPtr screen = crtc->pScreen;
-	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
-	int crtc_id = drmmode_get_crtc_id(xf86_crtc);
 	struct amdgpu_present_vblank_event *event;
 	uintptr_t drm_queue_seq;
-	drmVBlank vbl;
-	int ret;
 
 	event = calloc(sizeof(struct amdgpu_present_vblank_event), 1);
 	if (!event)
@@ -177,12 +162,10 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 		return BadAlloc;
 	}
 
-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id);
-	vbl.request.sequence = msc;
-	vbl.request.signal = drm_queue_seq;
 	for (;;) {
-		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-		if (!ret)
+		if (drmmode_wait_vblank(xf86_crtc,
+					DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc,
+					drm_queue_seq, NULL, NULL))
 			break;
 		if (errno != EBUSY || !amdgpu_present_flush_drm_events(screen)) {
 			amdgpu_drm_abort_entry(drm_queue_seq);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 93f6d27..1a805b8 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -190,6 +190,41 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
 }
 
 /*
+ * Utility helper for drmWaitVBlank
+ */
+Bool
+drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
+		    uint32_t target_seq, unsigned long signal, uint64_t *ust,
+		    uint32_t *result_seq)
+{
+	int crtc_id = drmmode_get_crtc_id(crtc);
+	ScrnInfoPtr scrn = crtc->scrn;
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+	drmVBlank vbl;
+
+	if (crtc_id == 1)
+		type |= DRM_VBLANK_SECONDARY;
+	else if (crtc_id > 1)
+		type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
+			DRM_VBLANK_HIGH_CRTC_MASK;
+
+	vbl.request.type = type;
+	vbl.request.sequence = target_seq;
+	vbl.request.signal = signal;
+
+	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl) != 0)
+		return FALSE;
+
+	if (ust)
+		*ust = (uint64_t)vbl.reply.tval_sec * 1000000 +
+			vbl.reply.tval_usec;
+	if (result_seq)
+		*result_seq = vbl.reply.sequence;
+
+	return TRUE;
+}
+
+/*
  * Retrieves present time in microseconds that is compatible
  * with units used by vblank timestamps. Depending on the kernel
  * version and DRM kernel module configuration, the vblank
@@ -219,23 +254,15 @@ int drmmode_get_current_ust(int drm_fd, CARD64 * ust)
 int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 {
 	ScrnInfoPtr scrn = crtc->scrn;
-	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
-	drmVBlank vbl;
-	int ret;
-
-	vbl.request.type = DRM_VBLANK_RELATIVE;
-	vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-	vbl.request.sequence = 0;
+	uint32_t seq;
 
-	ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-	if (ret) {
+	if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "get vblank counter failed: %s\n", strerror(errno));
-		return ret;
+		return -1;
 	}
 
-	*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
-	*msc = vbl.reply.sequence;
+	*msc = seq;
 
 	return Success;
 }
@@ -252,7 +279,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	drmmode_crtc->pending_dpms_mode = mode;
 
 	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
-		drmVBlank vbl;
+		uint32_t seq;
 
 		/* Wait for any pending flip to finish */
 		if (drmmode_crtc->flip_pending)
@@ -262,20 +289,14 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 		 * On->Off transition: record the last vblank time,
 		 * sequence number and frame period.
 		 */
-		vbl.request.type = DRM_VBLANK_RELATIVE;
-		vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-		vbl.request.sequence = 0;
-		ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
-		if (ret)
+		if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust,
+					 &seq))
 			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 				   "%s cannot get last vblank counter\n",
 				   __func__);
 		else {
-			CARD64 seq = (CARD64) vbl.reply.sequence;
 			CARD64 nominal_frame_rate, pix_in_frame;
 
-			ust = ((CARD64) vbl.reply.tval_sec * 1000000) +
-			    vbl.reply.tval_usec;
 			drmmode_crtc->dpms_last_ust = ust;
 			drmmode_crtc->dpms_last_seq = seq;
 			nominal_frame_rate = crtc->mode.Clock;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index bece0ce..ba7ec68 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -216,4 +216,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
 int drmmode_get_current_ust(int drm_fd, CARD64 * ust);
 
+Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
+			 uint32_t target_seq, unsigned long signal,
+			 uint64_t *ust, uint32_t *result_seq);
+
+
 #endif
commit 24b2718992e4bbc859c07e5b29b571f53314045d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 15:03:52 2017 +0900

    Pass reference CRTC to amdgpu_do_pageflip directly
    
    Simplifies the code slightly.
    
    (Ported from radeon commit 49cc61ab970ee28d4509b4e2dd0a57165136889f)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index dfbc999..52fac03 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -541,7 +541,6 @@ amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct dri2_buffer_priv *back_priv;
 	DRI2FrameEventPtr flip_info;
-	int ref_crtc_hw_id = drmmode_get_crtc_id(crtc);
 
 	flip_info = calloc(1, sizeof(DRI2FrameEventRec));
 	if (!flip_info)
@@ -561,8 +560,7 @@ amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
 	/* Page flip the full screen buffer */
 	back_priv = back->driverPrivate;
 	if (amdgpu_do_pageflip(scrn, client, back_priv->pixmap,
-			       AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info,
-			       ref_crtc_hw_id,
+			       AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info, crtc,
 			       amdgpu_dri2_flip_event_handler,
 			       amdgpu_dri2_flip_event_abort, FLIP_VSYNC,
 			       target_msc - amdgpu_get_msc_delta(draw, crtc))) {
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 550b702..7769e1f 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -308,8 +308,6 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 	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;
 	Bool ret;
 
 	if (!amdgpu_present_check_flip(crtc, screen->root, pixmap, sync_flip))
@@ -324,7 +322,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 	amdgpu_glamor_flush(scrn);
 
 	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
-				 pixmap, event_id, event, crtc_id,
+				 pixmap, event_id, event, crtc->devPrivate,
 				 amdgpu_present_flip_event,
 				 amdgpu_present_flip_abort,
 				 sync_flip ? FLIP_VSYNC : FLIP_ASYNC,
@@ -367,7 +365,7 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 
 	amdgpu_glamor_flush(scrn);
 	if (amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, pixmap,
-			       event_id, event, -1, amdgpu_present_flip_event,
+			       event_id, event, NULL, amdgpu_present_flip_event,
 			       amdgpu_present_flip_abort, flip_sync, 0))
 		return;
 
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 108fb68..93f6d27 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2759,7 +2759,7 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 
 Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
-			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
+			xf86CrtcPtr ref_crtc, amdgpu_drm_handler_proc handler,
 			amdgpu_drm_abort_proc abort,
 			enum drmmode_flip_sync flip_sync,
 			uint32_t target_msc)
@@ -2800,6 +2800,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	flipdata->event_data = data;
 	flipdata->handler = handler;
 	flipdata->abort = abort;
+	flipdata->fe_crtc = ref_crtc;
 
 	for (i = 0; i < config->num_crtc; i++) {
 		crtc = config->crtc[i];
@@ -2810,12 +2811,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		flipdata->flip_count++;
 		drmmode_crtc = crtc->driver_private;
 
-		/* Only the reference crtc will finally deliver its page flip
-		 * completion event. All other crtc's events will be discarded.
-		 */
-		if (drmmode_crtc->hw_id == ref_crtc_hw_id)
-			flipdata->fe_crtc = crtc;
-
 		drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, id,
 						       flipdata,
 						       drmmode_flip_handler,
@@ -2826,7 +2821,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			goto error;
 		}
 
-		if (drmmode_crtc->hw_id == ref_crtc_hw_id) {
+		if (crtc == ref_crtc) {
 			if (drmmode_page_flip_target_absolute(pAMDGPUEnt,
 							      drmmode_crtc,
 							      fb->handle,
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 7071a74..bece0ce 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -209,7 +209,7 @@ extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe);
 extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc);
 Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
-			int ref_crtc_hw_id, amdgpu_drm_handler_proc handler,
+			xf86CrtcPtr ref_crtc, amdgpu_drm_handler_proc handler,
 			amdgpu_drm_abort_proc abort,
 			enum drmmode_flip_sync flip_sync,
 			uint32_t target_msc);
commit 87a1f577f1de62f6b628bbe221cd8d551531e708
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Aug 18 14:56:10 2017 +0900

    Remove drmmode_crtc->scanout_destroy[] array
    
    No longer necessary since we're reference counting framebuffers.
    
    (Ported from radeon commit 3f120fa1d5d921656a367751bc079e020e9ab105)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 552bff8..108fb68 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -457,19 +457,10 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
 static void
 drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
 {
-	if (drmmode_crtc->flip_pending) {
-		drmmode_crtc->scanout_destroy[0] = drmmode_crtc->scanout[0];
-		drmmode_crtc->scanout[0].pixmap = NULL;
-		drmmode_crtc->scanout[0].bo = NULL;
-		drmmode_crtc->scanout_destroy[1] = drmmode_crtc->scanout[1];
-		drmmode_crtc->scanout[1].pixmap = NULL;
-		drmmode_crtc->scanout[1].bo = NULL;
-	} else {
-		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-					     &drmmode_crtc->scanout[0]);
-		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-					     &drmmode_crtc->scanout[1]);
-	}
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout[0]);
+	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+				     &drmmode_crtc->scanout[1]);
 
 	if (drmmode_crtc->scanout_damage)
 		DamageDestroy(drmmode_crtc->scanout_damage);
@@ -2238,11 +2229,6 @@ drmmode_clear_pending_flip(xf86CrtcPtr crtc)
 
 		drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
 	}
-
-	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-				     &drmmode_crtc->scanout_destroy[0]);
-	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
-				     &drmmode_crtc->scanout_destroy[1]);
 }
 
 static void
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index ca556f2..7071a74 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -79,7 +79,6 @@ typedef struct {
 	struct amdgpu_buffer *cursor_buffer;
 	struct drmmode_scanout rotate;
 	struct drmmode_scanout scanout[2];
-	struct drmmode_scanout scanout_destroy[2];
 	DamagePtr scanout_damage;
 	RegionRec scanout_last_region;
 	unsigned scanout_id;


More information about the xorg-commit mailing list