xf86-video-ati: Branch 'master' - 10 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Thu Aug 17 07:04:07 UTC 2017


 man/radeon.man        |    6 -
 src/drmmode_display.c |  246 +++++++++++++++++++++++++++-----------------------
 src/drmmode_display.h |   28 ++++-
 src/radeon.h          |    5 -
 src/radeon_dri2.c     |  109 ++++++----------------
 src/radeon_kms.c      |  106 +++++++++++----------
 src/radeon_present.c  |  106 ++++++++++++++-------
 src/radeon_video.c    |    2 
 8 files changed, 319 insertions(+), 289 deletions(-)

New commits:
commit d314cbfb228bb4b8762714f98d0c114a8ee3f061
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Jul 31 17:12:59 2017 +0900

    Always allow DRI2 page flipping with TearFree
    
    Even if TearFree is enabled for the CRTC we're synchronizing to.
    
    v2:
    * Move manpage hunk here from previous change.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com> # v1

diff --git a/man/radeon.man b/man/radeon.man
index 1e9a7beb..9fd863f3 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -285,10 +285,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/radeon_dri2.c b/src/radeon_dri2.c
index a0deb6ba..73adbe91 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -760,8 +760,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 4445765af5b97d0cfd10889fe6d6f58f2ce85659
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Feb 9 13:01:03 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.
    
    v2:
    * Move manpage hunk to next change, since TearFree can still prevent
      DRI2 page flipping with this change.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com> # v1

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 1ce58d1e..90588671 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -612,6 +612,14 @@ error:
 static void
 radeon_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;
@@ -2429,7 +2437,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 
 	drmmode_fb_reference(pRADEONEnt->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(pRADEONEnt->fd,
 				     &drmmode_crtc->flip_pending, NULL);
 	}
@@ -2998,13 +3007,16 @@ Bool radeon_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 = radeon_drm_queue_alloc(crtc, client, id,
 						       flipdata,
@@ -3016,10 +3028,39 @@ Bool radeon_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 = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+			if (!fb) {
+				ErrorF("Failed to get FB for TearFree flip\n");
+				goto error;
+			}
+
+			radeon_scanout_do_update(crtc, scanout_id,
+						 &new_front->drawable, &extents);
+
+			drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
+							drmmode_crtc->scanout_update_pending);
+		}
+
 		if (crtc == ref_crtc) {
 			if (drmmode_page_flip_target_absolute(pRADEONEnt,
 							      drmmode_crtc,
-							      flipdata->fb->handle,
+							      fb->handle,
 							      flip_flags,
 							      drm_queue_seq,
 							      target_msc) != 0)
@@ -3027,14 +3068,20 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		} else {
 			if (drmmode_page_flip_target_relative(pRADEONEnt,
 							      drmmode_crtc,
-							      flipdata->fb->handle,
+							      fb->handle,
 							      flip_flags,
 							      drm_queue_seq, 0) != 0)
 				goto flip_error;
 		}
 
-		drmmode_fb_reference(pRADEONEnt->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(pRADEONEnt->fd,
+				     &drmmode_crtc->flip_pending, fb);
 		drm_queue_seq = 0;
 	}
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 13f301f7..a6db87f8 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -85,6 +85,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;
@@ -106,6 +107,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 {
@@ -146,7 +155,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);
 }
 
 
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 17902334..7febf148 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -44,6 +44,10 @@
 
 #include "atipciids.h"
 
+#if HAVE_PRESENT_H
+#include <present.h>
+#endif
+
 /* DPMS */
 #ifdef HAVE_XEXTPROTO_71
 #include <X11/extensions/dpmsconst.h>
@@ -779,6 +783,15 @@ radeon_prime_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
     drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
 			 drmmode_crtc->flip_pending);
     radeon_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
@@ -1001,10 +1014,14 @@ radeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
     ScreenPtr screen = crtc->scrn->pScreen;
     RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
 
-    radeon_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 (radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id,
+				     &screen->GetWindowPixmap(screen->root)->drawable,
+				     &region->extents))
+	    RegionEmpty(region);
+    }
 
     radeon_scanout_update_abort(crtc, event_data);
 }
@@ -1021,6 +1038,7 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
 
     if (!xf86_crtc->enabled ||
 	drmmode_crtc->scanout_update_pending ||
+	drmmode_crtc->flip_pending ||
 	drmmode_crtc->dpms_mode != DPMSModeOn)
 	return;
 
@@ -1088,6 +1106,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
     unsigned scanout_id;
 
     if (drmmode_crtc->scanout_update_pending ||
+	drmmode_crtc->flip_pending ||
 	drmmode_crtc->dpms_mode != DPMSModeOn)
 	return;
 
diff --git a/src/radeon_present.c b/src/radeon_present.c
index c7dde0ec..176853d9 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -52,6 +52,7 @@ static present_screen_info_rec radeon_present_screen_info;
 
 struct radeon_present_vblank_event {
     uint64_t event_id;
+    Bool vblank_for_flip;
     Bool unflip;
 };
 
@@ -119,9 +120,26 @@ static void
 radeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc,
 			      uint64_t usec, void *data)
 {
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
     struct radeon_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
 radeon_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 radeon_present_vblank_event *event;
     uintptr_t drm_queue_seq;
@@ -152,6 +171,9 @@ radeon_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 = radeon_drm_queue_alloc(xf86_crtc,
 					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
 					   event_id, event,
@@ -226,8 +248,17 @@ radeon_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;
@@ -240,10 +271,20 @@ static Bool
 radeon_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);
     RADEONInfoPtr info = RADEONPTR(scrn);
     PixmapPtr screen_pixmap;
+    int num_crtcs_on;
+    int i;
+
+    drmmode_crtc->present_flip_expected = FALSE;
+
+    if (!scrn->vtSema)
+	return FALSE;
 
     if (!info->allowPageFlip)
 	return FALSE;
@@ -262,10 +303,18 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	radeon_present_get_pixmap_tiling_flags(info, screen_pixmap))
 	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 radeon_present_check_unflip(scrn);
+    drmmode_crtc->present_flip_expected = TRUE;
+    return TRUE;
 }
 
 /*
@@ -304,18 +353,20 @@ static Bool
 radeon_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;
     RADEONInfoPtr info = RADEONPTR(scrn);
     struct radeon_present_vblank_event *event;
-    Bool ret;
+    Bool ret = FALSE;
 
     if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
-	return FALSE;
+	goto out;
 
     event = calloc(1, sizeof(struct radeon_present_vblank_event));
     if (!event)
-	return FALSE;
+	goto out;
 
     event->event_id = event_id;
 
@@ -332,6 +383,8 @@ radeon_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;
 }
 
@@ -376,7 +429,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)
commit 65e0c5ea1b4adff21d673dbf54af99704c429627
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Feb 8 17:52:28 2017 +0900

    Pass extents to radeon_scanout_do_update
    
    Preparation for following change, no functional change intended yet.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 35b706e0..1ce58d1e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -834,7 +834,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*x = *y = 0;
 
 		radeon_scanout_do_update(crtc, scanout_id,
-					 &screen->GetWindowPixmap(screen->root)->drawable);
+					 &screen->GetWindowPixmap(screen->root)->drawable,
+					 box);
 		radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
 	}
 }
diff --git a/src/radeon.h b/src/radeon.h
index 864fe7c3..bba34434 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -665,7 +665,7 @@ Bool radeon_dri3_screen_init(ScreenPtr screen);
 
 /* radeon_kms.c */
 Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
-			      DrawablePtr src_draw);
+			      DrawablePtr src_draw, BoxPtr extents);
 void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
 				   , RegionPtr pBSRegion
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 5f02a487..17902334 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -891,34 +891,29 @@ radeon_dirty_update(ScrnInfoPtr scrn)
 
 Bool
 radeon_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;
     RADEONInfoPtr info = RADEONPTR(scrn);
     DrawablePtr pDraw;
-    BoxRec extents;
     Bool force;
 
     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 (!radeon_scanout_extents_intersect(xf86_crtc, &extents))
+    if (!radeon_scanout_extents_intersect(xf86_crtc, extents))
 	return FALSE;
 
     if (drmmode_crtc->tear_free) {
-	radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
-	RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
+	radeon_sync_scanout_pixmaps(xf86_crtc, &region, scanout_id);
+	RegionCopy(&drmmode_crtc->scanout_last_region, &region);
     }
-    RegionEmpty(pRegion);
 
     force = info->accel_state->force;
     info->accel_state->force = TRUE;
@@ -960,9 +955,9 @@ radeon_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:
@@ -977,9 +972,9 @@ radeon_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);
     }
 
@@ -1004,9 +999,12 @@ radeon_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);
 
     radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id,
-			     &screen->GetWindowPixmap(screen->root)->drawable);
+			     &screen->GetWindowPixmap(screen->root)->drawable,
+			     &region->extents);
+    RegionEmpty(region);
 
     radeon_scanout_update_abort(crtc, event_data);
 }
@@ -1083,6 +1081,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr 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;
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
     uintptr_t drm_queue_seq;
@@ -1094,8 +1093,10 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
 
     scanout_id = drmmode_crtc->scanout_id ^ 1;
     if (!radeon_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 = radeon_drm_queue_alloc(xf86_crtc,
 					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
commit 1443270e52e8562bd8dc3603f301963bd4027cef
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Feb 7 18:58:23 2017 +0900

    Add source drawable parameter to radeon_scanout_do_update
    
    Preparation for following changes, no functional change intended yet.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index d86c4ba9..35b706e0 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -833,7 +833,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
 		*x = *y = 0;
 
-		radeon_scanout_do_update(crtc, scanout_id);
+		radeon_scanout_do_update(crtc, scanout_id,
+					 &screen->GetWindowPixmap(screen->root)->drawable);
 		radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
 	}
 }
diff --git a/src/radeon.h b/src/radeon.h
index b93e2816..864fe7c3 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -664,7 +664,8 @@ extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
 Bool radeon_dri3_screen_init(ScreenPtr screen);
 
 /* radeon_kms.c */
-Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id);
+Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
+			      DrawablePtr src_draw);
 void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
 				   , RegionPtr pBSRegion
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 977504d9..5f02a487 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -890,7 +890,8 @@ radeon_dirty_update(ScrnInfoPtr scrn)
 #endif
 
 Bool
-radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
+radeon_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);
@@ -930,10 +931,7 @@ radeon_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 "
@@ -978,8 +976,7 @@ radeon_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);
@@ -1006,8 +1003,10 @@ radeon_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;
 
-    radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id);
+    radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id,
+			     &screen->GetWindowPixmap(screen->root)->drawable);
 
     radeon_scanout_update_abort(crtc, event_data);
 }
@@ -1094,7 +1093,8 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
 	return;
 
     scanout_id = drmmode_crtc->scanout_id ^ 1;
-    if (!radeon_scanout_do_update(xf86_crtc, scanout_id))
+    if (!radeon_scanout_do_update(xf86_crtc, scanout_id,
+				  &pScreen->GetWindowPixmap(pScreen->root)->drawable))
 	return;
 
     drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
commit 7c10ee9c88378d773c0bcf651fdc5d9f2c6dc5e5
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 3 18:16:36 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.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 2692f697..d86c4ba9 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2403,6 +2403,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(pRADEONEnt->fd, &flipdata->fb, NULL);
 		free(flipdata);
 	}
 
@@ -2424,6 +2425,13 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 		flipdata->fe_usec = usec;
 	}
 
+	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
+			     flipdata->fb);
+	if (drmmode_crtc->flip_pending == flipdata->fb) {
+		drmmode_fb_reference(pRADEONEnt->fd,
+				     &drmmode_crtc->flip_pending, NULL);
+	}
+
 	if (--flipdata->flip_count == 0) {
 		/* Deliver MSC & UST from reference/current CRTC to flip event
 		 * handler
@@ -2434,13 +2442,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(pRADEONEnt->fd, &flipdata->fb, NULL);
 		free(flipdata);
 	}
-
-	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
-			     drmmode_crtc->flip_pending);
-	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
-			     NULL);
 }
 
 
@@ -2961,7 +2965,6 @@ Bool radeon_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) {
@@ -2970,8 +2973,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
              goto error;
         }
 
-	fb = radeon_pixmap_get_fb(new_front);
-	if (!fb) {
+	drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb,
+			     radeon_pixmap_get_fb(new_front));
+	if (!flipdata->fb) {
 		ErrorF("Failed to get FB for flip\n");
 		goto error;
 	}
@@ -3013,7 +3017,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		if (crtc == ref_crtc) {
 			if (drmmode_page_flip_target_absolute(pRADEONEnt,
 							      drmmode_crtc,
-							      fb->handle,
+							      flipdata->fb->handle,
 							      flip_flags,
 							      drm_queue_seq,
 							      target_msc) != 0)
@@ -3021,14 +3025,14 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		} else {
 			if (drmmode_page_flip_target_relative(pRADEONEnt,
 							      drmmode_crtc,
-							      fb->handle,
+							      flipdata->fb->handle,
 							      flip_flags,
 							      drm_queue_seq, 0) != 0)
 				goto flip_error;
 		}
 
 		drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
-				     fb);
+				     flipdata->fb);
 		drm_queue_seq = 0;
 	}
 
@@ -3046,6 +3050,7 @@ error:
 		drmmode_flip_abort(crtc, flipdata);
 	else {
 		abort(NULL, data);
+		drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
 		free(flipdata);
 	}
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 52b76f05..13f301f7 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -56,8 +56,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 e6d7dc2070f4d21a6900916bb70a31839112882c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 3 17:51:20 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.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 45e04058..2692f697 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -337,14 +337,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, pRADEONEnt->fd,
+						drmmode_crtc->flip_pending);
 
 		/*
 		 * On->Off transition: record the last vblank time,
@@ -398,10 +395,8 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 
 	/* Disable unused 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, pRADEONEnt->fd,
+						drmmode_crtc->flip_pending);
 		drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
 			       0, 0, 0, NULL, 0, NULL);
 		drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
@@ -1419,7 +1414,6 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 	drmmode_crtc->mode_crtc = drmModeGetCrtc(pRADEONEnt->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);
 
@@ -1545,16 +1539,9 @@ 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(pRADEONEnt->fd, koutput->connector_id,
 				    drmmode_output->dpms_enum_id, mode);
 
@@ -2405,38 +2392,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;
-	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
-
-	drmmode_fb_reference(pRADEONEnt->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;
+	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
 	drmmode_flipdata_ptr flipdata = event_data;
 
 	if (--flipdata->flip_count == 0) {
@@ -2446,7 +2406,8 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 		free(flipdata);
 	}
 
-	drmmode_clear_pending_flip(crtc);
+	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
 }
 
 static void
@@ -2478,7 +2439,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 
 	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
 			     drmmode_crtc->flip_pending);
-	drmmode_clear_pending_flip(crtc);
+	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+			     NULL);
 }
 
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 71d1c4a4..52b76f05 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -92,8 +92,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;
@@ -145,7 +143,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;
 }
@@ -215,7 +213,6 @@ extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
 extern int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling);
 extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
 extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
-extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc);
 
 Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 423d36cb..977504d9 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -732,7 +732,7 @@ radeon_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 = radeon_drm_queue_alloc(xf86_crtc,
@@ -761,10 +761,12 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 static void
 radeon_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
 {
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
     drmmode_crtc_private_ptr drmmode_crtc = event_data;
 
     drmmode_crtc->scanout_update_pending = FALSE;
-    drmmode_clear_pending_flip(crtc);
+    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
+			 NULL);
 }
 
 static void
@@ -796,7 +798,7 @@ radeon_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;
@@ -1022,7 +1024,7 @@ radeon_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;
@@ -1088,7 +1090,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr 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/radeon_present.c b/src/radeon_present.c
index 135a0a97..c7dde0ec 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -379,7 +379,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/radeon_video.c b/src/radeon_video.c
index d058986a..e08d8e00 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -71,7 +71,7 @@ radeon_box_area(BoxPtr box)
 Bool radeon_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
commit f87acdbfb1b0b6d2769764772a52ea8b81675e20
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Jul 28 12:28:53 2017 +0900

    Create drmmode_crtc_wait_pending_event helper macro
    
    Preparation for following change, no functional change intended yet.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index d86f8300..45e04058 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -99,6 +99,14 @@ RADEONZaphodStringMatches(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,
@@ -951,10 +959,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(pRADEONEnt->fd,
-					    &drmmode->event_context) > 0);
+		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
+						drmmode_crtc->flip_pending);
 
 		if (drmModeSetCrtc(pRADEONEnt->fd,
 				   drmmode_crtc->mode_crtc->crtc_id,
commit 99f1d7a474af3683fe1a66f50c0bb8935478ff0a
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Aug 14 12:23:04 2017 +0900

    Create drmmode_wait_vblank helper
    
    Allows cleaning up the code considerably.
    
    v2:
    * Fix "drmWaiVBlank" typo, add blank line for readability (Slava Abramov)
    * Rename in/out sequence parameters to "target_seq" and "result_seq",
      hopefully that will be clearer.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com> # v1

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 46a579ff..d86f8300 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -243,6 +243,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;
+	RADEONEntPtr pRADEONEnt = RADEONEntPriv(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(pRADEONEnt->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
@@ -272,23 +307,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;
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
-    drmVBlank vbl;
-    int ret;
-
-    vbl.request.type = DRM_VBLANK_RELATIVE;
-    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
-    vbl.request.sequence = 0;
+    uint32_t seq;
 
-    ret = drmWaitVBlank(pRADEONEnt->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;
 }
@@ -305,7 +332,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)
@@ -315,20 +342,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 |= radeon_populate_vbl_request_type(crtc);
-		vbl.request.sequence = 0;
-		ret = drmWaitVBlank(pRADEONEnt->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 f2104789..71d1c4a4 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -226,5 +226,10 @@ Bool radeon_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
 
diff --git a/src/radeon.h b/src/radeon.h
index d815d3f0..b93e2816 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -693,8 +693,6 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
 void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size);
 extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn);
 
-drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc);
-
 static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
 {
 #ifdef USE_GLAMOR
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 80b17f1f..a0deb6ba 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -889,26 +889,6 @@ cleanup:
     radeon_dri2_frame_event_abort(crtc, event_data);
 }
 
-drmVBlankSeqType radeon_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)
-#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT
-	type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
-		DRM_VBLANK_HIGH_CRTC_MASK;
-#else
-	ErrorF("radeon driver bug: %s called for CRTC %d > 1, but "
-	       "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n",
-	       __func__, crtc_id);
-#endif
-
-    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
@@ -1087,13 +1067,11 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 {
     ScreenPtr screen = draw->pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
     DRI2FrameEventPtr wait_info = NULL;
     uintptr_t drm_queue_seq = 0;
     xf86CrtcPtr crtc = radeon_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
@@ -1132,17 +1110,13 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
     }
 
     /* Get current count */
-    vbl.request.type = DRM_VBLANK_RELATIVE;
-    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
-    vbl.request.sequence = 0;
-    ret = drmWaitVBlank(pRADEONEnt->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 = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT,
@@ -1169,12 +1143,9 @@ static int radeon_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 |= radeon_populate_vbl_request_type(crtc);
-        vbl.request.sequence = target_msc - msc_delta;
-        vbl.request.signal = drm_queue_seq;
-        ret = drmWaitVBlank(pRADEONEnt->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));
             goto out_complete;
@@ -1188,11 +1159,7 @@ static int radeon_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 |= radeon_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,
@@ -1201,11 +1168,10 @@ static int radeon_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(pRADEONEnt->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;
@@ -1249,14 +1215,14 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 {
     ScreenPtr screen = draw->pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
     xf86CrtcPtr crtc = radeon_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;
 
@@ -1319,18 +1285,14 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
     }
 
     /* Get current count */
-    vbl.request.type = DRM_VBLANK_RELATIVE;
-    vbl.request.type |= radeon_populate_vbl_request_type(crtc);
-    vbl.request.sequence = 0;
-    ret = drmWaitVBlank(pRADEONEnt->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 */
@@ -1352,14 +1314,13 @@ static int radeon_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 |= radeon_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
@@ -1368,17 +1329,15 @@ static int radeon_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(pRADEONEnt->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;
         swap_info->frame = *target_msc;
 
         return TRUE;
@@ -1389,13 +1348,11 @@ static int radeon_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 |= radeon_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
@@ -1408,15 +1365,13 @@ static int radeon_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(pRADEONEnt->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));
@@ -1424,7 +1379,7 @@ static int radeon_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/radeon_kms.c b/src/radeon_kms.c
index 5ae94f5c..423d36cb 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -722,11 +722,9 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 {
     ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
     xf86CrtcPtr xf86_crtc = radeon_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;
@@ -748,13 +746,10 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 	return;
     }
 
-    vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
-    vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
-    vbl.request.sequence = 1;
-    vbl.request.signal = drm_queue_seq;
-    if (drmWaitVBlank(pRADEONEnt->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));
 	radeon_drm_abort_entry(drm_queue_seq);
 	return;
@@ -1019,10 +1014,8 @@ static void
 radeon_scanout_update(xf86CrtcPtr xf86_crtc)
 {
     drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(xf86_crtc->scrn);
     uintptr_t drm_queue_seq;
     ScrnInfoPtr scrn;
-    drmVBlank vbl;
     DamagePtr pDamage;
     RegionPtr pRegion;
     BoxRec extents;
@@ -1059,13 +1052,10 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
 	return;
     }
 
-    vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
-    vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
-    vbl.request.sequence = 1;
-    vbl.request.signal = drm_queue_seq;
-    if (drmWaitVBlank(pRADEONEnt->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));
 	radeon_drm_abort_entry(drm_queue_seq);
 	return;
diff --git a/src/radeon_present.c b/src/radeon_present.c
index c01ba95f..135a0a97 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -55,16 +55,6 @@ struct radeon_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
 radeon_present_get_crtc(WindowPtr window)
 {
@@ -155,13 +145,8 @@ radeon_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);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
-    int crtc_id = drmmode_get_crtc_id(xf86_crtc);
     struct radeon_present_vblank_event *event;
     uintptr_t drm_queue_seq;
-    drmVBlank vbl;
-    int ret;
 
     event = calloc(sizeof(struct radeon_present_vblank_event), 1);
     if (!event)
@@ -177,12 +162,10 @@ radeon_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(pRADEONEnt->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 || !radeon_present_flush_drm_events(screen)) {
 	    radeon_drm_abort_entry(drm_queue_seq);
commit 49cc61ab970ee28d4509b4e2dd0a57165136889f
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Aug 1 18:45:53 2017 +0900

    Pass reference CRTC to radeon_do_pageflip directly
    
    Simplifies the code slightly.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 53314846..46a579ff 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2959,7 +2959,7 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
 
 Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
-			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+			xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler,
 			radeon_drm_abort_proc abort,
 			enum drmmode_flip_sync flip_sync,
 			uint32_t target_msc)
@@ -3000,6 +3000,7 @@ Bool radeon_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];
@@ -3010,12 +3011,6 @@ Bool radeon_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 = radeon_drm_queue_alloc(crtc, client, id,
 						       flipdata,
 						       drmmode_flip_handler,
@@ -3026,7 +3021,7 @@ Bool radeon_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(pRADEONEnt,
 							      drmmode_crtc,
 							      fb->handle,
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 82dcff0e..f2104789 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -219,7 +219,7 @@ extern void drmmode_clear_pending_flip(xf86CrtcPtr crtc);
 
 Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			PixmapPtr new_front, uint64_t id, void *data,
-			int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+			xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler,
 			radeon_drm_abort_proc abort,
 			enum drmmode_flip_sync flip_sync,
 			uint32_t target_msc);
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 4b059897..80b17f1f 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -654,7 +654,6 @@ radeon_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
     RADEONInfoPtr info = RADEONPTR(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)
@@ -674,8 +673,7 @@ radeon_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client,
     /* Page flip the full screen buffer */
     back_priv = back->driverPrivate;
     if (radeon_do_pageflip(scrn, client, back_priv->pixmap,
-			   RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
-			   ref_crtc_hw_id,
+			   RADEON_DRM_QUEUE_ID_DEFAULT, flip_info, crtc,
 			   radeon_dri2_flip_event_handler,
 			   radeon_dri2_flip_event_abort, FLIP_VSYNC,
 			   target_msc - radeon_get_msc_delta(draw, crtc))) {
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 4d43733e..c01ba95f 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -325,8 +325,6 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     RADEONInfoPtr info = RADEONPTR(scrn);
     struct radeon_present_vblank_event *event;
-    xf86CrtcPtr xf86_crtc = crtc->devPrivate;
-    int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
     Bool ret;
 
     if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
@@ -341,7 +339,7 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
     radeon_cs_flush_indirect(scrn);
 
     ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap,
-			     event_id, event, crtc_id,
+			     event_id, event, crtc->devPrivate,
 			     radeon_present_flip_event,
 			     radeon_present_flip_abort,
 			     sync_flip ? FLIP_VSYNC : FLIP_ASYNC,
@@ -385,7 +383,7 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
     event->unflip = TRUE;
 
     if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, pixmap,
-			   event_id, event, -1, radeon_present_flip_event,
+			   event_id, event, NULL, radeon_present_flip_event,
 			   radeon_present_flip_abort, flip_sync, 0))
 	return;
 
commit 3f120fa1d5d921656a367751bc079e020e9ab105
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 3 17:42:51 2017 +0900

    Remove drmmode_crtc->scanout_destroy[] array
    
    No longer necessary since we're reference counting framebuffers.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index addee9ca..53314846 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -515,19 +515,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);
@@ -2414,11 +2405,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 f859377c..82dcff0e 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -83,7 +83,6 @@ typedef struct {
     struct radeon_bo *cursor_bo;
     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