xf86-video-intel: 5 commits - src/sna/sna_dri2.c src/sna/sna_driver.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Aug 19 14:00:04 PDT 2015


 src/sna/sna_dri2.c   |  302 ++++++++++++++++++++++-----------------------------
 src/sna/sna_driver.c |    2 
 2 files changed, 132 insertions(+), 172 deletions(-)

New commits:
commit 74c1e45ed5797eca5dec6dcea8f6f734d23d0f89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 19 21:08:58 2015 +0100

    sna/dri2: Look for potential flip targets when recreating backbuffers
    
    As the window may be reparented during its swap lifetime, we may be able
    to recreate the backbuffer ready for flipping next swap.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 2b4075b..f805d26 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -197,6 +197,7 @@ struct dri2_window {
 	int64_t msc_delta;
 	struct list cache;
 	uint32_t cache_size;
+	int scanout;
 };
 
 static struct dri2_window *dri2_window(WindowPtr win)
@@ -205,6 +206,23 @@ static struct dri2_window *dri2_window(WindowPtr win)
 	return ((void **)__get_private(win, sna_window_key))[1];
 }
 
+static bool use_scanout(struct sna *sna,
+			DrawablePtr draw,
+			struct dri2_window *priv)
+{
+	if (priv->front)
+		return true;
+
+	if (priv->scanout < 0)
+		priv->scanout =
+			(sna->flags & (SNA_LINEAR_FB | SNA_NO_WAIT | SNA_NO_FLIP)) == 0 &&
+			draw->width  == sna->front->drawable.width &&
+			draw->height == sna->front->drawable.height &&
+			draw->bitsPerPixel == sna->front->drawable.bitsPerPixel;
+
+	return priv->scanout;
+}
+
 static void
 sna_dri2_get_back(struct sna *sna,
 		  DrawablePtr draw,
@@ -218,11 +236,12 @@ sna_dri2_get_back(struct sna *sna,
 	int flags;
 	bool reuse;
 
-	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, pitch=%d, front pitch=%d\n",
+	DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, active?=%d, pitch=%d, front pitch=%d\n",
 	     __FUNCTION__, draw->width, draw->height,
 	     get_private(back)->bo->handle,
 	     get_private(back)->size & 0xffff, get_private(back)->size >> 16,
 	     get_private(back)->bo->scanout,
+	     get_private(back)->bo->active_scanout,
 	     back->pitch, front_pitch(draw)));
 	assert(priv);
 
@@ -242,13 +261,15 @@ sna_dri2_get_back(struct sna *sna,
 	}
 
 	reuse = size == get_private(back)->size;
-	if (reuse && get_private(back)->bo->scanout)
+	if (reuse)
 		reuse = front_pitch(draw) == back->pitch;
+	if (reuse)
+		reuse = get_private(back)->bo->scanout == use_scanout(sna, draw, priv);
 	DBG(("%s: reuse backbuffer? %d\n", __FUNCTION__, reuse));
 	if (reuse) {
 		bo = get_private(back)->bo;
 		assert(bo->refcnt);
-		DBG(("%s: back buffer handle=%d, scanout?=%d, refcnt=%d\n",
+		DBG(("%s: back buffer handle=%d, active?=%d, refcnt=%d\n",
 		     __FUNCTION__, bo->handle, bo->active_scanout, get_private(back)->refcnt));
 		if (bo->active_scanout == 0) {
 			DBG(("%s: reuse unattached back\n", __FUNCTION__));
@@ -274,10 +295,17 @@ sna_dri2_get_back(struct sna *sna,
 	}
 	if (bo == NULL) {
 		DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
+		flags = CREATE_EXACT;
+
+		if (use_scanout(sna, draw, priv)) {
+			DBG(("%s: requesting scanout compatible back\n", __FUNCTION__));
+			flags |= CREATE_SCANOUT;
+		}
+
 		bo = kgem_create_2d(&sna->kgem,
 				    draw->width, draw->height, draw->bitsPerPixel,
 				    get_private(back)->bo->tiling,
-				    get_private(back)->bo->scanout ? CREATE_SCANOUT | CREATE_EXACT : CREATE_EXACT);
+				    flags);
 		if (bo == NULL)
 			return;
 
@@ -1492,6 +1520,7 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc)
 			priv->crtc = crtc;
 			priv->msc_delta = 0;
 			priv->chain = NULL;
+			priv->scanout = -1;
 			list_init(&priv->cache);
 			dri2_window_attach((WindowPtr)draw, priv);
 		}
@@ -1781,6 +1810,8 @@ void sna_dri2_decouple_window(WindowPtr win)
 		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
 		priv->front = NULL;
 	}
+
+	priv->scanout = -1;
 }
 
 void sna_dri2_destroy_window(WindowPtr win)
commit 3d0cd2dfcac7b855d60c86070a874c6d950466a6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 19 20:27:29 2015 +0100

    sna/dri2: Extend the active buffer tracking to TearFree
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index f1d7a6e..2b4075b 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -535,13 +535,18 @@ sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo)
 	if (private->bo == bo)
 		return;
 
+	assert(private->bo->active_scanout > 0);
+	private->bo->active_scanout--;
+
 	DBG(("%s: dropping flush hint from handle=%d\n", __FUNCTION__, private->bo->handle));
 	private->bo->flush = false;
 	kgem_bo_destroy(&sna->kgem, private->bo);
 
+
 	buffer->name = kgem_bo_flink(&sna->kgem, bo);
 	buffer->pitch = bo->pitch;
 	private->bo = ref(bo);
+	bo->active_scanout++;
 
 	DBG(("%s: adding flush hint to handle=%d\n", __FUNCTION__, bo->handle));
 	bo->flush = true;
commit 819971e7a62e695fe4b75af80557b783c8caafd3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 19 20:24:37 2015 +0100

    sna/dri2: Remove stale active buffer assert
    
    Since the DRI2BufferPtr destruction may be delayed, by the time we do
    free it, the state may no longer be accurate. (At this level at least,
    there is a later assertion to the same regard just as we think we are
    releasing the buffer.)
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 177b921..f1d7a6e 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -821,7 +821,6 @@ sna_dri2_cache_bo(struct sna *sna,
 	return;
 
 err:
-	assert(bo->active_scanout == 0 || bo->scanout);
 	kgem_bo_destroy(&sna->kgem, bo);
 }
 
commit 6f3e81d430dc80d892d3ffe8b101ff991040237a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 19 19:59:56 2015 +0100

    sna/dri2: Consolidate vblank queueing into a couple of helpers
    
    With the rigamorale of assertions, using the vblank is no longer
    trivial.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 41354e8..177b921 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1413,15 +1413,53 @@ inline static uint32_t pipe_select(int pipe)
 		return 0;
 }
 
-static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, int pipe)
+static inline bool sna_next_vblank(struct sna_dri2_event *info)
 {
-	DBG(("%s(pipe=%d, waiting until seq=%u%s)\n",
-	     __FUNCTION__, pipe, vbl->request.sequence,
-	     vbl->request.type & DRM_VBLANK_RELATIVE ? " [relative]" : ""));
-	assert(pipe != -1);
+	union drm_wait_vblank vbl;
 
-	vbl->request.type |= pipe_select(pipe);
-	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+	DBG(("%s(pipe=%d, waiting until next vblank)\n",
+	     __FUNCTION__, info->pipe));
+	assert(info->pipe != -1);
+
+	VG_CLEAR(vbl);
+	vbl.request.type =
+		DRM_VBLANK_RELATIVE |
+		DRM_VBLANK_EVENT |
+		pipe_select(info->pipe);
+	vbl.request.sequence = 1;
+	vbl.request.signal = (uintptr_t)info;
+
+	assert(!info->queued);
+	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
+		return false;
+
+	info->queued = true;
+	return true;
+}
+
+static inline bool sna_wait_vblank(struct sna_dri2_event *info,
+				   unsigned seq)
+{
+	union drm_wait_vblank vbl;
+
+	DBG(("%s(pipe=%d, waiting until vblank %u)\n",
+	     __FUNCTION__, info->pipe, seq));
+	assert(info->pipe != -1);
+
+	VG_CLEAR(vbl);
+	vbl.request.type =
+		DRM_VBLANK_ABSOLUTE |
+		DRM_VBLANK_EVENT |
+		pipe_select(info->pipe);
+	vbl.request.sequence = seq;
+	vbl.request.signal = (uintptr_t)info;
+
+	assert(!info->queued);
+	if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
+		return false;
+
+	info->queued = true;
+	return true;
 }
 
 #if DRI2INFOREC_VERSION >= 4
@@ -2376,8 +2414,6 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
 
 static void chain_swap(struct sna_dri2_event *chain)
 {
-	union drm_wait_vblank vbl;
-
 	DBG(("%s: draw=%ld, queued?=%d, type=%d\n",
 	     __FUNCTION__, (long)chain->draw->id, chain->queued, chain->type));
 
@@ -2399,18 +2435,8 @@ static void chain_swap(struct sna_dri2_event *chain)
 		    !chain->sna->mode.shadow_damage) {
 			/* recursed from wait_for_shadow(), simply requeue */
 			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
-			VG_CLEAR(vbl);
-			vbl.request.type =
-				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT;
-			vbl.request.sequence = 1;
-			vbl.request.signal = (uintptr_t)chain;
-
-			assert(!chain->queued);
-			if (!sna_wait_vblank(chain->sna, &vbl, chain->pipe)) {
-				chain->queued = true;
+			if (sna_next_vblank(chain))
 				return;
-			}
 
 			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
 		}
@@ -2431,23 +2457,14 @@ static void chain_swap(struct sna_dri2_event *chain)
 		return;
 	}
 
-	VG_CLEAR(vbl);
-	vbl.request.type =
-		DRM_VBLANK_RELATIVE |
-		DRM_VBLANK_EVENT;
-	vbl.request.sequence = 1;
-	vbl.request.signal = (uintptr_t)chain;
-
-	assert(!chain->queued);
 	if ((chain->type == SWAP_COMPLETE &&
 	     !swap_limit(chain->draw, 2 + !chain->sync) &&
 	     !chain->sync) ||
-	    sna_wait_vblank(chain->sna, &vbl, chain->pipe)) {
+	    !sna_next_vblank(chain)) {
 		DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
 		frame_swap_complete(chain, DRI2_BLIT_COMPLETE);
 		sna_dri2_event_free(chain);
-	} else
-		chain->queued = true;
+	}
 }
 
 static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
@@ -2468,27 +2485,13 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
 	return __kgem_busy(kgem, bo->handle);
 }
 
-static bool sna_dri2_blit_complete(struct sna *sna,
-				   struct sna_dri2_event *info)
+static bool sna_dri2_blit_complete(struct sna_dri2_event *info)
 {
-	if (rq_is_busy(&sna->kgem, info->bo)) {
-		union drm_wait_vblank vbl;
-
+	if (rq_is_busy(&info->sna->kgem, info->bo)) {
 		DBG(("%s: vsync'ed blit is still busy, postponing\n",
 		     __FUNCTION__));
-
-		VG_CLEAR(vbl);
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.sequence = 1;
-		vbl.request.signal = (uintptr_t)info;
-
-		assert(!info->queued);
-		if (!sna_wait_vblank(sna, &vbl, info->pipe)) {
-			info->queued = true;
+		if (sna_next_vblank(info))
 			return false;
-		}
 	}
 
 	DBG(("%s: blit finished\n", __FUNCTION__));
@@ -2501,7 +2504,6 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
 	struct sna_dri2_event *info = (void *)(uintptr_t)event->user_data;
 	struct sna *sna = info->sna;
 	DrawablePtr draw;
-	union drm_wait_vblank vbl;
 	uint64_t msc;
 
 	DBG(("%s(type=%d, sequence=%d, draw=%ld)\n", __FUNCTION__, info->type, event->sequence, info->draw ? info->draw->serialNumber : 0));
@@ -2543,18 +2545,8 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
 			info->type = SWAP_COMPLETE;
 		}
 
-		VG_CLEAR(vbl);
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.sequence = 1;
-		vbl.request.signal = (uintptr_t)info;
-
-		assert(!info->queued);
-		if (!sna_wait_vblank(sna, &vbl, info->pipe)) {
-			info->queued = true;
+		if (sna_next_vblank(info))
 			return;
-		}
 
 		DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
 		assert(info->pending.bo == NULL);
@@ -2566,7 +2558,7 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
 		     event->sequence, event->tv_sec, event->tv_usec));
 
 		if (info->signal) {
-			if (!sna_dri2_blit_complete(sna, info))
+			if (!sna_dri2_blit_complete(info))
 				return;
 
 			DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
@@ -2607,18 +2599,8 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
 		}
 
 		if (--info->keepalive) {
-			VG_CLEAR(vbl);
-			vbl.request.type =
-				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT;
-			vbl.request.sequence = 1;
-			vbl.request.signal = (uintptr_t)info;
-
-			assert(!info->queued);
-			if (!sna_wait_vblank(sna, &vbl, info->pipe)) {
-				info->queued = true;
+			if (sna_next_vblank(info))
 				return;
-			}
 
 			if (info->signal) {
 				DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__,
@@ -2672,8 +2654,6 @@ sna_dri2_immediate_blit(struct sna *sna,
 	info->keepalive = KEEPALIVE;
 
 	if (chain == info) {
-		union drm_wait_vblank vbl;
-
 		DBG(("%s: no pending blit, starting chain\n", __FUNCTION__));
 
 		if (can_xchg(info->sna, info->draw, info->front, info->back)) {
@@ -2687,21 +2667,12 @@ sna_dri2_immediate_blit(struct sna *sna,
 
 		assert(info->signal);
 
-		VG_CLEAR(vbl);
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.sequence = 1;
-		vbl.request.signal = (uintptr_t)info;
-
-		assert(!info->queued);
 		if ((!swap_limit(draw, 2 + !sync) && !sync) ||
-		    sna_wait_vblank(sna, &vbl, info->pipe)) {
+		    !sna_next_vblank(info)) {
 			DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
 			frame_swap_complete(info, DRI2_BLIT_COMPLETE);
 			sna_dri2_event_free(info);
 		}
-		info->queued = true;
 		return;
 	}
 
@@ -2822,24 +2793,10 @@ static void chain_flip(struct sna *sna)
 		__sna_dri2_copy_event(chain, DRI2_SYNC);
 
 		if (xorg_can_triple_buffer()) {
-			union drm_wait_vblank vbl;
-
-			VG_CLEAR(vbl);
-
 			chain->type = SWAP_COMPLETE;
 			assert(chain->signal);
-
-			vbl.request.type =
-				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT;
-			vbl.request.sequence = 1;
-			vbl.request.signal = (uintptr_t)chain;
-
-			assert(!chain->queued);
-			if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
-				chain->queued = true;
+			if (sna_next_vblank(chain))
 				return;
-			}
 		}
 
 		DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__));
@@ -2913,16 +2870,24 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
 	}
 }
 
+static int
+sna_query_vblank(struct sna *sna, xf86CrtcPtr crtc, union drm_wait_vblank *vbl)
+{
+	VG_CLEAR(*vbl);
+	vbl->request.type =
+		_DRM_VBLANK_RELATIVE | pipe_select(sna_crtc_pipe(crtc));
+	vbl->request.sequence = 0;
+
+	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+}
+
 static uint64_t
 get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
 {
 	union drm_wait_vblank vbl;
 	uint64_t ret;
 
-	VG_CLEAR(vbl);
-	vbl.request.type = _DRM_VBLANK_RELATIVE;
-	vbl.request.sequence = 0;
-	if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0)
+	if (sna_query_vblank(sna, crtc, &vbl) == 0)
 		ret = sna_crtc_record_vblank(crtc, &vbl);
 	else
 		ret = sna_crtc_last_swap(crtc)->msc;
@@ -3142,25 +3107,12 @@ queue:
 	if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) {
 		*target_msc = current_msc + 1;
 	} else {
-		union drm_wait_vblank vbl;
-
-		VG_CLEAR(vbl);
-
-		vbl.request.type =
-			DRM_VBLANK_ABSOLUTE |
-			DRM_VBLANK_EVENT;
-
 		/* Account for 1 frame extra pageflip delay */
-		vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
-		vbl.request.signal = (uintptr_t)info;
-
-		assert(!info->queued);
-		if (sna_wait_vblank(sna, &vbl, info->pipe)) {
+		if (!sna_wait_vblank(info,
+				     draw_target_seq(draw, *target_msc - 1))) {
 			sna_dri2_event_free(info);
 			return false;
 		}
-
-		info->queued = true;
 	}
 
 	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
@@ -3202,7 +3154,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		       CARD64 remainder, DRI2SwapEventPtr func, void *data)
 {
 	struct sna *sna = to_sna_from_drawable(draw);
-	union drm_wait_vblank vbl;
 	xf86CrtcPtr crtc = NULL;
 	struct sna_dri2_event *info = NULL;
 	int type = DRI2_EXCHANGE_COMPLETE;
@@ -3296,8 +3247,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 				  func, data))
 		return TRUE;
 
-	VG_CLEAR(vbl);
-
 	info = sna_dri2_add_event(sna, draw, client, crtc);
 	if (!info)
 		goto blit;
@@ -3319,32 +3268,28 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		return TRUE;
 	}
 
-	vbl.request.type =
-		DRM_VBLANK_ABSOLUTE |
-		DRM_VBLANK_EVENT;
-	vbl.request.signal = (uintptr_t)info;
-
 	info->type = SWAP;
-	vbl.request.sequence = draw_target_seq(draw, *target_msc - 1);
 	if (*target_msc <= current_msc + 1) {
 		DBG(("%s: performing blit before queueing\n", __FUNCTION__));
 		__sna_dri2_copy_event(info, DRI2_SYNC);
 		info->type = SWAP_COMPLETE;
+		if (!sna_next_vblank(info))
+			goto fake;
 
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.sequence = 1;
+		DBG(("%s: reported target_msc=%llu\n",
+		     __FUNCTION__, *target_msc));
 		*target_msc = current_msc + 1;
-	}
+		swap_limit(draw, 2);
+	} else {
+		if (!sna_wait_vblank(info,
+				     draw_target_seq(draw, *target_msc - 1)))
+			goto blit;
 
-	assert(!info->queued);
-	if (sna_wait_vblank(sna, &vbl, info->pipe))
-		goto blit;
-	info->queued = true;
+		DBG(("%s: reported target_msc=%llu (in)\n",
+		     __FUNCTION__, *target_msc));
+		swap_limit(draw, 1);
+	}
 
-	DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc));
-	swap_limit(draw, 1 + (info->type == SWAP_COMPLETE));
 	return TRUE;
 
 blit:
@@ -3366,7 +3311,7 @@ skip:
 		if (info != dri2_chain(draw))
 			goto fake;
 
-	assert(info->crtc == crtc);
+		assert(info->crtc == crtc);
 
 		info->type = SWAP_COMPLETE;
 		info->event_complete = func;
@@ -3376,18 +3321,9 @@ skip:
 		info->front = sna_dri2_reference_buffer(front);
 		info->back = sna_dri2_reference_buffer(back);
 
-		VG_CLEAR(vbl);
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.signal = (uintptr_t)info;
-		vbl.request.sequence = 1;
-
-		assert(!info->queued);
-		if (sna_wait_vblank(sna, &vbl, info->pipe))
+		if (!sna_next_vblank(info))
 			goto fake;
 
-		info->queued = true;
 		swap_limit(draw, 2);
 	} else {
 fake:
@@ -3412,21 +3348,16 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
 	struct sna *sna = to_sna_from_drawable(draw);
 	xf86CrtcPtr crtc = sna_dri2_get_crtc(draw);
 	const struct ust_msc *swap;
+	union drm_wait_vblank vbl;
 
 	DBG(("%s(draw=%ld, pipe=%d)\n", __FUNCTION__, draw->id,
 	     crtc ? sna_crtc_pipe(crtc) : -1));
 
-	if (crtc != NULL) {
-		union drm_wait_vblank vbl;
-
-		VG_CLEAR(vbl);
-		vbl.request.type = _DRM_VBLANK_RELATIVE;
-		vbl.request.sequence = 0;
-		if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0)
-			sna_crtc_record_vblank(crtc, &vbl);
-	} else
-		/* Drawable not displayed, make up a *monotonic* value */
+	/* Drawable not displayed, make up a *monotonic* value */
+	if (crtc == NULL)
 		crtc = sna_primary_crtc(sna);
+	if (sna_query_vblank(sna, crtc, &vbl) == 0)
+		sna_crtc_record_vblank(crtc, &vbl);
 
 	swap = sna_crtc_last_swap(crtc);
 	*msc = draw_current_msc(draw, crtc, swap->msc);
@@ -3450,7 +3381,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
 	struct sna_dri2_event *info = NULL;
 	xf86CrtcPtr crtc;
 	CARD64 current_msc;
-	union drm_wait_vblank vbl;
 	const struct ust_msc *swap;
 
 	crtc = sna_dri2_get_crtc(draw);
@@ -3484,8 +3414,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
 	assert(info->crtc == crtc);
 	info->type = WAITMSC;
 
-	vbl.request.signal = (uintptr_t)info;
-	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 	/*
 	 * If divisor is zero, or current_msc is smaller than target_msc,
 	 * we just need to make sure target_msc passes before waking up the
@@ -3502,13 +3430,10 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
 		if (target_msc <= current_msc)
 			target_msc += divisor;
 	}
-	vbl.request.sequence = draw_target_seq(draw, target_msc);
 
-	assert(!info->queued);
-	if (sna_wait_vblank(sna, &vbl, info->pipe))
+	if (!sna_wait_vblank(info, draw_target_seq(draw, target_msc)))
 		goto out_free_info;
 
-	info->queued = true;
 	DRI2BlockClient(client, draw);
 	return TRUE;
 
commit e29dc33e3588035ce790e1d534e85a521b2955ce
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Aug 19 18:28:51 2015 +0100

    sna: Release the mode before releasing the accel backend on LeaveVT
    
    When we release the accel backend, we mark the interface as wedged.
    However, when we release the modesetting backend we flush the vblank
    queue which may want to do rendering. So if we do that first then
    disable the accel backend, things we go much smoother.
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=91658#c20
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 6db129f..18fc48d 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -903,8 +903,8 @@ static void sna_leave_vt(VT_FUNC_ARGS_DECL)
 
 	DBG(("%s\n", __FUNCTION__));
 
-	sna_accel_leave(sna);
 	sna_mode_reset(sna);
+	sna_accel_leave(sna);
 
 	if (intel_put_master(sna->dev))
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,


More information about the xorg-commit mailing list