diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-04 10:07:26 -0800 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-03-05 12:52:47 -0800 |
commit | b6e0b92f398823629ba8a1ea8f5e62fbf959e725 (patch) | |
tree | c3dbbb204c0b253154a65e88d0eb5190067a0e9c /src | |
parent | 54ac4e2df987b72529a523ffbde357bec27e3658 (diff) |
DRI2: handle offscreen drawables better at swap time
If a drawable isn't visible due to DPMS or redirection, we'll just blit
it rather than schedule a swap event. However, we didn't reset the
target_msc, so the swap target we receive from the server could get out
of sync with the vblank count of the drawable's display. So at DPMS on
time, the swap target would be the last good vblank count plus some
large number (since the swaps won't have been throttled).
Solve this by zeroing out the swap target like we should when we fall
back to a blit. Also make the kernel error cases more friendly by
making them fall back to blits too.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/i830_dri.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/src/i830_dri.c b/src/i830_dri.c index 64aeb762..0738cdb9 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -641,28 +641,14 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, int ret, pipe = I830DRI2DrawablePipe(draw), flip = 0; DRI2FrameEventPtr swap_info; enum DRI2FrameEventType swap_type = DRI2_SWAP; + BoxRec box; + RegionRec region; swap_info = xcalloc(1, sizeof(DRI2FrameEventRec)); /* Drawable not displayed... just complete the swap */ - if (pipe == -1 || !swap_info) { - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = draw->width; - box.y2 = draw->height; - REGION_INIT(pScreen, ®ion, &box, 0); - - I830DRI2CopyRegion(draw, ®ion, front, back); - - DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, - data); - if (swap_info) - xfree(swap_info); - return TRUE; - } + if (pipe == -1 || !swap_info) + goto blit_fallback; swap_info->drawable_id = draw->id; swap_info->client = client; @@ -681,7 +667,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, xf86DrvMsg(scrn->scrnIndex, X_WARNING, "first get vblank counter failed: %s\n", strerror(errno)); - return FALSE; + goto blit_fallback; } /* Flips need to be submitted one frame before */ @@ -693,6 +679,13 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, swap_info->type = swap_type; + if ((*target_msc != 1) && (*target_msc > vbl.reply.sequence) && + ((*target_msc - vbl.reply.sequence) > 100)) + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "vblank event >100 frames away: cur %ld, target %ld\n", + (unsigned long)vbl.reply.sequence, + (unsigned long)*target_msc); + /* * If divisor is zero, we just need to make sure target_msc passes * before waking up the client. @@ -711,7 +704,7 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, xf86DrvMsg(scrn->scrnIndex, X_WARNING, "divisor 0 get vblank counter failed: %s\n", strerror(errno)); - return FALSE; + goto blit_fallback; } *target_msc = vbl.reply.sequence; @@ -764,13 +757,28 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, xf86DrvMsg(scrn->scrnIndex, X_WARNING, "final get vblank counter failed: %s\n", strerror(errno)); - return FALSE; + goto blit_fallback; } *target_msc = vbl.reply.sequence; swap_info->frame = *target_msc; return TRUE; + +blit_fallback: + box.x1 = 0; + box.y1 = 0; + box.x2 = draw->width; + box.y2 = draw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + I830DRI2CopyRegion(draw, ®ion, front, back); + + DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data); + if (swap_info) + xfree(swap_info); + *target_msc = 0; /* offscreen, so zero out target vblank count */ + return TRUE; } /* |