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; |     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) { | ||||||
|  | @ -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. |      * 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…
	
		Reference in New Issue