xf86-video-intel: 7 commits - src/sna/sna_present.c test/present-test.c
Chris Wilson
ickle at kemper.freedesktop.org
Thu Feb 12 13:04:42 PST 2015
src/sna/sna_present.c | 75 +++---
test/present-test.c | 555 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 502 insertions(+), 128 deletions(-)
New commits:
commit 9eb0ab15b1ab09cd6a4e8666b6f488fad1dc36b4
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 17:05:52 2015 +0000
test/present: Look for MSC wraparound
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/present-test.c b/test/present-test.c
index aefed73..ec8db6b 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -165,7 +165,7 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc,
free(ev);
} while (!complete);
- if (msc < last_msc) {
+ if ((int64_t)(msc - last_msc) < 0) {
printf("Invalid MSC: was %llu, now %llu\n",
(long long)last_msc, (long long)msc);
}
commit 254f2f2f4b0a4deccec847e46086881c5a2681b1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 17:03:46 2015 +0000
test/present: Check a simple double-buffer sequence
Just check that we can do a present roundtrip in time to submit a new
frame on the next vblank.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/present-test.c b/test/present-test.c
index 35ae8d3..aefed73 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -324,6 +324,87 @@ static uint64_t flush_flips(Display *dpy, Window win, Pixmap pixmap, void *Q, ui
return check_msc(dpy, win, Q, msc, ust);
}
+static int test_double(Display *dpy, void *Q)
+{
+#define COUNT (15*60)
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ Pixmap pixmap;
+ Window root;
+ unsigned int width, height;
+ unsigned border, depth;
+ int x, y, n, ret;
+ struct {
+ uint64_t msc, ust;
+ } frame[COUNT+1];
+ int offset = 0;
+
+ XGetGeometry(dpy, DefaultRootWindow(dpy),
+ &root, &x, &y, &width, &height, &border, &depth);
+
+ printf("Testing whole screen flip double buffering: %dx%d\n", width, height);
+ _x_error_occurred = 0;
+
+ pixmap = XCreatePixmap(dpy, root, width, height, depth);
+ flush_flips(dpy, root, pixmap, Q, NULL);
+ for (n = 0; n <= COUNT; n++) {
+ int complete;
+
+ xcb_present_pixmap(c, root, pixmap, n,
+ 0, /* valid */
+ 0, /* update */
+ 0, /* x_off */
+ 0, /* y_off */
+ None,
+ None, /* wait fence */
+ None,
+ XCB_PRESENT_OPTION_NONE,
+ 0, /* 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 &&
+ ce->serial == n) {
+ frame[n].msc = ce->msc;
+ frame[n].ust = ce->ust;
+ complete = 1;
+ }
+ free(ev);
+ } while (!complete);
+ }
+ XFreePixmap(dpy, pixmap);
+
+ XSync(dpy, True);
+ ret = !!_x_error_occurred;
+
+ if (frame[COUNT].msc - frame[0].msc != COUNT) {
+ printf("Expected %d frames interval, %d elapsed instead\n",
+ COUNT, (int)(frame[COUNT].msc - frame[0].msc));
+ for (n = 0; n <= COUNT; n++) {
+ if (frame[n].msc - frame[0].msc != n + offset) {
+ printf("frame[%d]: msc=%03lld, ust=%lld\n", n,
+ (long long)(frame[n].msc - frame[0].msc),
+ (long long)(frame[n].ust - frame[0].ust));
+ offset = frame[n].msc - frame[0].msc - n;
+ ret++;
+ }
+ }
+ }
+
+ return ret;
+}
+
static int test_future(Display *dpy, void *Q)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
@@ -1285,6 +1366,9 @@ int main(void)
error += test_whole(dpy);
last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+ error += test_double(dpy, queue);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
+
error += test_future(dpy, queue);
last_msc = check_msc(dpy, root, queue, last_msc, NULL);
commit 92f74186b0b329e7ede53153a6b5f953c5cad2a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 14:24:38 2015 +0000
test/present: Include test for timing 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 c8f340b..35ae8d3 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -136,7 +136,7 @@ static void *setup_msc(Display *dpy, Window win)
return q;
}
-static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
+static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc, uint64_t *ust)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
static uint32_t serial = 1;
@@ -158,6 +158,8 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
ce->serial == serial) {
msc = ce->msc;
+ if (ust)
+ *ust = ce->ust;
complete = 1;
}
free(ev);
@@ -174,6 +176,46 @@ static uint64_t check_msc(Display *dpy, Window win, void *q, uint64_t last_msc)
return msc;
}
+static uint64_t msc_interval(Display *dpy, Window win, void *q)
+{
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ uint64_t msc, ust;
+ int complete = 0;
+
+ msc = check_msc(dpy, win, q, 0, NULL);
+
+ xcb_present_notify_msc(c, win, 0xc0ffee00, msc, 0, 0);
+ xcb_present_notify_msc(c, win, 0xc0ffee01, msc + 10, 0, 0);
+ xcb_flush(c);
+
+ ust = msc = 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_NOTIFY_MSC &&
+ ce->serial == 0xc0ffee00) {
+ msc -= ce->msc;
+ ust -= ce->ust;
+ complete++;
+ }
+ if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC &&
+ ce->serial == 0xc0ffee01) {
+ msc += ce->msc;
+ ust += ce->ust;
+ complete++;
+ }
+ free(ev);
+ } while (complete != 2);
+
+ return (ust + msc/2) / msc;
+}
+
static void teardown_msc(Display *dpy, void *q)
{
xcb_unregister_for_special_event(XGetXCBConnection(dpy), q);
@@ -241,32 +283,14 @@ static int test_whole(Display *dpy)
return ret;
}
-static int test_future(Display *dpy, void *Q)
+static uint64_t flush_flips(Display *dpy, Window win, Pixmap pixmap, void *Q, uint64_t *ust)
{
xcb_connection_t *c = XGetXCBConnection(dpy);
- Pixmap pixmap;
- struct dri3_fence fence;
- Window root;
- unsigned int width, height;
- unsigned border, depth;
- int x, y, ret = 0, n;
- uint64_t target;
+ uint64_t msc;
int complete;
- int early = 0, late = 0;
- int earliest = 0, latest = 0;
-
- XGetGeometry(dpy, DefaultRootWindow(dpy),
- &root, &x, &y, &width, &height, &border, &depth);
-
- if (dri3_create_fence(dpy, root, &fence))
- return 0;
-
- printf("Testing whole screen flips into the future: %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,
+ msc = check_msc(dpy, win, Q, 0, NULL);
+ xcb_present_pixmap(c, win, pixmap,
0xdeadbeef, /* serial */
0, /* valid */
0, /* update */
@@ -276,7 +300,7 @@ static int test_future(Display *dpy, void *Q)
None, /* wait fence */
None,
XCB_PRESENT_OPTION_NONE,
- target + 60, /* target msc */
+ msc + 60, /* target msc */
0, /* divisor */
0, /* remainder */
0, NULL);
@@ -291,18 +315,46 @@ static int test_future(Display *dpy, void *Q)
break;
ce = (xcb_present_complete_notify_event_t *)ev;
- if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
- break;
-
- complete = ce->serial == 0xdeadbeef;
+ complete = (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP &&
+ ce->serial == 0xdeadbeef);
free(ev);
} while (!complete);
XSync(dpy, True);
- target = check_msc(dpy, root, Q, 0);
- for (n = 0; n <= 10; n++)
+ return check_msc(dpy, win, Q, msc, ust);
+}
+
+static int test_future(Display *dpy, void *Q)
+{
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ Pixmap pixmap;
+ struct dri3_fence fence;
+ Window root;
+ unsigned int width, height;
+ unsigned border, depth;
+ int x, y, ret = 0, n;
+ uint64_t msc, ust;
+ int complete;
+ int early = 0, late = 0;
+ int earliest = 0, latest = 0;
+ uint64_t interval;
+
+ XGetGeometry(dpy, DefaultRootWindow(dpy),
+ &root, &x, &y, &width, &height, &border, &depth);
+
+ if (dri3_create_fence(dpy, root, &fence))
+ return 0;
+
+ printf("Testing whole screen flips into the future: %dx%d\n", width, height);
+ _x_error_occurred = 0;
+
+ interval = msc_interval(dpy, root, Q);
+
+ pixmap = XCreatePixmap(dpy, root, width, height, depth);
+ msc = flush_flips(dpy, root, pixmap, Q, &ust);
+ for (n = 1; n <= 10; n++)
xcb_present_pixmap(c, root, pixmap,
- target + 60 + n*15*60, /* serial */
+ n, /* serial */
0, /* valid */
0, /* update */
0, /* x_off */
@@ -311,7 +363,7 @@ static int test_future(Display *dpy, void *Q)
None, /* wait fence */
None,
XCB_PRESENT_OPTION_NONE,
- target + 60 + n*15*60, /* target msc */
+ msc + 60 + n*15*60, /* target msc */
0, /* divisor */
0, /* remainder */
0, NULL);
@@ -325,7 +377,7 @@ static int test_future(Display *dpy, void *Q)
None, /* wait fence */
None,
XCB_PRESENT_OPTION_NONE,
- target + 60 + n*15*60, /* target msc */
+ msc + 60 + n*15*60, /* target msc */
0, /* divisor */
0, /* remainder */
0, NULL);
@@ -341,29 +393,38 @@ static int test_future(Display *dpy, void *Q)
break;
ce = (xcb_present_complete_notify_event_t *)ev;
- if (ce->kind != XCB_PRESENT_COMPLETE_KIND_PIXMAP)
- break;
-
- assert(ce->serial);
+ assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
if (ce->serial == 0xdeadbeef) {
+ int64_t time;
+
+ time = ce->ust - (ust + (60 + 15*60*n) * interval);
+ if (time < -(int64_t)interval) {
+ fprintf(stderr,
+ "\tflips completed too early by %lldms\n",
+ (long long)(-time / 1000));
+ } else if (time > (int64_t)interval) {
+ fprintf(stderr,
+ "\tflips completed too late by %lldms\n",
+ (long long)(time / 1000));
+ }
complete = 1;
} else {
- int msc = (uint32_t)ce->msc - ce->serial;
- if (msc < 0) {
- ret += -msc;
- if (-msc > earliest) {
- fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60)/(15*60), (long long)msc);
- earliest = -msc;
+ 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);
+ earliest = -diff;
}
early++;
- } else if (msc > 0) {
- ret += msc;
- if (msc > latest) {
- fprintf(stderr, "\tframe %d displayed late by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
- latest = msc;
+ ret++;
+ } else if (diff > 0) {
+ if (diff > latest) {
+ fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
+ latest = diff;
}
late++;
+ ret++;
}
}
free(ev);
@@ -391,7 +452,6 @@ static int test_exhaustion(Display *dpy, void *Q)
unsigned border, depth;
int x, y, ret = 0, n;
uint64_t target, final;
- int complete;
XGetGeometry(dpy, DefaultRootWindow(dpy),
&root, &x, &y, &width, &height, &border, &depth);
@@ -405,7 +465,7 @@ static int test_exhaustion(Display *dpy, void *Q)
region = xcb_generate_id(c);
xcb_xfixes_create_region(c, region, 0, NULL);
- target = check_msc(dpy, root, Q, 0);
+ target = check_msc(dpy, root, Q, 0, NULL);
pixmap = XCreatePixmap(dpy, root, width, height, depth);
xshmfence_reset(fence.addr);
for (n = N_VBLANKS; n--; )
@@ -440,7 +500,7 @@ static int test_exhaustion(Display *dpy, void *Q)
XSync(dpy, True);
ret += !!xshmfence_await(fence.addr);
- final = check_msc(dpy, root, Q, 0);
+ final = check_msc(dpy, root, Q, 0, NULL);
if (final < target) {
printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
(long long)final, (long long)target);
@@ -468,7 +528,7 @@ static int test_exhaustion(Display *dpy, void *Q)
xcb_flush(c);
ret += !!xshmfence_await(fence.addr);
- final = check_msc(dpy, root, Q, 0);
+ final = check_msc(dpy, root, Q, 0, NULL);
if (final < target + N_VBLANKS) {
printf("\tLast flip too early, MSC was %llu, expected %llu\n",
(long long)final, (long long)(target + N_VBLANKS));
@@ -479,36 +539,7 @@ static int test_exhaustion(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);
+ flush_flips(dpy, root, pixmap, Q, NULL);
XFreePixmap(dpy, pixmap);
xcb_xfixes_destroy_region(c, region);
@@ -538,48 +569,14 @@ static int test_accuracy(Display *dpy, void *Q)
XGetGeometry(dpy, DefaultRootWindow(dpy),
&root, &x, &y, &width, &height, &border, &depth);
- printf("Testing whole screen flip acccuracy: %dx%d\n", width, height);
+ printf("Testing whole screen flip accuracy: %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, target);
+ target = flush_flips(dpy, root, pixmap, Q, NULL);
for (n = 0; n <= N_VBLANKS; n++)
xcb_present_pixmap(c, root, pixmap,
- target + 60 + n, /* serial */
+ n, /* serial */
0, /* valid */
0, /* update */
0, /* x_off */
@@ -592,41 +589,53 @@ static int test_accuracy(Display *dpy, void *Q)
0, /* divisor */
0, /* remainder */
0, NULL);
+ 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 + 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);
+ assert(ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP);
- msc = (uint32_t)ce->msc - ce->serial;
- if (msc < 0) {
- ret += -msc;
- if (-msc > earliest) {
- fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
- earliest = -msc;
- }
- early++;
- } else if (msc > 0) {
- ret += msc;
- if (msc > latest) {
- fprintf(stderr, "\tframe %d displayed late by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
- latest = msc;
+ if (ce->serial != 0xdeadbeef) {
+ int diff = (int64_t)(ce->msc - (target + ce->serial + 60));
+ if (diff < 0) {
+ if (-diff > earliest) {
+ fprintf(stderr, "\tframe %d displayed early by %d frames\n", ce->serial, -diff);
+ earliest = -diff;
+ }
+ early++;
+ ret++;
+ } else if (diff > 0) {
+ if (diff > latest) {
+ fprintf(stderr, "\tframe %d displayed late by %d frames\n", ce->serial, diff);
+ latest = diff;
+ }
+ ret++;
+ late++;
}
- late++;
- }
- complete = ce->serial == target + 60 + N_VBLANKS;
+ } else
+ complete = 1;
free(ev);
} while (!complete);
@@ -664,45 +673,11 @@ static int test_modulus(Display *dpy, void *Q)
printf("Testing whole screen flip modulus: %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);
-
region = xcb_generate_id(c);
xcb_xfixes_create_region(c, region, 0, NULL);
- target = check_msc(dpy, root, Q, target);
+ pixmap = XCreatePixmap(dpy, root, width, height, depth);
+ target = flush_flips(dpy, root, pixmap, Q, NULL);
for (x = 1; x <= 7; x++) {
for (y = 0; y < x; y++) {
xcb_present_pixmap(c, root, pixmap,
@@ -908,7 +883,7 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
Pixmap pixmap;
int err = 0;
- test->msc = check_msc(dpy, test->win, test->queue, test->msc);
+ test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
if (test->flags & SYNC)
xshmfence_reset(test->fence.addr);
@@ -952,7 +927,7 @@ static int __test_crtc(Display *dpy, RRCrtc crtc,
}
XFreePixmap(dpy, pixmap);
- test->msc = check_msc(dpy, test->win, test->queue, test->msc);
+ test->msc = check_msc(dpy, test->win, test->queue, test->msc, NULL);
return err;
}
@@ -973,21 +948,21 @@ static int test_crtc(Display *dpy, void *queue, uint64_t last_msc)
printf("Testing each crtc, without waiting for each flip\n");
test.flags = 0;
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
err += for_each_crtc(dpy, __test_crtc, &test);
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
printf("Testing each crtc, waiting for flips to complete\n");
test.flags = SYNC;
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
err += for_each_crtc(dpy, __test_crtc, &test);
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
printf("Testing each crtc, with future flips\n");
test.flags = FUTURE | SYNC;
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
err += for_each_crtc(dpy, __test_crtc, &test);
- test.msc = check_msc(dpy, test.win, test.queue, test.msc);
+ test.msc = check_msc(dpy, test.win, test.queue, test.msc, NULL);
dri3_fence_free(dpy, &test.fence);
XSync(dpy, True);
@@ -1305,31 +1280,31 @@ int main(void)
XSetErrorHandler(_check_error_handler);
queue = setup_msc(dpy, root);
- last_msc = check_msc(dpy, root, queue, 0);
+ last_msc = check_msc(dpy, root, queue, 0, NULL);
error += test_whole(dpy);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_future(dpy, queue);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_accuracy(dpy, queue);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_modulus(dpy, queue);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_exhaustion(dpy, queue);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_crtc(dpy, queue, last_msc);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_shm(dpy);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
error += test_dri3(dpy);
- last_msc = check_msc(dpy, root, queue, last_msc);
+ last_msc = check_msc(dpy, root, queue, last_msc, NULL);
teardown_msc(dpy, queue);
commit 9d4df75edb21b8fdef4b45cc8cda114ca55c54cb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 13:46:05 2015 +0000
test/present: Check modulus computation
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/present-test.c b/test/present-test.c
index 3c84359..c8f340b 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -576,7 +576,7 @@ static int test_accuracy(Display *dpy, void *Q)
} while (!complete);
XSync(dpy, True);
- target = check_msc(dpy, root, Q, 0);
+ target = check_msc(dpy, root, Q, target);
for (n = 0; n <= N_VBLANKS; n++)
xcb_present_pixmap(c, root, pixmap,
target + 60 + n, /* serial */
@@ -635,12 +635,170 @@ static int test_accuracy(Display *dpy, void *Q)
if (late)
printf("\t%d frames shown too late (worst %d)!\n", late, latest);
+ XFreePixmap(dpy, pixmap);
+
+ XSync(dpy, True);
ret += !!_x_error_occurred;
return ret;
#undef N_VBLANKS
}
+static int test_modulus(Display *dpy, void *Q)
+{
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ Pixmap pixmap;
+ Window root;
+ unsigned int width, height;
+ unsigned border, depth;
+ xcb_xfixes_region_t region;
+ int x, y, ret = 0;
+ uint64_t target;
+ int early = 0, late = 0;
+ int earliest = 0, latest = 0;
+ int complete;
+
+ XGetGeometry(dpy, DefaultRootWindow(dpy),
+ &root, &x, &y, &width, &height, &border, &depth);
+
+ printf("Testing whole screen flip modulus: %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);
+
+ region = xcb_generate_id(c);
+ xcb_xfixes_create_region(c, region, 0, NULL);
+
+ target = check_msc(dpy, root, Q, target);
+ for (x = 1; x <= 7; x++) {
+ for (y = 0; y < x; y++) {
+ xcb_present_pixmap(c, root, pixmap,
+ y << 16 | x, /* serial */
+ region, /* valid */
+ region, /* update */
+ 0, /* x_off */
+ 0, /* y_off */
+ None,
+ None, /* wait fence */
+ None,
+ XCB_PRESENT_OPTION_NONE,
+ 0, /* target msc */
+ x, /* divisor */
+ y, /* remainder */
+ 0, NULL);
+ }
+ }
+ 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 + 2*x, /* 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;
+
+ 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) {
+ ret += -diff;
+ if (-diff > earliest) {
+ fprintf(stderr, "\tframe (%d, %d) displayed early by %d frames\n", y, x, -diff);
+ earliest = -diff;
+ }
+ early++;
+ } 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++;
+ }
+ } else
+ complete = 1;
+ free(ev);
+ } while (!complete);
+
+ if (early)
+ printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
+ if (late)
+ printf("\t%d frames shown too late (worst %d)!\n", late, latest);
+
+ XFreePixmap(dpy, pixmap);
+ xcb_xfixes_destroy_region(c, region);
+
+ XSync(dpy, True);
+ ret += !!_x_error_occurred;
+
+ return ret;
+}
+
static inline XRRScreenResources *_XRRGetScreenResourcesCurrent(Display *dpy, Window window)
{
XRRScreenResources *res;
@@ -1158,6 +1316,9 @@ int main(void)
error += test_accuracy(dpy, queue);
last_msc = check_msc(dpy, root, queue, last_msc);
+ error += test_modulus(dpy, queue);
+ last_msc = check_msc(dpy, root, queue, last_msc);
+
error += test_exhaustion(dpy, queue);
last_msc = check_msc(dpy, root, queue, last_msc);
commit 51f184edfb2c09ea512c45cfe468a68406a8f6da
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 12:49:57 2015 +0000
test/present: Tighten the accuracy requirements
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/test/present-test.c b/test/present-test.c
index bd38977..3c84359 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -351,15 +351,18 @@ static int test_future(Display *dpy, void *Q)
} else {
int msc = (uint32_t)ce->msc - ce->serial;
if (msc < 0) {
- fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60)/(15*60), (long long)msc);
ret += -msc;
- if (-msc > earliest)
+ if (-msc > earliest) {
+ fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60)/(15*60), (long long)msc);
earliest = -msc;
+ }
early++;
- } else if (msc > 1) { /* allow the frame to slip by a vblank */
+ } else if (msc > 0) {
ret += msc;
- if (msc > latest)
+ if (msc > latest) {
+ fprintf(stderr, "\tframe %d displayed late by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
latest = msc;
+ }
late++;
}
}
@@ -609,15 +612,18 @@ static int test_accuracy(Display *dpy, void *Q)
msc = (uint32_t)ce->msc - ce->serial;
if (msc < 0) {
- fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
ret += -msc;
- if (-msc > earliest)
+ if (-msc > earliest) {
+ fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
earliest = -msc;
+ }
early++;
- } else if (msc > 1) { /* allow the frame to slip by a vblank */
+ } else if (msc > 0) {
ret += msc;
- if (msc > latest)
+ if (msc > latest) {
+ fprintf(stderr, "\tframe %d displayed late by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
latest = msc;
+ }
late++;
}
complete = ce->serial == target + 60 + N_VBLANKS;
commit ac1eb7f7c976b45b63b0ca3000ddfe1be2ccce62
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 11:23:07 2015 +0000
test/present: Test accuracy of long pauses
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 d9cb8e5..0f507b5 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -219,7 +219,7 @@ sna_present_vblank_handler(struct drm_event_vblank *event)
{
struct sna_present_event *info = to_present_event(event->user_data);
- DBG(("%s: pipe=%d tv=%d.%06d msc=%d (target=%lld), event %lld complete%s\n", __FUNCTION__,
+ DBG(("%s: pipe=%d tv=%d.%06d msc=%d (target=%lld), event=%lld complete%s\n", __FUNCTION__,
sna_crtc_to_pipe(info->crtc),
event->tv_sec, event->tv_usec, event->sequence,
(long long)info->target_msc, (long long)info->event_id,
@@ -393,7 +393,7 @@ page_flip__async(struct sna *sna,
return FALSE;
}
- DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event %lld complete\n", __FUNCTION__,
+ DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
pipe_from_crtc(crtc),
gettime_ust64() / 1000000, gettime_ust64() % 1000000,
(long long)sna_crtc_last_swap(crtc->devPrivate)->msc,
@@ -417,7 +417,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
} else
swap = *sna_crtc_last_swap(info->crtc);
- DBG(("%s: pipe=%d, tv=%d.%06d msc %lld (target %lld), event %lld complete%s\n", __FUNCTION__,
+ DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld (target %lld), event=%lld complete%s\n", __FUNCTION__,
info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
swap.tv_sec, swap.tv_usec, (long long)swap.msc,
(long long)info->target_msc,
@@ -553,7 +553,7 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id)
notify:
swap = sna_crtc_last_swap(sna_primary_crtc(sna));
- DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
+ DBG(("%s: pipe=%d, tv=%d.%06d msc=%lld, event=%lld complete\n", __FUNCTION__,
-1,
swap->tv_sec, swap->tv_usec, (long long)swap->msc,
(long long)event_id));
diff --git a/test/present-test.c b/test/present-test.c
index 9e5e96b..bd38977 100644
--- a/test/present-test.c
+++ b/test/present-test.c
@@ -243,6 +243,141 @@ static int test_whole(Display *dpy)
static int test_future(Display *dpy, void *Q)
{
+ xcb_connection_t *c = XGetXCBConnection(dpy);
+ Pixmap pixmap;
+ struct dri3_fence fence;
+ Window root;
+ unsigned int width, height;
+ unsigned border, depth;
+ int x, y, ret = 0, n;
+ uint64_t target;
+ int complete;
+ int early = 0, late = 0;
+ int earliest = 0, latest = 0;
+
+ XGetGeometry(dpy, DefaultRootWindow(dpy),
+ &root, &x, &y, &width, &height, &border, &depth);
+
+ if (dri3_create_fence(dpy, root, &fence))
+ return 0;
+
+ printf("Testing whole screen flips into the future: %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 <= 10; n++)
+ xcb_present_pixmap(c, root, pixmap,
+ target + 60 + n*15*60, /* serial */
+ 0, /* valid */
+ 0, /* update */
+ 0, /* x_off */
+ 0, /* y_off */
+ None,
+ None, /* wait fence */
+ None,
+ XCB_PRESENT_OPTION_NONE,
+ target + 60 + n*15*60, /* target msc */
+ 0, /* divisor */
+ 0, /* remainder */
+ 0, NULL);
+ 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 + n*15*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;
+
+ assert(ce->serial);
+
+ if (ce->serial == 0xdeadbeef) {
+ complete = 1;
+ } else {
+ int msc = (uint32_t)ce->msc - ce->serial;
+ if (msc < 0) {
+ fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60)/(15*60), (long long)msc);
+ ret += -msc;
+ if (-msc > earliest)
+ earliest = -msc;
+ early++;
+ } else if (msc > 1) { /* allow the frame to slip by a vblank */
+ ret += msc;
+ if (msc > latest)
+ latest = msc;
+ late++;
+ }
+ }
+ free(ev);
+ } while (!complete);
+
+ if (early)
+ printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
+ if (late)
+ printf("\t%d frames shown too late (worst %d)!\n", late, latest);
+
+ ret += !!_x_error_occurred;
+
+ return ret;
+}
+
+static int test_exhaustion(Display *dpy, void *Q)
+{
#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
xcb_connection_t *c = XGetXCBConnection(dpy);
Pixmap pixmap;
@@ -261,7 +396,7 @@ static int test_future(Display *dpy, void *Q)
if (dri3_create_fence(dpy, root, &fence))
return 0;
- printf("Testing whole screen flips into the future: %dx%d\n", width, height);
+ printf("Testing whole screen flips with long vblank queues: %dx%d\n", width, height);
_x_error_occurred = 0;
region = xcb_generate_id(c);
@@ -304,11 +439,11 @@ static int test_future(Display *dpy, void *Q)
final = check_msc(dpy, root, Q, 0);
if (final < target) {
- printf("First flip too early, MSC was %llu, expected %llu\n",
+ printf("\tFirst flip too early, MSC was %llu, expected %llu\n",
(long long)final, (long long)target);
ret++;
} else if (final > target + 1) {
- printf("First flip too late, MSC was %llu, expected %llu\n",
+ printf("\tFirst flip too late, MSC was %llu, expected %llu\n",
(long long)final, (long long)target);
ret++;
}
@@ -332,11 +467,11 @@ static int test_future(Display *dpy, void *Q)
final = check_msc(dpy, root, Q, 0);
if (final < target + N_VBLANKS) {
- printf("Last flip too early, MSC was %llu, expected %llu\n",
+ printf("\tLast flip too early, MSC was %llu, expected %llu\n",
(long long)final, (long long)(target + N_VBLANKS));
ret++;
} else if (final > target + N_VBLANKS + 1) {
- printf("Last flip too late, MSC was %llu, expected %llu\n",
+ printf("\tLast flip too late, MSC was %llu, expected %llu\n",
(long long)final, (long long)(target + N_VBLANKS));
ret++;
}
@@ -394,6 +529,7 @@ static int test_accuracy(Display *dpy, void *Q)
int x, y, ret = 0, n;
uint64_t target;
int early = 0, late = 0;
+ int earliest = 0, latest = 0;
int complete;
XGetGeometry(dpy, DefaultRootWindow(dpy),
@@ -471,13 +607,17 @@ static int test_accuracy(Display *dpy, void *Q)
assert(ce->serial);
- msc = ce->msc - ce->serial;
+ msc = (uint32_t)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);
+ fprintf(stderr, "\tframe %d displayed early by %lld frames\n", (int)(ce->serial - target - 60), (long long)msc);
ret += -msc;
+ if (-msc > earliest)
+ earliest = -msc;
early++;
} else if (msc > 1) { /* allow the frame to slip by a vblank */
ret += msc;
+ if (msc > latest)
+ latest = msc;
late++;
}
complete = ce->serial == target + 60 + N_VBLANKS;
@@ -485,11 +625,9 @@ static int test_accuracy(Display *dpy, void *Q)
} while (!complete);
if (early)
- printf("%d frames shown too early! ", early);
+ printf("\t%d frames shown too early (worst %d)!\n", early, earliest);
if (late)
- printf("%d fames shown too late!", late);
- if (early|late)
- printf("\n");
+ printf("\t%d frames shown too late (worst %d)!\n", late, latest);
ret += !!_x_error_occurred;
@@ -542,8 +680,6 @@ static int for_each_crtc(Display *dpy,
for (i = 0; i < res->ncrtc; i++)
original_crtc[i] = XRRGetCrtcInfo(dpy, res, res->crtcs[i]);
- printf("noutput=%d, ncrtc=%d\n", res->noutput, res->ncrtc);
-
for (i = 0; i < res->noutput; i++) {
XRROutputInfo *output;
XRRModeInfo *mode;
@@ -1016,6 +1152,9 @@ int main(void)
error += test_accuracy(dpy, queue);
last_msc = check_msc(dpy, root, queue, last_msc);
+ error += test_exhaustion(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);
commit 818b596a6a4dddea29f92f52d73a3577ef16c8b2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Feb 12 12:12:29 2015 +0000
sna/present: Store target_msc for DBG output in flip handler
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 e578803..d9cb8e5 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -219,11 +219,11 @@ sna_present_vblank_handler(struct drm_event_vblank *event)
{
struct sna_present_event *info = to_present_event(event->user_data);
- DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete: target_msc=%lld\n", __FUNCTION__,
+ DBG(("%s: pipe=%d tv=%d.%06d msc=%d (target=%lld), event %lld complete%s\n", __FUNCTION__,
sna_crtc_to_pipe(info->crtc),
event->tv_sec, event->tv_usec, event->sequence,
- (long long)info->event_id,
- (long long)info->target_msc));
+ (long long)info->target_msc, (long long)info->event_id,
+ info->target_msc && event->sequence == (uint32_t)info->target_msc ? "" : ": MISS"));
present_event_notify(info->event_id,
ust64(event->tv_sec, event->tv_usec),
sna_crtc_record_event(info->crtc, event));
@@ -234,32 +234,38 @@ static int
sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
{
struct sna *sna = to_sna_from_screen(crtc->pScreen);
- struct sna_present_event *event;
+ struct sna_present_event *info;
+ const struct ust_msc *swap;
union drm_wait_vblank vbl;
DBG(("%s(pipe=%d, event=%lld, msc=%lld)\n",
__FUNCTION__, pipe_from_crtc(crtc),
(long long)event_id, (long long)msc));
- event = malloc(sizeof(struct sna_present_event));
- if (event == NULL)
- return BadAlloc;
+ swap = sna_crtc_last_swap(crtc->devPrivate);
+ assert((int64_t)(msc - swap->msc) >= 0);
+ if ((int64_t)(msc - swap->msc) <= 0) {
+ present_event_notify(event_id, swap_ust(swap), swap->msc);
+ return Success;
+ }
- event->crtc = crtc->devPrivate;
- event->sna = sna;
- event->target_msc = msc;
- event->event_id = event_id;
+ info = malloc(sizeof(struct sna_present_event));
+ if (info == NULL)
+ return BadAlloc;
- assert((int64_t)(msc - sna_crtc_last_swap(event->crtc)->msc) >= 0);
+ info->crtc = crtc->devPrivate;
+ info->sna = sna;
+ info->target_msc = msc;
+ info->event_id = event_id;
VG_CLEAR(vbl);
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
vbl.request.sequence = msc;
- vbl.request.signal = (uintptr_t)MARK_PRESENT(event);
- if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(event->crtc))) {
+ vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
+ if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) {
DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
- if (!sna_fake_vblank(event)) {
- free(event);
+ if (!sna_fake_vblank(info)) {
+ free(info);
return BadAlloc;
}
}
@@ -387,11 +393,11 @@ page_flip__async(struct sna *sna,
return FALSE;
}
- DBG(("%s: pipe=%d tv=%d.%06d msc=%d, event %lld complete\n", __FUNCTION__,
+ DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event %lld complete\n", __FUNCTION__,
pipe_from_crtc(crtc),
gettime_ust64() / 1000000, gettime_ust64() % 1000000,
- sna_crtc_last_swap(crtc->devPrivate)->msc,
- (long long)event_id));
+ (long long)sna_crtc_last_swap(crtc->devPrivate)->msc,
+ (long long)target_msc, (long long)event_id));
present_event_notify(event_id, gettime_ust64(), target_msc);
return TRUE;
}
@@ -411,10 +417,12 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
} else
swap = *sna_crtc_last_swap(info->crtc);
- DBG(("%s: pipe=%d, tv=%d.%06d msc %lld, event %lld complete\n", __FUNCTION__,
+ DBG(("%s: pipe=%d, tv=%d.%06d msc %lld (target %lld), event %lld complete%s\n", __FUNCTION__,
info->crtc ? sna_crtc_to_pipe(info->crtc) : -1,
swap.tv_sec, swap.tv_usec, (long long)swap.msc,
- (long long)info->event_id));
+ (long long)info->target_msc,
+ (long long)info->event_id,
+ info->target_msc && info->target_msc == swap.msc ? "" : ": MISS"));
present_event_notify(info->event_id, swap_ust(&swap), swap.msc);
if (info->sna->present.unflip) {
@@ -430,9 +438,10 @@ static Bool
page_flip(struct sna *sna,
RRCrtcPtr crtc,
uint64_t event_id,
+ uint64_t target_msc,
struct kgem_bo *bo)
{
- struct sna_present_event *event;
+ struct sna_present_event *info;
DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
__FUNCTION__,
@@ -440,18 +449,18 @@ page_flip(struct sna *sna,
(long long)event_id,
bo->handle));
- event = malloc(sizeof(struct sna_present_event));
- if (event == NULL)
+ info = malloc(sizeof(struct sna_present_event));
+ if (info == NULL)
return FALSE;
- event->crtc = crtc ? crtc->devPrivate : NULL;
- event->sna = sna;
- event->event_id = event_id;
- event->target_msc = 0;
+ info->crtc = crtc ? crtc->devPrivate : NULL;
+ info->sna = sna;
+ info->event_id = event_id;
+ info->target_msc = target_msc;
- if (!sna_page_flip(sna, bo, present_flip_handler, event)) {
+ if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
DBG(("%s: pageflip failed\n", __FUNCTION__));
- free(event);
+ free(info);
return FALSE;
}
@@ -525,7 +534,7 @@ sna_present_flip(RRCrtcPtr crtc,
}
if (sync_flip)
- return page_flip(sna, crtc, event_id, bo);
+ return page_flip(sna, crtc, event_id, target_msc, bo);
else
return page_flip__async(sna, crtc, event_id, target_msc, bo);
}
@@ -573,7 +582,7 @@ reset_mode:
return;
}
- if (!page_flip(sna, NULL, event_id, bo))
+ if (!page_flip(sna, NULL, event_id, 0, bo))
goto reset_mode;
}
More information about the xorg-commit
mailing list