diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-02-15 19:20:35 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-02-15 19:21:01 +0000 |
commit | 3382bd78d9e9885a7714ebbfd777a03ee8708a01 (patch) | |
tree | 9c67d5196907de49d12d2cff7b7fc497e40f99d3 /test | |
parent | 5fc2628e803998c9b5b8c9bdd88dc34a46b31e2e (diff) |
test/present: Test notifier accuracy
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'test')
-rw-r--r-- | test/present-test.c | 309 |
1 files changed, 305 insertions, 4 deletions
diff --git a/test/present-test.c b/test/present-test.c index 651df4aa..029e4eb9 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); |