xf86-video-intel: 2 commits - src/sna/sna_display.c src/sna/sna.h src/sna/sna_present.c test/present-test.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Feb 11 14:30:30 PST 2015


 src/sna/sna.h         |    6 +
 src/sna/sna_display.c |    8 +
 src/sna/sna_present.c |   89 ++++++++++++-------
 test/present-test.c   |  226 ++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 273 insertions(+), 56 deletions(-)

New commits:
commit 8348927c37b0550ce666d1156b0860b15de2a35a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Feb 10 16:54:07 2015 +0000

    sna/present: Handle fake RRCrtc
    
    Be sure we don't crash if the user requests presenting on one of our
    fake RRCrtcs.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 1ff36f3..d2c95ff 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -587,6 +587,7 @@ static inline void sna_present_vblank_handler(struct drm_event_vblank *event) {
 
 extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
 extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
+extern int sna_crtc_to_pipe__safe(xf86CrtcPtr crtc);
 extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
 extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
 extern bool sna_crtc_is_on(xf86CrtcPtr crtc);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 95c1b31..423b93d 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -280,6 +280,14 @@ int sna_crtc_to_pipe(xf86CrtcPtr crtc)
 	return to_sna_crtc(crtc)->pipe;
 }
 
+int sna_crtc_to_pipe__safe(xf86CrtcPtr crtc)
+{
+	if (to_sna_crtc(crtc))
+		return sna_crtc_to_pipe(crtc);
+	else
+		return sna_crtc_to_pipe(sna_primary_crtc(to_sna(crtc->scrn)));
+}
+
 uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
 {
 	assert(to_sna_crtc(crtc));
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 7bff86e..e578803 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -56,7 +56,7 @@ to_present_event(uintptr_t  data)
 
 static int pipe_from_crtc(RRCrtcPtr crtc)
 {
-	return crtc ? sna_crtc_to_pipe(crtc->devPrivate) : -1;
+	return crtc ? sna_crtc_to_pipe__safe(crtc->devPrivate) : -1;
 }
 
 static uint32_t pipe_select(int pipe)
commit 688f5e9bd7d3e1162db44ba341ac43e054aba237
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 11 16:12:41 2015 +0000

    sna/present: Compensate for time elapsed since last swap
    
    When computing the delay for the fake flip, compensate for any time
    elapsed since the last frame in order to hit the desired vblank more
    accurately. A side-effect of this is that we may now compute 0 delay
    timers which require special handling.
    
    Testcase: present-test/accuracy
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 9075167..1ff36f3 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -542,6 +542,11 @@ static inline uint64_t ust64(int tv_sec, int tv_usec)
 	return (uint64_t)tv_sec * 1000000 + tv_usec;
 }
 
+static inline uint64_t swap_ust(const struct ust_msc *swap)
+{
+	return ust64(swap->tv_sec, swap->tv_usec);
+}
+
 #if HAVE_DRI2
 bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen);
 void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event);
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 25b4e8b..7bff86e 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -78,10 +78,34 @@ static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, i
 	return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl);
 }
 
-static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t msc)
+static uint64_t gettime_ust64(void)
+{
+	struct timespec tv;
+
+	if (clock_gettime(CLOCK_MONOTONIC, &tv))
+		return GetTimeInMicros();
+
+	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
+}
+
+static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target)
 {
-	DisplayModePtr mode = &crtc->desiredMode;
-	return msc * mode->VTotal * mode->HTotal / mode->Clock;
+	const DisplayModeRec *mode = &crtc->desiredMode;
+	const struct ust_msc *swap = sna_crtc_last_swap(crtc);
+	int64_t delay, subframe;
+
+	delay = (target - swap->msc) * mode->VTotal * mode->HTotal / mode->Clock;
+	subframe = gettime_ust64() - swap_ust(swap);
+	subframe /= 1000;
+	if (subframe < delay)
+		delay -= subframe;
+	else
+		delay = 0;
+
+	DBG(("%s: sleep %d frames, %llu ms\n", __FUNCTION__,
+	     (int)(target - swap->msc), (long long)delay));
+	assert(delay >= 0);
+	return delay;
 }
 
 static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
@@ -90,7 +114,7 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 	union drm_wait_vblank vbl;
 	uint64_t msc, ust;
 
-	DBG(("%s(now=%d)\n", __FUNCTION__, now));
+	DBG(("%s(event=%lld, now=%d)\n", __FUNCTION__, (long long)info->event_id, now));
 
 	VG_CLEAR(vbl);
 	vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -98,12 +122,19 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 	if (sna_wait_vblank(info->sna, &vbl, sna_crtc_to_pipe(info->crtc)) == 0) {
 		ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec);
 		msc = sna_crtc_record_vblank(info->crtc, &vbl);
-		if (msc < info->target_msc)
-			return msc_to_delay(info->crtc, msc - info->target_msc);
+		DBG(("%s: event=%lld, target msc=%lld, now %lld\n",
+		     __FUNCTION__, (long long)info->event_id, (long long)info->target_msc, (long long)msc));
+		if (msc < info->target_msc) {
+			uint32_t delay = msc_to_delay(info->crtc, info->target_msc);
+			if (delay)
+				return delay;
+		}
 	} else {
 		const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
-		ust = ust64(swap->tv_sec, swap->tv_usec);
+		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, (long long)info->target_msc, (long long)msc));
 	}
 
 	present_event_notify(info->event_id, ust, msc);
@@ -112,20 +143,26 @@ static CARD32 sna_fake_vblank_handler(OsTimerPtr timer, CARD32 now, void *data)
 	return 0;
 }
 
-static bool sna_fake_vblank(struct sna_present_event *event)
+static bool sna_fake_vblank(struct sna_present_event *info)
 {
-	uint64_t msc = sna_crtc_last_swap(event->crtc)->msc;
+	uint64_t msc = sna_crtc_last_swap(info->crtc)->msc;
 	uint32_t delay;
 
-	if (msc < event->target_msc)
-		delay = msc_to_delay(event->crtc, event->target_msc - msc);
+	if (msc < info->target_msc)
+		delay = msc_to_delay(info->crtc, info->target_msc);
 	else
 		delay = 0;
 
-	DBG(("%s(target_msc=%lld, msc=%lld, delay=%ums)\n",
-	     __FUNCTION__, event->target_msc, msc, delay));
+	DBG(("%s(event=%lld, target_msc=%lld, msc=%lld, delay=%ums)\n",
+	     __FUNCTION__, (long long)info->event_id, (long long)info->target_msc, msc, delay));
+	if (delay == 0) {
+		const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
+		present_event_notify(info->event_id, swap_ust(swap), swap->msc);
+		free(info);
+		return true;
+	}
 
-	return TimerSet(NULL, 0, delay, sna_fake_vblank_handler, event);
+	return TimerSet(NULL, 0, delay, sna_fake_vblank_handler, info);
 }
 
 static RRCrtcPtr
@@ -166,7 +203,7 @@ sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 		*msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl);
 	} else {
 		const struct ust_msc *swap = sna_crtc_last_swap(crtc->devPrivate);
-		*ust = ust64(swap->tv_sec, swap->tv_usec);
+		*ust = swap_ust(swap);
 		*msc = swap->msc;
 	}
 
@@ -213,6 +250,8 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 	event->target_msc = msc;
 	event->event_id = event_id;
 
+	assert((int64_t)(msc - sna_crtc_last_swap(event->crtc)->msc) >= 0);
+
 	VG_CLEAR(vbl);
 	vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
 	vbl.request.sequence = msc;
@@ -300,7 +339,7 @@ sna_present_check_flip(RRCrtcPtr crtc,
 
 	if (sync_flip) {
 		if ((sna->flags & SNA_HAS_FLIP) == 0) {
-			DBG(("%s: async flips not suported\n", __FUNCTION__));
+			DBG(("%s: sync flips not suported\n", __FUNCTION__));
 			return FALSE;
 		}
 	} else {
@@ -329,16 +368,6 @@ sna_present_check_flip(RRCrtcPtr crtc,
 	return TRUE;
 }
 
-static uint64_t gettime_ust64(void)
-{
-	struct timespec tv;
-
-	if (clock_gettime(CLOCK_MONOTONIC, &tv))
-		return 0;
-
-	return ust64(tv.tv_sec, tv.tv_nsec / 1000);
-}
-
 static Bool
 page_flip__async(struct sna *sna,
 		 RRCrtcPtr crtc,
@@ -386,7 +415,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
 	     info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
 	     swap.tv_sec, swap.tv_usec, (long long)swap.msc,
 	     (long long)info->event_id));
-	present_event_notify(info->event_id, ust64(swap.tv_sec, swap.tv_usec), swap.msc);
+	present_event_notify(info->event_id, swap_ust(&swap), swap.msc);
 
 	if (info->sna->present.unflip) {
 		DBG(("%s: executing queued unflip (event=%lld)\n", __FUNCTION__, info->sna->present.unflip));
@@ -519,9 +548,7 @@ notify:
 		     -1,
 		     swap->tv_sec, swap->tv_usec, (long long)swap->msc,
 		     (long long)event_id));
-		present_event_notify(event_id,
-				     ust64(swap->tv_sec, swap->tv_usec),
-				     swap->msc);
+		present_event_notify(event_id, swap_ust(swap), swap->msc);
 		return;
 	}
 
diff --git a/test/present-test.c b/test/present-test.c
index 6f6d6a8..9e5e96b 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -45,6 +45,7 @@
 #include <xcb/xcb.h>
 #include <xcb/present.h>
 #include <xcb/xfixes.h>
+#include <xcb/dri3.h>
 #include <xf86drm.h>
 #include <i915_drm.h>
 
@@ -138,9 +139,11 @@ static void *setup_msc(Display *dpy,  Window win)
 static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
 {
 	xcb_connection_t *c = XGetXCBConnection(dpy);
+	static uint32_t serial = 1;
 	uint64_t msc = 0;
+	int complete = 0;
 
-	xcb_present_notify_msc(c, win, 0, 0, 0, 0);
+	xcb_present_notify_msc(c, win, serial, 0, 0, 0);
 	xcb_flush(c);
 
 	do {
@@ -152,16 +155,22 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
 			break;
 
 		ce = (xcb_present_complete_notify_event_t *)ev;
-		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
+		if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
+		    ce->serial == serial) {
 			msc = ce->msc;
+			complete = 1;
+		}
 		free(ev);
-	} while (msc == 0);
+	} while (!complete);
 
 	if (msc < last_msc) {
 		printf("Invalid MSC: was %llu, now %llu\n",
 		       (long long)last_msc, (long long)msc);
 	}
 
+	if (++serial == 0)
+		serial = 1;
+
 	return msc;
 }
 
@@ -191,8 +200,7 @@ static int test_whole(Display *dpy)
 	xshmfence_reset(fence.addr);
 
 	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	xcb_present_pixmap(c, root, pixmap,
-			   0, /* sbc */
+	xcb_present_pixmap(c, root, pixmap, 0,
 			   0, /* valid */
 			   0, /* update */
 			   0, /* x_off */
@@ -208,8 +216,7 @@ static int test_whole(Display *dpy)
 	XFreePixmap(dpy, pixmap);
 
 	pixmap = XCreatePixmap(dpy, root, width, height, depth);
-	xcb_present_pixmap(c, root, pixmap,
-			   0, /* sbc */
+	xcb_present_pixmap(c, root, pixmap, 0,
 			   0, /* valid */
 			   0, /* update */
 			   0, /* x_off */
@@ -244,8 +251,9 @@ static int test_future(Display *dpy, void *Q)
 	xcb_xfixes_region_t region;
 	unsigned int width, height;
 	unsigned border, depth;
-	int x, y, ret = 1, n;
+	int x, y, ret = 0, n;
 	uint64_t target, final;
+	int complete;
 
 	XGetGeometry(dpy, DefaultRootWindow(dpy),
 		     &root, &x, &y, &width, &height, &border, &depth);
@@ -263,8 +271,7 @@ static int test_future(Display *dpy, void *Q)
 	pixmap = XCreatePixmap(dpy, root, width, height, depth);
 	xshmfence_reset(fence.addr);
 	for (n = N_VBLANKS; n--; )
-		xcb_present_pixmap(c, root, pixmap,
-				   n, /* sbc */
+		xcb_present_pixmap(c, root, pixmap, 0,
 				   0, /* valid */
 				   region, /* update */
 				   0, /* x_off */
@@ -277,8 +284,7 @@ static int test_future(Display *dpy, void *Q)
 				   1, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-	xcb_present_pixmap(c, root, pixmap,
-			   N_VBLANKS, /* sbc */
+	xcb_present_pixmap(c, root, pixmap, 0,
 			   region, /* valid */
 			   region, /* update */
 			   0, /* x_off */
@@ -294,7 +300,7 @@ static int test_future(Display *dpy, void *Q)
 	xcb_flush(c);
 
 	XSync(dpy, True);
-	ret = !!xshmfence_await(fence.addr);
+	ret += !!xshmfence_await(fence.addr);
 
 	final = check_msc(dpy, root, Q, 0);
 	if (final < target) {
@@ -308,8 +314,7 @@ static int test_future(Display *dpy, void *Q)
 	}
 
 	xshmfence_reset(fence.addr);
-	xcb_present_pixmap(c, root, pixmap,
-			   N_VBLANKS, /* sbc */
+	xcb_present_pixmap(c, root, pixmap, 0,
 			   region, /* valid */
 			   region, /* update */
 			   0, /* x_off */
@@ -323,7 +328,7 @@ static int test_future(Display *dpy, void *Q)
 			   0, /* remainder */
 			   0, NULL);
 	xcb_flush(c);
-	ret = !!xshmfence_await(fence.addr);
+	ret += !!xshmfence_await(fence.addr);
 
 	final = check_msc(dpy, root, Q, 0);
 	if (final < target + N_VBLANKS) {
@@ -336,6 +341,37 @@ static int test_future(Display *dpy, void *Q)
 		ret++;
 	}
 
+	xcb_present_pixmap(c, root, pixmap, 0xdeadbeef,
+			   0, /* valid */
+			   0, /* update */
+			   0, /* x_off */
+			   0, /* y_off */
+			   None,
+			   None, /* wait fence */
+			   0,
+			   XCB_PRESENT_OPTION_NONE,
+			   final + N_VBLANKS + 1, /* target msc */
+			   0, /* divisor */
+			   0, /* remainder */
+			   0, NULL);
+	xcb_flush(c);
+	complete = 0;
+	do {
+		xcb_present_complete_notify_event_t *ce;
+		xcb_generic_event_t *ev;
+
+		ev = xcb_wait_for_special_event(c, Q);
+		if (ev == NULL)
+			break;
+
+		ce = (xcb_present_complete_notify_event_t *)ev;
+		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
+			break;
+
+		complete = ce->serial == 0xdeadbeef;
+		free(ev);
+	} while (!complete);
+
 	XFreePixmap(dpy, pixmap);
 	xcb_xfixes_destroy_region(c, region);
 	dri3_fence_free(dpy, &fence);
@@ -344,6 +380,121 @@ static int test_future(Display *dpy, void *Q)
 	ret += !!_x_error_occurred;
 
 	return ret;
+#undef N_VBLANKS
+}
+
+static int test_accuracy(Display *dpy, void *Q)
+{
+#define N_VBLANKS (60 * 120) /* ~2 minutes */
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	Pixmap pixmap;
+	Window root;
+	unsigned int width, height;
+	unsigned border, depth;
+	int x, y, ret = 0, n;
+	uint64_t target;
+	int early = 0, late = 0;
+	int complete;
+
+	XGetGeometry(dpy, DefaultRootWindow(dpy),
+		     &root, &x, &y, &width, &height, &border, &depth);
+
+	printf("Testing whole screen flip acccuracy: %dx%d\n", width, height);
+	_x_error_occurred = 0;
+
+	target = check_msc(dpy, root, Q, 0);
+	pixmap = XCreatePixmap(dpy, root, width, height, depth);
+	xcb_present_pixmap(c, root, pixmap,
+			   0xdeadbeef, /* serial */
+			   0, /* valid */
+			   0, /* update */
+			   0, /* x_off */
+			   0, /* y_off */
+			   None,
+			   None, /* wait fence */
+			   None,
+			   XCB_PRESENT_OPTION_NONE,
+			   target + 60, /* target msc */
+			   0, /* divisor */
+			   0, /* remainder */
+			   0, NULL);
+	xcb_flush(c);
+	complete = 0;
+	do {
+		xcb_present_complete_notify_event_t *ce;
+		xcb_generic_event_t *ev;
+
+		ev = xcb_wait_for_special_event(c, Q);
+		if (ev == NULL)
+			break;
+
+		ce = (xcb_present_complete_notify_event_t *)ev;
+		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
+			break;
+
+		complete = ce->serial == 0xdeadbeef;
+		free(ev);
+	} while (!complete);
+	XSync(dpy, True);
+
+	target = check_msc(dpy, root, Q, 0);
+	for (n = 0; n <= N_VBLANKS; n++)
+		xcb_present_pixmap(c, root, pixmap,
+				   target + 60 + n, /* serial */
+				   0, /* valid */
+				   0, /* update */
+				   0, /* x_off */
+				   0, /* y_off */
+				   None,
+				   None, /* wait fence */
+				   None,
+				   XCB_PRESENT_OPTION_NONE,
+				   target + 60 + n, /* target msc */
+				   0, /* divisor */
+				   0, /* remainder */
+				   0, NULL);
+	xcb_flush(c);
+
+	complete = 0;
+	do {
+		xcb_present_complete_notify_event_t *ce;
+		xcb_generic_event_t *ev;
+		int64_t msc;
+
+		ev = xcb_wait_for_special_event(c, Q);
+		if (ev == NULL)
+			break;
+
+		ce = (xcb_present_complete_notify_event_t *)ev;
+		if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
+			break;
+
+		assert(ce->serial);
+
+		msc = ce->msc - ce->serial;
+		if (msc < 0) {
+			fprintf(stderr, "frame %d displayed early by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
+			ret += -msc;
+			early++;
+		} else if (msc > 1) { /* allow the frame to slip by a vblank */
+			ret += msc;
+			late++;
+		}
+		complete = ce->serial == target + 60 + N_VBLANKS;
+		free(ev);
+	} while (!complete);
+
+	if (early)
+		printf("%d frames shown too early! ", early);
+	if (late)
+		printf("%d fames shown too late!", late);
+	if (early|late)
+		printf("\n");
+
+	ret += !!_x_error_occurred;
+
+	return ret;
+#undef N_VBLANKS
 }
 
 static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
@@ -447,6 +598,7 @@ struct test_crtc {
 	uint64_t msc;
 };
 #define SYNC 0x1
+#define FUTURE 0x2
 
 static int __test_crtc(Display *dpy, RRCrtc crtc,
 		       int width, int height,
@@ -473,16 +625,14 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
 			   None, /* wait fence */
 			   test->flags & SYNC ? test->fence.xid : None,
 			   XCB_PRESENT_OPTION_NONE,
-			   0, /* target msc */
+			   test->msc, /* target msc */
 			   1, /* divisor */
 			   0, /* remainder */
 			   0, NULL);
-	XFreePixmap(dpy, pixmap);
-
 	if (test->flags & SYNC) {
-		pixmap = XCreatePixmap(dpy, test->win, width, height, test->depth);
+		Pixmap tmp = XCreatePixmap(dpy, test->win, width, height, test->depth);
 		xcb_present_pixmap(XGetXCBConnection(dpy),
-				   test->win, pixmap,
+				   test->win, tmp,
 				   1, /* sbc */
 				   0, /* valid */
 				   0, /* update */
@@ -492,14 +642,15 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
 				   None, /* wait fence */
 				   None, /* sync fence */
 				   XCB_PRESENT_OPTION_NONE,
-				   1, /* target msc */
+				   test->msc + (test->flags & FUTURE ? 5 * 16 : 1), /* target msc */
 				   1, /* divisor */
 				   0, /* remainder */
 				   0, NULL);
-		XFreePixmap(dpy, pixmap);
+		XFreePixmap(dpy, tmp);
 		XFlush(dpy);
 		err += !!xshmfence_await(test->fence.addr);
 	}
+	XFreePixmap(dpy, pixmap);
 
 	test->msc = check_msc(dpy, test->win, test->queue, test->msc);
 	return err;
@@ -532,6 +683,12 @@ static int test_crtc(Display *dpy, void *queue, uint64_t last_msc)
 	err += for_each_crtc(dpy, __test_crtc, &test);
 	test.msc = check_msc(dpy, test.win, test.queue, test.msc);
 
+	printf("Testing each crtc, with future flips\n");
+	test.flags = FUTURE | SYNC;
+	test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+	err += for_each_crtc(dpy, __test_crtc, &test);
+	test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+
 	dri3_fence_free(dpy, &test.fence);
 	XSync(dpy, True);
 	err += !!_x_error_occurred;
@@ -794,8 +951,22 @@ static int has_present(Display *dpy)
 					       &error);
 	free(reply);
 	free(error);
-	if (reply == NULL)
+	if (reply == NULL) {
+		fprintf(stderr, "XFixes not supported on %s\n", DisplayString(dpy));
+		return 0;
+	}
+
+	reply = xcb_dri3_query_version_reply(c,
+					     xcb_dri3_query_version(c,
+								    XCB_DRI3_MAJOR_VERSION,
+								    XCB_DRI3_MINOR_VERSION),
+					     &error);
+	free(reply);
+	free(error);
+	if (reply == NULL) {
+		fprintf(stderr, "DRI3 not supported on %s\n", DisplayString(dpy));
 		return 0;
+	}
 
 	reply = xcb_present_query_version_reply(c,
 						xcb_present_query_version(c,
@@ -805,8 +976,10 @@ static int has_present(Display *dpy)
 
 	free(reply);
 	free(error);
-	if (reply == NULL)
+	if (reply == NULL) {
+		fprintf(stderr, "Present not supported on %s\n", DisplayString(dpy));
 		return 0;
+	}
 
 	return 1;
 }
@@ -840,6 +1013,9 @@ int main(void)
 	error += test_future(dpy, queue);
 	last_msc = check_msc(dpy, root, queue, last_msc);
 
+	error += test_accuracy(dpy, queue);
+	last_msc = check_msc(dpy, root, queue, last_msc);
+
 	error += test_crtc(dpy, queue, last_msc);
 	last_msc = check_msc(dpy, root, queue, last_msc);
 


More information about the xorg-commit mailing list