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

Chris Wilson ickle at kemper.freedesktop.org
Sun Feb 15 11:21:23 PST 2015


 src/sna/sna_display.c |   26 +---
 test/present-test.c   |  309 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 315 insertions(+), 20 deletions(-)

New commits:
commit 3382bd78d9e9885a7714ebbfd777a03ee8708a01
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 15 19:20:35 2015 +0000

    test/present: Test notifier accuracy
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/test/present-test.c b/test/present-test.c
index 651df4a..029e4eb 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -496,7 +496,7 @@ static int test_future(Display *dpy, void *Q)
 			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
 			if (diff < 0) {
 				if (-diff > earliest) {
-					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, diff);
+					fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
 					earliest = -diff;
 				}
 				early++;
@@ -714,8 +714,8 @@ static int test_accuracy(Display *dpy, void *Q)
 					fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
 					latest = diff;
 				}
-				ret++;
 				late++;
+				ret++;
 			}
 		} else
 			complete = 1;
@@ -824,19 +824,19 @@ static int test_modulus(Display *dpy, void *Q)
 
 			diff = (int64_t)(ce->msc - msc);
 			if (diff < 0) {
-				ret += -diff;
 				if (-diff > earliest) {
 					fprintf(stderr, "\tframe (%d, %d) displayed early by %d frames\n", y, x, -diff);
 					earliest = -diff;
 				}
 				early++;
+				ret++;
 			} else if (diff > 0) {
-				ret += diff;
 				if (diff > latest) {
 					fprintf(stderr, "\tframe (%d, %d) displayed late by %d frames\n", y, x, diff);
 					latest = diff;
 				}
 				late++;
+				ret++;
 			}
 		} else
 			complete = 1;
@@ -857,6 +857,295 @@ static int test_modulus(Display *dpy, void *Q)
 	return ret;
 }
 
+static int test_future_msc(Display *dpy, void *Q)
+{
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	Window root = DefaultRootWindow(dpy);
+	int ret = 0, n;
+	uint64_t msc, ust;
+	int complete;
+	int early = 0, late = 0;
+	int earliest = 0, latest = 0;
+	uint64_t interval;
+
+	printf("Testing notifies into the future\n");
+	_x_error_occurred = 0;
+
+	interval = msc_interval(dpy, root, Q);
+	msc = check_msc(dpy, root, Q, 0, &ust);
+
+	for (n = 1; n <= 10; n++)
+		xcb_present_notify_msc(c, root, n, msc + 60 + n*15*60, 0, 0);
+	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n*15*60, 0, 0);
+	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;
+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
+
+		if (ce->serial == 0xdeadbeef) {
+			int64_t time;
+
+			time = ce->ust - (ust + (60 + 15*60*n) * interval);
+			if (time < -(int64_t)interval) {
+				fprintf(stderr,
+					"\tnotifies completed too early by %lldms\n",
+					(long long)(-time / 1000));
+			} else if (time > (int64_t)interval) {
+				fprintf(stderr,
+					"\tnotifies completed too late by %lldms\n",
+					(long long)(time / 1000));
+			}
+			complete = 1;
+		} else {
+			int diff = (int64_t)(ce->msc - (15*60*ce->serial + msc + 60));
+			if (diff < 0) {
+				if (-diff > earliest) {
+					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
+					earliest = -diff;
+				}
+				early++;
+				ret++;
+			} else if (diff > 0) {
+				if (diff > latest) {
+					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
+					latest = diff;
+				}
+				late++;
+				ret++;
+			}
+		}
+		free(ev);
+	} while (!complete);
+
+	if (early)
+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
+	if (late)
+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
+
+	XSync(dpy, True);
+	ret += !!_x_error_occurred;
+
+	return ret;
+}
+
+static int test_exhaustion_msc(Display *dpy, void *Q)
+{
+#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	Window root = DefaultRootWindow(dpy);
+	int ret = 0, n, complete;
+	int earliest = 0, early = 0;
+	int latest = 0, late = 0;
+	uint64_t msc;
+
+	printf("Testing notifies with long queues\n");
+	_x_error_occurred = 0;
+
+	msc = check_msc(dpy, root, Q, 0, NULL);
+	for (n = N_VBLANKS; n--; )
+		xcb_present_notify_msc(c, root, N_VBLANKS, msc + N_VBLANKS, 1, 0);
+	xcb_present_notify_msc(c, root, 1, msc, 1, 0);
+	xcb_flush(c);
+
+	complete = N_VBLANKS + 1;
+	do {
+		xcb_present_complete_notify_event_t *ce;
+		xcb_generic_event_t *ev;
+		int diff;
+
+		ev = xcb_wait_for_special_event(c, Q);
+		if (ev == NULL)
+			break;
+
+		ce = (xcb_present_complete_notify_event_t *)ev;
+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
+
+		diff = (int64_t)(ce->msc - msc - ce->serial);
+		if (diff < 0) {
+			if (-diff > earliest) {
+				fprintf(stderr, "\tnotify %d early by %d msc\n",(int)ce->serial, -diff);
+				earliest = -diff;
+			}
+			early++;
+			ret++;
+		} else if (diff > 0) {
+			if (diff > latest) {
+				fprintf(stderr, "\tnotify %d late by %d msc\n", (int)ce->serial, diff);
+				latest = diff;
+			}
+			late++;
+			ret++;
+		}
+		free(ev);
+	} while (--complete);
+
+	if (early)
+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
+	if (late)
+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
+
+	XSync(dpy, True);
+	ret += !!_x_error_occurred;
+
+	return ret;
+#undef N_VBLANKS
+}
+
+static int test_accuracy_msc(Display *dpy, void *Q)
+{
+#define N_VBLANKS (60 * 120) /* ~2 minutes */
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	Window root = DefaultRootWindow(dpy);
+	int ret = 0, n;
+	uint64_t msc;
+	int early = 0, late = 0;
+	int earliest = 0, latest = 0;
+	int complete;
+
+	printf("Testing notify accuracy\n");
+	_x_error_occurred = 0;
+
+	msc = check_msc(dpy, root, Q, 0, NULL);
+	for (n = 0; n <= N_VBLANKS; n++)
+		xcb_present_notify_msc(c, root, n, msc + 60 + n, 0, 0);
+	xcb_present_notify_msc(c, root, 0xdeadbeef, msc + 60 + n, 0, 0);
+	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;
+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
+
+		if (ce->serial != 0xdeadbeef) {
+			int diff = (int64_t)(ce->msc - (msc + ce->serial + 60));
+			if (diff < 0) {
+				if (-diff > earliest) {
+					fprintf(stderr, "\tnotify %d early by %d msc\n", ce->serial, -diff);
+					earliest = -diff;
+				}
+				early++;
+				ret++;
+			} else if (diff > 0) {
+				if (diff > latest) {
+					fprintf(stderr, "\tnotify %d late by %d msc\n", ce->serial, diff);
+					latest = diff;
+				}
+				late++;
+				ret++;
+			}
+		} else
+			complete = 1;
+		free(ev);
+	} while (!complete);
+
+	if (early)
+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
+	if (late)
+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
+
+	XSync(dpy, True);
+	ret += !!_x_error_occurred;
+
+	return ret;
+#undef N_VBLANKS
+}
+
+static int test_modulus_msc(Display *dpy, void *Q)
+{
+	xcb_connection_t *c = XGetXCBConnection(dpy);
+	Window root = DefaultRootWindow(dpy);
+	int x, y, ret = 0;
+	uint64_t target;
+	int early = 0, late = 0;
+	int earliest = 0, latest = 0;
+	int complete;
+
+	printf("Testing notify modulus\n");
+	_x_error_occurred = 0;
+
+	target = check_msc(dpy, root, Q, 0, NULL);
+	for (x = 1; x <= 7; x++) {
+		for (y = 0; y < x; y++) {
+			xcb_present_notify_msc(c, root, y << 16 | x, 0, x, y);
+		}
+	}
+	xcb_present_notify_msc(c, root, 0xdeadbeef, target + 2*x, 0, 0);
+	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;
+		assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
+
+		assert(ce->serial);
+		if (ce->serial != 0xdeadbeef) {
+			uint64_t msc;
+			int diff;
+
+			x = ce->serial & 0xffff;
+			y = ce->serial >> 16;
+
+			msc = target;
+			msc -= target % x;
+			msc += y;
+			if (msc <= target)
+				msc += x;
+
+			diff = (int64_t)(ce->msc - msc);
+			if (diff < 0) {
+				if (-diff > earliest) {
+					fprintf(stderr, "\tnotify (%d, %d) early by %d msc\n", y, x, -diff);
+					earliest = -diff;
+				}
+				early++;
+				ret++;
+			} else if (diff > 0) {
+				if (diff > latest) {
+					fprintf(stderr, "\tnotify (%d, %d) late by %d msc\n", y, x, diff);
+					latest = diff;
+				}
+				late++;
+				ret++;
+			}
+		} else
+			complete = 1;
+		free(ev);
+	} while (!complete);
+
+	if (early)
+		printf("\t%d notifies too early (worst %d)!\n", early, earliest);
+	if (late)
+		printf("\t%d notifies too late (worst %d)!\n", late, latest);
+
+	XSync(dpy, True);
+	ret += !!_x_error_occurred;
+
+	return ret;
+}
+
 static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
 {
 	XRRScreenResources *res;
@@ -1369,6 +1658,18 @@ int main(void)
 	queue = setup_msc(dpy, root);
 	last_msc = check_msc(dpy, root, queue, 0, NULL);
 
+	error += test_future_msc(dpy, queue);
+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+
+	error += test_accuracy_msc(dpy, queue);
+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+
+	error += test_modulus_msc(dpy, queue);
+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+
+	error += test_exhaustion_msc(dpy, queue);
+	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+
 	error += test_whole(dpy);
 	last_msc = check_msc(dpy, root, queue, last_msc, NULL);
 
commit 5fc2628e803998c9b5b8c9bdd88dc34a46b31e2e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Feb 15 14:43:27 2015 +0000

    sna: Use shadow_enabled to prevent TearFree recursion
    
    At times, we want to clear pending flips from inside TearFree, and thus
    need to disable recursion. Currently we dance with shadow_damage, but
    now we can just migrate over to using the shadow_enabled flag.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index cbfa921..ecbdf4b 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1110,7 +1110,6 @@ static bool wait_for_shadow(struct sna *sna,
 			    unsigned flags)
 {
 	PixmapPtr pixmap = priv->pixmap;
-	DamagePtr damage;
 	struct kgem_bo *bo, *tmp;
 	int flip_active;
 	bool ret = true;
@@ -1165,9 +1164,7 @@ static bool wait_for_shadow(struct sna *sna,
 	}
 
 	assert(sna->mode.shadow_active);
-
-	damage = sna->mode.shadow_damage;
-	sna->mode.shadow_damage = NULL;
+	sna->mode.shadow_enabled = false;
 
 	flip_active = sna->mode.flip_active;
 	if (flip_active) {
@@ -1219,6 +1216,7 @@ static bool wait_for_shadow(struct sna *sna,
 			bo = sna->mode.shadow;
 		}
 	}
+	sna->mode.shadow_enabled = true;
 
 	if (bo->refcnt > 1) {
 		bo = kgem_create_2d(&sna->kgem,
@@ -1241,8 +1239,6 @@ static bool wait_for_shadow(struct sna *sna,
 			bo = sna->mode.shadow;
 	}
 
-	sna->mode.shadow_damage = damage;
-
 	RegionSubtract(&sna->mode.shadow_region,
 		       &sna->mode.shadow_region,
 		       &sna->mode.shadow_cancel);
@@ -1391,6 +1387,7 @@ static bool sna_mode_enable_shadow(struct sna *sna)
 	assert(sna->mode.shadow == NULL);
 	assert(sna->mode.shadow_damage == NULL);
 	assert(sna->mode.shadow_active == 0);
+	assert(!sna->mode.shadow_enabled);
 
 	sna->mode.shadow_damage = DamageCreate(sna_mode_damage, NULL,
 					       DamageReportRawRegion,
@@ -7237,9 +7234,11 @@ void sna_mode_redisplay(struct sna *sna)
 		return;
 	}
 
-	if (!sna->mode.shadow_enabled || !sna->mode.shadow_damage)
+	if (!sna->mode.shadow_enabled)
 		return;
 
+	assert(sna->mode.shadow_damage);
+
 	DBG(("%s: posting shadow damage? %d (flips pending? %d, mode reconfiguration pending? %d)\n",
 	     __FUNCTION__,
 	     !RegionNil(DamageRegion(sna->mode.shadow_damage)),
@@ -7261,20 +7260,15 @@ void sna_mode_redisplay(struct sna *sna)
 	     region->extents.x2, region->extents.y2));
 
 	if (sna->mode.flip_active) {
-		DamagePtr damage;
-
-		damage = sna->mode.shadow_damage;
-		sna->mode.shadow_damage = NULL;
-
+		sna->mode.shadow_enabled = false;
 		while (sna->mode.flip_active && sna_mode_wakeup(sna))
 			;
+		sna->mode.shadow_enabled = true;
 
-		sna->mode.shadow_damage = damage;
+		if (sna->mode.flip_active)
+			return;
 	}
 
-	if (sna->mode.flip_active)
-		return;
-
 	if (wedged(sna) || !move_crtc_to_gpu(sna)) {
 		DBG(("%s: forcing scanout update using the CPU\n", __FUNCTION__));
 		if (!sna_pixmap_move_to_cpu(sna->front, MOVE_READ))


More information about the xorg-commit mailing list