DRI2/xserver: Don't hang in glXSwapBuffers if drawable moves between crtc's (bug 28383)
Detect if a drawable has been moved from an original crtc to a new crtc with a lower current vblank count than the original crtc inbetween glXSwapBuffers() calls. Reinitialize drawable's last_swap_target before scheduling next swap if such a move has taken place. last_swap_target defines the baseline for scheduling the next swap. If a movement between crtc's is not taken into account, the swap may schedule for a vblank count on the new crtc far in the future, resulting in a apparent "hang" of the drawable for a long time. Fixes Bugzilla bug #28383. Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
868bf3de47
commit
75beadd766
@ -759,6 +759,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||
DRI2DrawablePtr pPriv;
|
||||
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
||||
int ret, i;
|
||||
CARD64 ust, current_msc;
|
||||
|
||||
pPriv = DRI2GetDrawable(pDraw);
|
||||
if (pPriv == NULL) {
|
||||
@ -803,12 +804,26 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||
* need to schedule a swap for the last swap target + the swap interval.
|
||||
*/
|
||||
if (target_msc == 0 && divisor == 0 && remainder == 0) {
|
||||
/* If the current vblank count of the drawable's crtc is lower
|
||||
* than the count stored in last_swap_target from a previous swap
|
||||
* then reinitialize last_swap_target to the current crtc's msc,
|
||||
* otherwise the swap will hang. This will happen if the drawable
|
||||
* is moved to a crtc with a lower refresh rate, or a crtc that just
|
||||
* got enabled.
|
||||
*/
|
||||
if (!(*ds->GetMSC)(pDraw, &ust, ¤t_msc))
|
||||
pPriv->last_swap_target = 0;
|
||||
|
||||
if (current_msc < pPriv->last_swap_target)
|
||||
pPriv->last_swap_target = current_msc;
|
||||
|
||||
/*
|
||||
* Swap target for this swap is last swap target + swap interval since
|
||||
* we have to account for the current swap count, interval, and the
|
||||
* number of pending swaps.
|
||||
*/
|
||||
*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
||||
|
||||
} else {
|
||||
/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
||||
*swap_target = target_msc;
|
||||
|
Loading…
Reference in New Issue
Block a user