summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner@tuebingen.mpg.de>2012-02-16 00:45:20 +0100
committerBen Skeggs <bskeggs@redhat.com>2012-03-06 08:12:57 +1000
commit919643888045b102f3e10dfdeb6210ab14b6ecab (patch)
tree493f4ea108eebe4cf769dae89f0e3936af42efb3
parent5ede4538366a352aa9726560f8d42e85df4aec82 (diff)
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.c23
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;