xf86-video-intel: 5 commits - src/sna/sna_dri2.c src/sna/sna_present.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Mar 16 06:38:24 UTC 2016


 src/sna/sna_dri2.c    |  108 +++++++++++++++++++++++++-------------------------
 src/sna/sna_present.c |   11 ++---
 test/present-test.c   |   14 ++++++
 3 files changed, 73 insertions(+), 60 deletions(-)

New commits:
commit b6f204b62bbf2d0918761bb7773d2f80fff985fd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 15 21:24:20 2016 +0000

    sna/dri2: Prevent starting a swap chain for a decoupled Pixmap
    
    When a Window is resized, a new Pixmap is attached to the Window and the
    DRI2 buffers invalidated. However, the client may have requested a swap
    before it is notified of the resize and so we have to discard the stale
    swap. In doing so, we do not want to start a swap chain as it references
    the wrong frontbuffer and causes dire confusion when we start swapping
    for real.
    
    Reported-by: Jiri Slaby <jirislaby at gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70461#c131
    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 63d1f27..e3dce81 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -874,8 +874,9 @@ static void _sna_dri2_destroy_buffer(struct sna *sna,
 	if (buffer == NULL)
 		return;
 
-	DBG(("%s: %p [handle=%d] -- refcnt=%d, pixmap=%ld, proxy?=%d\n",
+	DBG(("%s: %p [handle=%d] -- refcnt=%d, draw=%ld, pixmap=%ld, proxy?=%d\n",
 	     __FUNCTION__, buffer, private->bo->handle, private->refcnt,
+	     draw ? draw->id : 0,
 	     private->pixmap ? private->pixmap->drawable.serialNumber : 0,
 	     private->proxy != NULL));
 	assert(private->refcnt > 0);
@@ -2329,10 +2330,10 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
 	back_bo = get_private(back)->bo;
 	front_bo = get_private(front)->bo;
 
-	DBG(("%s: win=%ld, exchange front=%d/%d and back=%d/%d, pixmap=%ld %dx%d\n",
+	DBG(("%s: win=%ld, exchange front=%d/%d,ref=%d and back=%d/%d,ref=%d, pixmap=%ld %dx%d\n",
 	     __FUNCTION__, win->drawable.id,
-	     front_bo->handle, front->name,
-	     back_bo->handle, back->name,
+	     front_bo->handle, front->name, get_private(front)->refcnt,
+	     back_bo->handle, back->name, get_private(back)->refcnt,
 	     pixmap->drawable.serialNumber,
 	     pixmap->drawable.width,
 	     pixmap->drawable.height));
@@ -3304,6 +3305,14 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	assert(get_private(front)->bo->refcnt);
 	assert(get_private(back)->bo->refcnt);
 
+	if (get_private(front)->pixmap != get_drawable_pixmap(draw)) {
+		DBG(("%s: decoupled DRI2 front pixmap=%ld, actual pixmap=%ld\n",
+		     __FUNCTION__,
+		     get_private(front)->pixmap->drawable.serialNumber,
+		     get_drawable_pixmap(draw)->drawable.serialNumber));
+		goto fake;
+	}
+
 	if (get_private(back)->stale) {
 		DBG(("%s: stale back buffer\n", __FUNCTION__));
 		goto skip;
@@ -3317,6 +3326,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 			front = priv->front;
 			assert(front->attachment == DRI2BufferFrontLeft);
 			assert(get_private(front)->refcnt);
+			assert(get_private(front)->pixmap == get_drawable_pixmap(draw));
 		}
 
 		if (win->clipList.extents.x2 <= win->clipList.extents.x1 ||
@@ -3331,16 +3341,8 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 		}
 	}
 
-	DBG(("%s: using front handle=%d, active_scanout?=%d\n", __FUNCTION__, get_private(front)->bo->handle, get_private(front)->bo->active_scanout));
+	DBG(("%s: using front handle=%d, active_scanout?=%d, flush?=%d\n", __FUNCTION__, get_private(front)->bo->handle, get_private(front)->bo->active_scanout, sna_pixmap_from_drawable(draw)->flush));
 	assert(get_private(front)->bo->active_scanout);
-	if (get_private(front)->pixmap != get_drawable_pixmap(draw)) {
-		DBG(("%s: decoupled DRI2 front pixmap=%ld, actual pixmap=%ld\n",
-		     __FUNCTION__,
-		     get_private(front)->pixmap->drawable.serialNumber,
-		     get_drawable_pixmap(draw)->drawable.serialNumber));
-		goto skip;
-	}
-
 	assert(sna_pixmap_from_drawable(draw)->flush);
 
 	/* Drawable not displayed... just complete the swap */
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index cec06d8..f95a12c 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -323,7 +323,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 		present_event_notify(event_id, swap_ust(swap), swap->msc);
 		return Success;
 	}
-	warn_unless(msc < swap->msc + 1ull<<32);
+	warn_unless(msc < swap->msc + (1ull<<32));
 
 	list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
 		if (tmp->target_msc == msc &&
commit a11cbb6954f08edd0d8fb5eeca1debb289fdb9af
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 15 21:11:48 2016 +0000

    sna/dri2: Cancel all pending events when the window is resized
    
    Kill the events early for simplicity.
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=70461#c138
    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 c334643..63d1f27 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1816,19 +1816,12 @@ sna_dri2_add_event(struct sna *sna,
 	return info;
 }
 
-void sna_dri2_decouple_window(WindowPtr win)
+static void decouple_window(WindowPtr win,
+			    struct dri2_window *priv,
+			    struct sna *sna)
 {
-	struct dri2_window *priv;
-
-	priv = dri2_window(win);
-	if (priv == NULL)
-		return;
-
-	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
-
 	if (priv->front) {
-		struct sna *sna = to_sna_from_drawable(&win->drawable);
-
+		DBG(("%s: decouple private front\n", __FUNCTION__));
 		assert(priv->crtc);
 		sna_shadow_unset_crtc(sna, priv->crtc);
 
@@ -1836,28 +1829,6 @@ void sna_dri2_decouple_window(WindowPtr win)
 		priv->front = NULL;
 	}
 
-	priv->scanout = -1;
-}
-
-void sna_dri2_destroy_window(WindowPtr win)
-{
-	struct dri2_window *priv;
-	struct sna *sna;
-
-	priv = dri2_window(win);
-	if (priv == NULL)
-		return;
-
-	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
-	sna = to_sna_from_drawable(&win->drawable);
-
-	if (priv->front) {
-		assert(priv->crtc);
-		sna_shadow_unset_crtc(sna, priv->crtc);
-
-		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
-	}
-
 	if (priv->chain) {
 		struct sna_dri2_event *info, *chain;
 
@@ -1892,6 +1863,34 @@ void sna_dri2_destroy_window(WindowPtr win)
 				sna_dri2_event_free(info);
 		}
 	}
+}
+
+void sna_dri2_decouple_window(WindowPtr win)
+{
+	struct dri2_window *priv;
+
+	priv = dri2_window(win);
+	if (priv == NULL)
+		return;
+
+	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
+	decouple_window(win, priv, to_sna_from_drawable(&win->drawable));
+
+	priv->scanout = -1;
+}
+
+void sna_dri2_destroy_window(WindowPtr win)
+{
+	struct dri2_window *priv;
+	struct sna *sna;
+
+	priv = dri2_window(win);
+	if (priv == NULL)
+		return;
+
+	DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id));
+	sna = to_sna_from_drawable(&win->drawable);
+	decouple_window(win, priv, sna);
 
 	while (!list_is_empty(&priv->cache)) {
 		struct dri_bo *c;
@@ -2677,10 +2676,9 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
 			else
 				__sna_dri2_copy_event(info, info->sync | DRI2_BO);
 
-			if (info->draw) {
-				info->keepalive++;
-				info->signal = true;
-			}
+			assert(info->draw);
+			info->keepalive++;
+			info->signal = true;
 		}
 
 		if (--info->keepalive) {
@@ -2768,7 +2766,7 @@ sna_dri2_immediate_blit(struct sna *sna,
 
 	if (chain->type == SWAP_COMPLETE) {
 		assert(chain->draw == info->draw);
-		assert(chain->front = info->front);
+		assert(chain->front == info->front);
 		assert(chain->client == info->client);
 		assert(chain->event_complete == info->event_complete);
 		assert(chain->event_data == info->event_data);
commit 0d42fce3c684a8ab6f45ad47f6a0dd20a1af0f5a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 15 16:15:02 2016 +0000

    sna/present: Use the current system time when providing a vblank off notify
    
    If we need to report the vblank after the pipe is off, just use the
    current system time rather than the last swap time from the pipe.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index d7a2661..cec06d8 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -192,11 +192,10 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 			(void)sna_wait_vblank(info->sna, &vbl, sna_crtc_pipe(info->crtc));
 		}
 	} else {
-		const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
-		ust = swap_ust(swap);
-		msc = swap->msc;
-		DBG(("%s: event=%lld, CRTC OFF, target msc=%lld, was %lld\n",
-		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)msc));
+		ust = gettime_ust64();
+		msc = info->target_msc;
+		DBG(("%s: event=%lld, CRTC OFF, target msc=%lld, was %lld (off)\n",
+		     __FUNCTION__, (long long)info->event_id[0], (long long)info->target_msc, (long long)sna_crtc_last_swap(info->crtc)->msc));
 	}
 
 	vblank_complete(info, ust, msc);
commit a0bf3c1f48bc77f508f169d3ec8b64aecc902bc2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 15 16:12:56 2016 +0000

    test/present: Catch FPE when notifies are broken
    
    If the Xserver reports 10 frames passed instantaneously, flag an error
    rather than divide by zero.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index b33fd2e..af1882a 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -248,6 +248,12 @@ static uint64_t msc_interval(Display *dpy, Window win, void *q)
 		free(ev);
 	} while (complete != 2);
 
+	printf("10 frame interval: msc=%lld, ust=%lld\n",
+	       (long long)msc, (long long)ust);
+	XSync(dpy, True);
+	if (msc == 0)
+		return 0;
+
 	return (ust + msc/2) / msc;
 }
 
@@ -466,6 +472,10 @@ static int test_future(Display *dpy, Window win, const char *phase, void *Q)
 	_x_error_occurred = 0;
 
 	interval = msc_interval(dpy, win, Q);
+	if (interval == 0) {
+		printf("Zero delay between frames\n");
+		return 1;
+	}
 
 	pixmap = XCreatePixmap(dpy, win, width, height, depth);
 	msc = flush_flips(dpy, win, pixmap, Q, &ust);
@@ -918,6 +928,10 @@ static int test_future_msc(Display *dpy, void *Q)
 	_x_error_occurred = 0;
 
 	interval = msc_interval(dpy, root, Q);
+	if (interval == 0) {
+		printf("Zero delay between frames\n");
+		return 1;
+	}
 	msc = check_msc(dpy, root, Q, 0, &ust);
 
 	for (n = 1; n <= 10; n++)
commit 4e88e7dcc704d89583620af6af2738d49db9e5aa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 15 21:03:52 2016 +0000

    sna/dri2: Rearrange "impossible" paths to avoid an assert
    
    Ensure that we don't try and double-free the decoupled vblank event by
    checking whether it is still pending first.
    
    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 2ed698d..c334643 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2484,14 +2484,14 @@ static void chain_swap(struct sna_dri2_event *chain)
 	DBG(("%s: draw=%ld, queued?=%d, type=%d\n",
 	     __FUNCTION__, (long)chain->draw->id, chain->queued, chain->type));
 
+	if (chain->queued) /* too early! */
+		return;
+
 	if (chain->draw == NULL) {
 		sna_dri2_event_free(chain);
 		return;
 	}
 
-	if (chain->queued) /* too early! */
-		return;
-
 	assert(chain == dri2_chain(chain->draw));
 	assert(chain->signal);
 


More information about the xorg-commit mailing list