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

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Aug 17 08:25:22 UTC 2018


 src/drmmode_display.c  |   58 +++++++----------
 src/drmmode_display.h  |   12 +--
 src/radeon_dri2.c      |   14 ++--
 src/radeon_drm_queue.c |  161 ++++++++++++++++++++++++++++++++++++++++++-------
 src/radeon_drm_queue.h |    8 +-
 src/radeon_kms.c       |   11 ---
 src/radeon_present.c   |   36 +---------
 7 files changed, 186 insertions(+), 114 deletions(-)

New commits:
commit 60cd28bbbe4f9db391b4f27c5ff9289d5c2bef40
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 16 18:06:31 2018 +0200

    Remove drmmode_crtc_private_rec::present_vblank_* related code
    
    Not needed anymore with the more robust mechanisms for preventing nested
    drmHandleEvent calls introduced in the previous changes.
    
    (Ported from amdgpu commit 85cd8eef0cbed7b409b07f58d76dacd34aa3ddea)
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index a039bf8f..bc66eda6 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -111,14 +111,6 @@ 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 {
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 809d2446..a2477681 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -541,15 +541,6 @@ radeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
     drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
 			 drmmode_crtc->flip_pending);
     radeon_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
 }
 
 
diff --git a/src/radeon_present.c b/src/radeon_present.c
index ffc14a0e..d0a0c68c 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -52,7 +52,6 @@ static present_screen_info_rec radeon_present_screen_info;
 
 struct radeon_present_vblank_event {
     uint64_t event_id;
-    Bool vblank_for_flip;
     Bool unflip;
 };
 
@@ -120,26 +119,9 @@ 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;
 
-    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);
-
+    present_event_notify(event->event_id, usec, msc);
     free(event);
 }
 
@@ -162,7 +144,6 @@ 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;
@@ -171,8 +152,6 @@ 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,
@@ -272,7 +251,6 @@ 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 = xf86_crtc->scrn;
     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -281,8 +259,6 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
     int num_crtcs_on;
     int i;
 
-    drmmode_crtc->present_flip_expected = FALSE;
-
     if (!scrn->vtSema)
 	return FALSE;
 
@@ -313,7 +289,6 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
     if (num_crtcs_on == 0)
 	return FALSE;
 
-    drmmode_crtc->present_flip_expected = TRUE;
     return TRUE;
 }
 
@@ -354,7 +329,6 @@ 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 = xf86_crtc->scrn;
     RADEONInfoPtr info = RADEONPTR(scrn);
@@ -362,11 +336,11 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
     Bool ret = FALSE;
 
     if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
-	goto out;
+	return ret;
 
     event = calloc(1, sizeof(struct radeon_present_vblank_event));
     if (!event)
-	goto out;
+	return ret;
 
     event->event_id = event_id;
 
@@ -383,8 +357,6 @@ 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;
 }
 
commit c42f6e2e61d166c8d3ef3fcad175d7050a00288b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Jul 20 16:56:22 2018 +0200

    Defer vblank event handling while waiting for a pending flip
    
    This is to avoid submitting more flips while we are waiting for pending
    ones to complete.
    
    (Ported from amdgpu commit e52872da69ecc84dafb3355839e35b0383f0d228)
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index b4c9783c..8445ef2a 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -324,6 +324,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 				nominal_frame_rate /= pix_in_frame;
 			drmmode_crtc->dpms_last_fps = nominal_frame_rate;
 		}
+
+		drmmode_crtc->dpms_mode = mode;
+		radeon_drm_queue_handle_deferred(crtc);
 	} else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) {
 		/*
 		 * Off->On transition: calculate and accumulate the
@@ -341,8 +344,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 			drmmode_crtc->interpolated_vblanks += delta_seq;
 
 		}
+
+		drmmode_crtc->dpms_mode = DPMSModeOn;
 	}
-	drmmode_crtc->dpms_mode = mode;
 }
 
 static void
@@ -972,6 +976,7 @@ done:
 		}
 	}
 
+	radeon_drm_queue_handle_deferred(crtc);
 	return ret;
 }
 
@@ -1763,11 +1768,6 @@ drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt,
 	drmmode_output->tear_free = tear_free;
 
 	if (crtc) {
-		/* Wait for pending flips before drmmode_set_mode_major calls
-		 * drmmode_crtc_update_tear_free, to prevent a nested
-		 * drmHandleEvent call, which would hang
-		 */
-		radeon_drm_wait_pending_flip(crtc);
 		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
 				       crtc->x, crtc->y);
 	}
@@ -3278,6 +3278,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
 	uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0;
 	drmmode_flipdata_ptr flipdata;
+	Bool handle_deferred = FALSE;
 	uintptr_t drm_queue_seq = 0;
 	struct drmmode_fb *fb;
 	int i = 0;
@@ -3360,6 +3361,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 
 			if (drmmode_crtc->scanout_update_pending) {
 				radeon_drm_wait_pending_flip(crtc);
+				handle_deferred = TRUE;
 				radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
 				drmmode_crtc->scanout_update_pending = 0;
 			}
@@ -3395,6 +3397,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		drm_queue_seq = 0;
 	}
 
+	if (handle_deferred)
+		radeon_drm_queue_handle_deferred(ref_crtc);
 	if (flipdata->flip_count > 0)
 		return TRUE;
 
@@ -3414,5 +3418,7 @@ error:
 
 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
 		   strerror(errno));
+	if (handle_deferred)
+		radeon_drm_queue_handle_deferred(ref_crtc);
 	return FALSE;
 }
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 46449c8e..a039bf8f 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -103,6 +103,10 @@ typedef struct {
      * modeset)
      */
     Bool need_modeset;
+    /* For keeping track of nested calls to drm_wait_pending_flip /
+     * drm_queue_handle_deferred
+     */
+    int wait_flip_nesting_level;
     /* A flip to this FB is pending for this CRTC */
     struct drmmode_fb *flip_pending;
     /* The FB currently being scanned out by this CRTC, if any */
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index 3d2f4d15..857278fd 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -118,6 +118,30 @@ radeon_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
 }
 
 /*
+ * Handle deferred DRM vblank events
+ *
+ * This function must be called after radeon_drm_wait_pending_flip, once
+ * it's safe to attempt queueing a flip again
+ */
+void
+radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc)
+{
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    if (drmmode_crtc->wait_flip_nesting_level == 0 ||
+	--drmmode_crtc->wait_flip_nesting_level > 0)
+	return;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
+	drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+
+	if (drmmode_crtc->wait_flip_nesting_level == 0)
+	    radeon_drm_queue_handle_one(e);
+    }
+}
+
+/*
  * Enqueue a potential drm response; when the associated response
  * appears, we've got data to pass to the handler from here
  */
@@ -191,6 +215,13 @@ radeon_drm_abort_entry(uintptr_t seq)
     if (seq == RADEON_DRM_QUEUE_ERROR)
 	return;
 
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
+	if (e->seq == seq) {
+	    radeon_drm_abort_one(e);
+	    return;
+	}
+    }
+
     xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
 	if (e->seq == seq) {
 	    radeon_drm_abort_one(e);
@@ -229,8 +260,12 @@ radeon_drm_handle_event(int fd, drmEventContext *event_context)
     xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
 	radeon_drm_queue_handle_one(e);
 
-    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list)
-	radeon_drm_queue_handle_one(e);
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) {
+	drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+
+	if (drmmode_crtc->wait_flip_nesting_level == 0)
+	    radeon_drm_queue_handle_one(e);
+    }
 
     return r;
 }
@@ -244,6 +279,8 @@ void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc)
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
     struct radeon_drm_queue_entry *e, *tmp;
 
+    drmmode_crtc->wait_flip_nesting_level++;
+
     xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
 	radeon_drm_queue_handle_one(e);
 
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index 59343361..334c4ca6 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -40,6 +40,7 @@ typedef void (*radeon_drm_handler_proc)(xf86CrtcPtr crtc, uint32_t seq,
 					uint64_t usec, void *data);
 typedef void (*radeon_drm_abort_proc)(xf86CrtcPtr crtc, void *data);
 
+void radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc);
 uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 				 uint64_t id, void *data,
 				 radeon_drm_handler_proc handler,
commit ba83a866af5a3784fc4822614375cc081e93197c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 16 17:44:45 2018 +0200

    Add radeon_drm_handle_event wrapper for drmHandleEvent
    
    Instead of processing DRM events directly from drmHandleEvent's
    callbacks, there are three phases:
    
    1. drmHandleEvent is called, and signalled events are re-queued to
       _signalled lists from its callbacks.
    2. Signalled page flip completion events are processed.
    3. Signalled vblank events are processed.
    
    This should make sure that we never call drmHandleEvent from one of its
    callbacks, which would usually result in blocking forever.
    
    (Ported from amdgpu commit 739181c8d3334ff14b5a607895dfdeb29b0d9020)
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 73eadeb1..b4c9783c 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2587,9 +2587,8 @@ static void
 drm_wakeup_handler(pointer data, int err, pointer p)
 #endif
 {
-	ScrnInfoPtr scrn = data;
-	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
-	RADEONInfoPtr info = RADEONPTR(scrn);
+	drmmode_ptr drmmode = data;
+	RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn);
 	
 #if !HAVE_NOTIFY_FD
 	fd_set *read_mask = p;
@@ -2597,7 +2596,7 @@ drm_wakeup_handler(pointer data, int err, pointer p)
 	if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask))
 #endif
 	{
-		drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context);
+		radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context);
 	}
 }
 
@@ -2747,11 +2746,13 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 	info->drmmode_inited = TRUE;
 	if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
 #if HAVE_NOTIFY_FD
-		SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn);
+		SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ,
+			    &info->drmmode);
 #else
 		AddGeneralSocket(pRADEONEnt->fd);
 		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
-				drm_wakeup_handler, pScrn);
+					       drm_wakeup_handler,
+					       &info->drmmode);
 #endif
 		pRADEONEnt->fd_wakeup_registered = serverGeneration;
 		pRADEONEnt->fd_wakeup_ref = 1;
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index 69474be2..3d2f4d15 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -40,6 +40,7 @@
 
 struct radeon_drm_queue_entry {
     struct xorg_list list;
+    uint64_t usec;
     uint64_t id;
     uintptr_t seq;
     void *data;
@@ -47,36 +48,73 @@ struct radeon_drm_queue_entry {
     xf86CrtcPtr crtc;
     radeon_drm_handler_proc handler;
     radeon_drm_abort_proc abort;
+    unsigned int frame;
 };
 
 static int radeon_drm_queue_refcnt;
 static struct xorg_list radeon_drm_queue;
+static struct xorg_list radeon_drm_flip_signalled;
+static struct xorg_list radeon_drm_vblank_signalled;
 static uintptr_t radeon_drm_queue_seq;
 
 
 /*
- * Handle a DRM event
+ * Process a DRM event
  */
 static void
-radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
-			 unsigned int usec, void *user_ptr)
+radeon_drm_queue_handle_one(struct radeon_drm_queue_entry *e)
 {
-	uintptr_t seq = (uintptr_t)user_ptr;
-	struct radeon_drm_queue_entry *e, *tmp;
-
-	xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
-		if (e->seq == seq) {
-			xorg_list_del(&e->list);
-			if (e->handler)
-				e->handler(e->crtc, frame,
-					   (uint64_t)sec * 1000000 + usec,
-					   e->data);
-			else
-				e->abort(e->crtc, e->data);
-			free(e);
-			break;
-		}
+    xorg_list_del(&e->list);
+    if (e->handler) {
+	e->handler(e->crtc, e->frame, e->usec, e->data);
+    } else
+	e->abort(e->crtc, e->data);
+    free(e);
+}
+
+static void
+radeon_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
+			 unsigned int sec, unsigned int usec, void *user_ptr)
+{
+    uintptr_t seq = (uintptr_t)user_ptr;
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+	if (e->seq == seq) {
+	    if (!e->handler) {
+		e->abort(e->crtc, e->data);
+		break;
+	    }
+
+	    xorg_list_del(&e->list);
+	    e->usec = (uint64_t)sec * 1000000 + usec;
+	    e->frame = frame;
+	    xorg_list_append(&e->list, signalled);
+	    break;
 	}
+    }
+}
+
+/*
+ * Signal a DRM page flip event
+ */
+static void
+radeon_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
+			     unsigned int usec, void *user_ptr)
+{
+    radeon_drm_queue_handler(&radeon_drm_flip_signalled, frame, sec, usec,
+			     user_ptr);
+}
+
+/*
+ * Signal a DRM vblank event
+ */
+static void
+radeon_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
+			  unsigned int usec, void *user_ptr)
+{
+    radeon_drm_queue_handler(&radeon_drm_vblank_signalled, frame, sec, usec,
+			     user_ptr);
 }
 
 /*
@@ -178,16 +216,40 @@ radeon_drm_abort_id(uint64_t id)
 }
 
 /*
+ * drmHandleEvent wrapper
+ */
+int
+radeon_drm_handle_event(int fd, drmEventContext *event_context)
+{
+    struct radeon_drm_queue_entry *e, *tmp;
+    int r;
+
+    r = drmHandleEvent(fd, event_context);
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
+	radeon_drm_queue_handle_one(e);
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list)
+	radeon_drm_queue_handle_one(e);
+
+    return r;
+}
+
+/*
  * Wait for pending page flip on given CRTC to complete
  */
 void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
     RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
-    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+    struct radeon_drm_queue_entry *e, *tmp;
+
+    xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_flip_signalled, list)
+	radeon_drm_queue_handle_one(e);
 
-    while (drmmode_crtc->flip_pending &&
-	   drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) > 0);
+    while (drmmode_crtc->flip_pending
+	   && radeon_drm_handle_event(pRADEONEnt->fd,
+					  &drmmode_crtc->drmmode->event_context) > 0);
 }
 
 /*
@@ -200,13 +262,15 @@ radeon_drm_queue_init(ScrnInfoPtr scrn)
     drmmode_ptr drmmode = &info->drmmode;
 
     drmmode->event_context.version = 2;
-    drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
-    drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
+    drmmode->event_context.vblank_handler = radeon_drm_vblank_handler;
+    drmmode->event_context.page_flip_handler = radeon_drm_page_flip_handler;
 
     if (radeon_drm_queue_refcnt++)
 	return;
 
     xorg_list_init(&radeon_drm_queue);
+    xorg_list_init(&radeon_drm_flip_signalled);
+    xorg_list_init(&radeon_drm_vblank_signalled);
 }
 
 /*
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index 96f88bd3..59343361 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -47,6 +47,7 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 void radeon_drm_abort_client(ClientPtr client);
 void radeon_drm_abort_entry(uintptr_t seq);
 void radeon_drm_abort_id(uint64_t id);
+int radeon_drm_handle_event(int fd, drmEventContext *event_context);
 void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc);
 void radeon_drm_queue_init(ScrnInfoPtr scrn);
 void radeon_drm_queue_close(ScrnInfoPtr scrn);
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 2982d728..ffc14a0e 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -110,7 +110,7 @@ radeon_present_flush_drm_events(ScreenPtr screen)
     if (r <= 0)
 	return 0;
 
-    return drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) >= 0;
+    return radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context) >= 0;
 }
 
 /*
commit 93621e408c17dd9e082236c17f051c06558d7f4d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 16 17:27:06 2018 +0200

    Add radeon_drm_wait_pending_flip function
    
    Replacing the drmmode_crtc_wait_pending_event macro.
    
    (Ported from amdgpu commit 6029794e8a35417faf825491a89b85f713c77fc1)
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 385c5b3e..73eadeb1 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -100,13 +100,6 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
 }
 
 
-/* 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,
@@ -306,8 +299,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
 		uint32_t seq;
 
-		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
-						drmmode_crtc->flip_pending);
+		radeon_drm_wait_pending_flip(crtc);
 
 		/*
 		 * On->Off transition: record the last vblank time,
@@ -918,8 +910,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			goto done;
 		}
 
-		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
-						drmmode_crtc->flip_pending);
+		radeon_drm_wait_pending_flip(crtc);
 
 		if (!drmmode_set_mode(crtc, fb, mode, x, y))
 			goto done;
@@ -1772,14 +1763,11 @@ drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt,
 	drmmode_output->tear_free = tear_free;
 
 	if (crtc) {
-		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-
 		/* Wait for pending flips before drmmode_set_mode_major calls
 		 * drmmode_crtc_update_tear_free, to prevent a nested
 		 * drmHandleEvent call, which would hang
 		 */
-		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
-						drmmode_crtc->flip_pending);
+		radeon_drm_wait_pending_flip(crtc);
 		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
 				       crtc->x, crtc->y);
 	}
@@ -3370,8 +3358,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 			radeon_cs_flush_indirect(crtc->scrn);
 
 			if (drmmode_crtc->scanout_update_pending) {
-				drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
-								drmmode_crtc->flip_pending);
+				radeon_drm_wait_pending_flip(crtc);
 				radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending);
 				drmmode_crtc->scanout_update_pending = 0;
 			}
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index bff010fa..69474be2 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -178,6 +178,19 @@ radeon_drm_abort_id(uint64_t id)
 }
 
 /*
+ * Wait for pending page flip on given CRTC to complete
+ */
+void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc)
+{
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+    while (drmmode_crtc->flip_pending &&
+	   drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) > 0);
+}
+
+/*
  * Initialize the DRM event queue
  */
 void
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index b6aab37c..96f88bd3 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -47,6 +47,7 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 void radeon_drm_abort_client(ClientPtr client);
 void radeon_drm_abort_entry(uintptr_t seq);
 void radeon_drm_abort_id(uint64_t id);
+void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc);
 void radeon_drm_queue_init(ScrnInfoPtr scrn);
 void radeon_drm_queue_close(ScrnInfoPtr scrn);
 
commit ecdf0b7ec9378bc386ce8276f16fb16d09f72812
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 16 17:14:42 2018 +0200

    Move DRM event queue related initialization to radeon_drm_queue_init
    
    And make radeon_drm_queue_handler not directly accessible outside of
    radeon_drm_queue.c.
    
    (Ported from amdgpu commit 0148283984c77f7a6e97026edc3093497547e0a4)
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 68d6254d..385c5b3e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2742,10 +2742,6 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
 
 	xf86InitialConfiguration(pScrn, TRUE);
 
-	drmmode->event_context.version = 2;
-	drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
-	drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
-
 	pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt);
 
 	drmModeFreeResources(mode_res);
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index c36e06f2..4d12fc09 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -968,13 +968,15 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
 
     scrn = crtc->scrn;
     pRADEONEnt = RADEONEntPriv(scrn);
+    drmmode_crtc = event_info->crtc->driver_private;
     ret = drmmode_get_current_ust(pRADEONEnt->fd, &drm_now);
     if (ret) {
 	xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 		   "%s cannot get current time\n", __func__);
 	if (event_info->drm_queue_seq)
-	    radeon_drm_queue_handler(pRADEONEnt->fd, 0, 0, 0,
-				     (void*)event_info->drm_queue_seq);
+	    drmmode_crtc->drmmode->event_context.
+		vblank_handler(pRADEONEnt->fd, 0, 0, 0,
+			       (void*)event_info->drm_queue_seq);
 	else
 	    radeon_dri2_frame_event_handler(crtc, 0, 0, data);
 	return 0;
@@ -983,15 +985,15 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
      * calculate the frame number from current time
      * that would come from CRTC if it were running
      */
-    drmmode_crtc = event_info->crtc->driver_private;
     delta_t = drm_now - (CARD64)drmmode_crtc->dpms_last_ust;
     delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
     delta_seq /= 1000000;
     frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq;
     if (event_info->drm_queue_seq)
-	radeon_drm_queue_handler(pRADEONEnt->fd, frame, drm_now / 1000000,
-				 drm_now % 1000000,
-				 (void*)event_info->drm_queue_seq);
+	drmmode_crtc->drmmode->event_context.
+	    vblank_handler(pRADEONEnt->fd, frame, drm_now / 1000000,
+			   drm_now % 1000000,
+			   (void*)event_info->drm_queue_seq);
     else
 	radeon_dri2_frame_event_handler(crtc, frame, drm_now, data);
     return 0;
diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c
index ac775f86..bff010fa 100644
--- a/src/radeon_drm_queue.c
+++ b/src/radeon_drm_queue.c
@@ -57,7 +57,7 @@ static uintptr_t radeon_drm_queue_seq;
 /*
  * Handle a DRM event
  */
-void
+static void
 radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
 			 unsigned int usec, void *user_ptr)
 {
@@ -181,8 +181,15 @@ radeon_drm_abort_id(uint64_t id)
  * Initialize the DRM event queue
  */
 void
-radeon_drm_queue_init()
+radeon_drm_queue_init(ScrnInfoPtr scrn)
 {
+    RADEONInfoPtr info = RADEONPTR(scrn);
+    drmmode_ptr drmmode = &info->drmmode;
+
+    drmmode->event_context.version = 2;
+    drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
+    drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
+
     if (radeon_drm_queue_refcnt++)
 	return;
 
diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h
index c3e2076d..b6aab37c 100644
--- a/src/radeon_drm_queue.h
+++ b/src/radeon_drm_queue.h
@@ -40,9 +40,6 @@ typedef void (*radeon_drm_handler_proc)(xf86CrtcPtr crtc, uint32_t seq,
 					uint64_t usec, void *data);
 typedef void (*radeon_drm_abort_proc)(xf86CrtcPtr crtc, void *data);
 
-void radeon_drm_queue_handler(int fd, unsigned int frame,
-			      unsigned int tv_sec, unsigned int tv_usec,
-			      void *user_ptr);
 uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 				 uint64_t id, void *data,
 				 radeon_drm_handler_proc handler,
@@ -50,7 +47,7 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 void radeon_drm_abort_client(ClientPtr client);
 void radeon_drm_abort_entry(uintptr_t seq);
 void radeon_drm_abort_id(uint64_t id);
-void radeon_drm_queue_init();
+void radeon_drm_queue_init(ScrnInfoPtr scrn);
 void radeon_drm_queue_close(ScrnInfoPtr scrn);
 
 #endif /* _RADEON_DRM_QUEUE_H_ */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 36840ad3..809d2446 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -1789,7 +1789,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 	return FALSE;
     }
 
-    radeon_drm_queue_init();
+    radeon_drm_queue_init(pScrn);
 
     info->allowColorTiling2D = FALSE;
 
commit 824189b3da9edc33e1a4f5c6130a043da73c1a4c
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Aug 16 18:22:27 2018 +0200

    Use correct FB handle in radeon_do_pageflip
    
    We were always using the handle of the client provided FB, which
    prevented RandR transforms from working, and could result in a black
    screen.
    
    Bugzilla: https://bugs.freedesktop.org/107519
    Fixes: 740f0850f1e4 "Store FB for each CRTC in drmmode_flipdata_rec"
    (Ported from amdgpu commit f6cd72e64e85896b6d155bee0930e59771dcb701)
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 0b92b70c..68d6254d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -3386,7 +3386,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[i]->handle,
 							      flip_flags,
 							      drm_queue_seq,
 							      target_msc) != 0)
@@ -3394,7 +3394,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		} else {
 			if (drmmode_page_flip_target_relative(pRADEONEnt,
 							      drmmode_crtc,
-							      fb->handle,
+							      flipdata->fb[i]->handle,
 							      flip_flags,
 							      drm_queue_seq, 0) != 0)
 				goto flip_error;


More information about the xorg-commit mailing list