xwayland: Always hook up frame_callback_list in xwl_present_queue_vblank
Even if there's no pending frame callback yet.
Without this, if there was no pending frame callback yet in
xwl_present_queue_vblank, xwl_present_msc_bump would only get called
from xwl_present_timer_callback, resulting in the MSC ticking at ~58
Hertz.
Doing this requires some adjustments elsewhere:
1. xwl_present_reset_timer needs to check for a pending frame callback
   as well.
2. xwl_window_create_frame_callback needs to call
   xwl_present_reset_timer for all child windows hooked up to
   frame_callback_list, to make sure the timer length takes the pending
   frame callback into account.
3. xwl_present_flip needs to hook up the window to frame_callback_list
   before calling xwl_window_create_frame_callback, for 2. to work.
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1309
Fixes: 9b31358c52 ("xwayland: Use frame callbacks for Present vblank events")
Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									102764b683
								
							
						
					
					
						commit
						9e5a379610
					
				|  | @ -66,6 +66,7 @@ xwl_present_window_get_priv(WindowPtr window) | |||
|         if (!xwl_present_window) | ||||
|             return NULL; | ||||
| 
 | ||||
|         xwl_present_window->window = window; | ||||
|         xwl_present_window->msc = 1; | ||||
|         xwl_present_window->ust = GetTimeInMicros(); | ||||
| 
 | ||||
|  | @ -127,14 +128,16 @@ xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window) | |||
|            !xorg_list_is_empty(&xwl_present_window->wait_list); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| void | ||||
| xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) | ||||
| { | ||||
|     if (xwl_present_has_pending_events(xwl_present_window)) { | ||||
|         struct xwl_window *xwl_window = xwl_window_from_window(xwl_present_window->window); | ||||
|         CARD32 now = GetTimeInMillis(); | ||||
|         CARD32 timeout; | ||||
| 
 | ||||
|         if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list)) | ||||
|         if (xwl_window && xwl_window->frame_callback && | ||||
|             !xorg_list_is_empty(&xwl_present_window->frame_callback_list)) | ||||
|             timeout = TIMER_LEN_FLIP; | ||||
|         else | ||||
|             timeout = TIMER_LEN_COPY; | ||||
|  | @ -505,8 +508,8 @@ xwl_present_queue_vblank(ScreenPtr screen, | |||
|     xorg_list_del(&event->vblank.event_queue); | ||||
|     xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list); | ||||
| 
 | ||||
|     /* If there's a pending frame callback, use that */ | ||||
|     if (xwl_window && xwl_window->frame_callback && | ||||
|     /* Hook up to frame callback */ | ||||
|     if (xwl_window && | ||||
|         xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { | ||||
|         xorg_list_add(&xwl_present_window->frame_callback_list, | ||||
|                       &xwl_window->frame_callback_list); | ||||
|  | @ -700,14 +703,14 @@ xwl_present_flip(WindowPtr present_window, | |||
|     /* We can flip directly to the main surface (full screen window without clips) */ | ||||
|     wl_surface_attach(xwl_window->surface, buffer, 0, 0); | ||||
| 
 | ||||
|     if (!xwl_window->frame_callback) | ||||
|         xwl_window_create_frame_callback(xwl_window); | ||||
| 
 | ||||
|     if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { | ||||
|         xorg_list_add(&xwl_present_window->frame_callback_list, | ||||
|                       &xwl_window->frame_callback_list); | ||||
|     } | ||||
| 
 | ||||
|     if (!xwl_window->frame_callback) | ||||
|         xwl_window_create_frame_callback(xwl_window); | ||||
| 
 | ||||
|     xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface, | ||||
|                        damage_box->x1 - present_window->drawable.x, | ||||
|                        damage_box->y1 - present_window->drawable.y, | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ | |||
| 
 | ||||
| #ifdef GLAMOR_HAS_GBM | ||||
| struct xwl_present_window { | ||||
|     WindowPtr window; | ||||
| 
 | ||||
|     struct xorg_list frame_callback_list; | ||||
| 
 | ||||
|     uint64_t msc; | ||||
|  | @ -59,6 +61,7 @@ struct xwl_present_event { | |||
|     PixmapPtr pixmap; | ||||
| }; | ||||
| 
 | ||||
| void xwl_present_reset_timer(struct xwl_present_window *xwl_present_window); | ||||
| void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window); | ||||
| Bool xwl_present_init(ScreenPtr screen); | ||||
| void xwl_present_cleanup(WindowPtr window); | ||||
|  |  | |||
|  | @ -765,6 +765,18 @@ xwl_window_create_frame_callback(struct xwl_window *xwl_window) | |||
|     xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); | ||||
|     wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, | ||||
|                              xwl_window); | ||||
| 
 | ||||
| #ifdef GLAMOR_HAS_GBM | ||||
|     if (xwl_window->xwl_screen->present) { | ||||
|         struct xwl_present_window *xwl_present_window, *tmp; | ||||
| 
 | ||||
|         xorg_list_for_each_entry_safe(xwl_present_window, tmp, | ||||
|                                       &xwl_window->frame_callback_list, | ||||
|                                       frame_callback_list) { | ||||
|             xwl_present_reset_timer(xwl_present_window); | ||||
|         } | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| Bool | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue