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