sna/present: Restrict vblank.sequence range to 31bits
The kernel checks for past vblanks using an int32_t comparison, so we can only program up to 31bits into the future (and similarly programing a timer that large would also overflow). References: https://bugs.freedesktop.org/show_bug.cgi?id=94685 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
4e108afe55
commit
c186d4dda3
|
|
@ -114,8 +114,10 @@ static void vblank_complete(struct sna_present_event *info,
|
|||
int n;
|
||||
|
||||
if (msc < info->target_msc) {
|
||||
DBG(("%s: %d too early, now %lld, expected %lld\n",
|
||||
__FUNCTION__, (long long)msc, (long long)info->target_msc));
|
||||
DBG(("%s: event=%d too early, now %lld, expected %lld\n",
|
||||
__FUNCTION__,
|
||||
info->event_id[0],
|
||||
(long long)msc, (long long)info->target_msc));
|
||||
if (sna_present_queue(info, msc))
|
||||
return;
|
||||
}
|
||||
|
|
@ -247,7 +249,7 @@ static bool sna_present_queue(struct sna_present_event *info,
|
|||
(long long)info->target_msc,
|
||||
(unsigned)info->target_msc,
|
||||
(long long)last_msc));
|
||||
assert(info->target_msc - last_msc < 1ull<<32);
|
||||
assert(info->target_msc - last_msc < 1ull<<31);
|
||||
|
||||
VG_CLEAR(vbl);
|
||||
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
|
||||
|
|
@ -360,7 +362,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
|
|||
present_event_notify(event_id, swap_ust(swap), swap->msc);
|
||||
return Success;
|
||||
}
|
||||
if (warn_unless(msc - swap->msc < 1ull<<32))
|
||||
if (warn_unless(msc - swap->msc < 1ull<<31))
|
||||
return BadValue;
|
||||
|
||||
list_for_each_entry(tmp, &sna->present.vblank_queue, link) {
|
||||
|
|
|
|||
|
|
@ -1089,6 +1089,86 @@ static int test_future_msc(Display *dpy, void *Q)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int test_wrap_msc(Display *dpy)
|
||||
{
|
||||
xcb_connection_t *c = XGetXCBConnection(dpy);
|
||||
Window root, win;
|
||||
int x, y;
|
||||
unsigned int width, height;
|
||||
unsigned border, depth;
|
||||
XSetWindowAttributes attr;
|
||||
int ret = 0, n;
|
||||
uint64_t msc, ust;
|
||||
int complete;
|
||||
uint64_t interval;
|
||||
void *Q;
|
||||
|
||||
XGetGeometry(dpy, DefaultRootWindow(dpy),
|
||||
&root, &x, &y, &width, &height, &border, &depth);
|
||||
|
||||
attr.override_redirect = 1;
|
||||
win = XCreateWindow(dpy, root,
|
||||
0, 0, width, height, 0, depth,
|
||||
InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
|
||||
CWOverrideRedirect, &attr);
|
||||
XMapWindow(dpy, win);
|
||||
XSync(dpy, True);
|
||||
if (_x_error_occurred)
|
||||
return 1;
|
||||
|
||||
printf("Testing wraparound notifies\n");
|
||||
_x_error_occurred = 0;
|
||||
|
||||
Q = setup_msc(dpy, win);
|
||||
interval = msc_interval(dpy, win, Q);
|
||||
if (interval == 0) {
|
||||
printf("Zero delay between frames\n");
|
||||
return 1;
|
||||
}
|
||||
msc = check_msc(dpy, win, Q, 0, &ust);
|
||||
printf("Initial msc=%llx, interval between frames %lldus\n",
|
||||
(long long)msc, (long long)interval);
|
||||
|
||||
for (n = 1; n <= 10; n++)
|
||||
xcb_present_notify_msc(c, win, n,
|
||||
msc + ((long long)n<<32) + n,
|
||||
0, 0);
|
||||
for (n = 1; n <= 10; n++)
|
||||
xcb_present_notify_msc(c, win, -n,
|
||||
0, (long long)n << 32, 0);
|
||||
xcb_present_notify_msc(c, win, 0xdeadbeef, msc + 60*10, 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) {
|
||||
complete = 1;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"\tnotify %d recieved at +%llu\n",
|
||||
ce->serial, ce->msc - msc);
|
||||
ret++;
|
||||
}
|
||||
free(ev);
|
||||
} while (!complete);
|
||||
|
||||
teardown_msc(dpy, Q);
|
||||
XDestroyWindow(dpy, win);
|
||||
XSync(dpy, True);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_exhaustion_msc(Display *dpy, void *Q)
|
||||
{
|
||||
#define N_VBLANKS 256 /* kernel event queue length: 128 vblanks */
|
||||
|
|
@ -2019,6 +2099,9 @@ int main(void)
|
|||
error += test_future_msc(dpy, queue);
|
||||
last_msc = check_msc(dpy, root, queue, last_msc, NULL);
|
||||
|
||||
error += test_wrap_msc(dpy);
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue