mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2025-12-20 18:40:02 +01:00
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>
(cherry picked from commit 75beadd766)
This commit is contained in:
parent
557301d5c7
commit
cc9f6806ac
1 changed files with 15 additions and 0 deletions
|
|
@ -614,6 +614,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||||
DRI2DrawablePtr pPriv;
|
DRI2DrawablePtr pPriv;
|
||||||
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
CARD64 ust, current_msc;
|
||||||
|
|
||||||
pPriv = DRI2GetDrawable(pDraw);
|
pPriv = DRI2GetDrawable(pDraw);
|
||||||
if (pPriv == NULL) {
|
if (pPriv == NULL) {
|
||||||
|
|
@ -658,12 +659,26 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
||||||
* need to schedule a swap for the last swap target + the swap interval.
|
* need to schedule a swap for the last swap target + the swap interval.
|
||||||
*/
|
*/
|
||||||
if (target_msc == 0 && divisor == 0 && remainder == 0) {
|
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
|
* Swap target for this swap is last swap target + swap interval since
|
||||||
* we have to account for the current swap count, interval, and the
|
* we have to account for the current swap count, interval, and the
|
||||||
* number of pending swaps.
|
* number of pending swaps.
|
||||||
*/
|
*/
|
||||||
*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
||||||
*swap_target = target_msc;
|
*swap_target = target_msc;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue