diff options
author | Mario Kleiner <mario.kleiner@tuebingen.mpg.de> | 2012-02-16 00:45:20 +0100 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-03-06 08:12:57 +1000 |
commit | 919643888045b102f3e10dfdeb6210ab14b6ecab (patch) | |
tree | 493f4ea108eebe4cf769dae89f0e3936af42efb3 | |
parent | 5ede4538366a352aa9726560f8d42e85df4aec82 (diff) | |
download | xorg-driver-xf86-video-nouveau-919643888045b102f3e10dfdeb6210ab14b6ecab.tar.gz |
dri2: Fixes to swap scheduling.
Fix some small off-by-one errors and a mismatch
between 32 bit kernel interfaces for vblank count
and 64 bit dri2 interfaces for target_msc et al.
Return corrected target_msc to swap scheduling in
x-server.
A revised version of the patch discussed here:
http://lists.freedesktop.org/archives/nouveau/2011-September/009143.html
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | src/nouveau_dri2.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 8608678..719b3bb 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -387,11 +387,22 @@ nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, if (ret) goto fail; + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal. + */ + *target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + /* Calculate a swap target if we don't have one */ if (current_msc >= *target_msc && divisor) *target_msc = current_msc + divisor - (current_msc - remainder) % divisor; + /* Avoid underflow of unsigned value below */ + if (*target_msc == 0) + *target_msc = 1; + /* Request a vblank event one frame before the target */ ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, @@ -399,7 +410,8 @@ nouveau_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, &expect_msc, NULL, s); if (ret) goto fail; - s->frame = (unsigned int) expect_msc & 0xffffffff; + s->frame = 1 + ((unsigned int) expect_msc & 0xffffffff); + *target_msc = 1 + expect_msc; } else { /* We can't/don't want to sync to vblank, just swap. */ nouveau_dri2_finish_swap(draw, 0, 0, 0, s); @@ -420,6 +432,13 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, CARD64 current_msc; int ret; + /* Truncate to match kernel interfaces; means occasional overflow + * misses, but that's generally not a big deal. + */ + target_msc &= 0xffffffff; + divisor &= 0xffffffff; + remainder &= 0xffffffff; + if (!can_sync_to_vblank(draw)) { DRI2WaitMSCComplete(client, draw, target_msc, 0, 0); return TRUE; @@ -439,7 +458,7 @@ nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, goto fail; /* Calculate a wait target if we don't have one */ - if (current_msc > target_msc && divisor) + if (current_msc >= target_msc && divisor) target_msc = current_msc + divisor - (current_msc - remainder) % divisor; |