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) |         if (!xwl_present_window) | ||||||
|             return NULL; |             return NULL; | ||||||
| 
 | 
 | ||||||
|  |         xwl_present_window->window = window; | ||||||
|         xwl_present_window->msc = 1; |         xwl_present_window->msc = 1; | ||||||
|         xwl_present_window->ust = GetTimeInMicros(); |         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); |            !xorg_list_is_empty(&xwl_present_window->wait_list); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | void | ||||||
| xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) | xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) | ||||||
| { | { | ||||||
|     if (xwl_present_has_pending_events(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 now = GetTimeInMillis(); | ||||||
|         CARD32 timeout; |         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; |             timeout = TIMER_LEN_FLIP; | ||||||
|         else |         else | ||||||
|             timeout = TIMER_LEN_COPY; |             timeout = TIMER_LEN_COPY; | ||||||
|  | @ -505,8 +508,8 @@ xwl_present_queue_vblank(ScreenPtr screen, | ||||||
|     xorg_list_del(&event->vblank.event_queue); |     xorg_list_del(&event->vblank.event_queue); | ||||||
|     xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list); |     xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list); | ||||||
| 
 | 
 | ||||||
|     /* If there's a pending frame callback, use that */ |     /* Hook up to frame callback */ | ||||||
|     if (xwl_window && xwl_window->frame_callback && |     if (xwl_window && | ||||||
|         xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { |         xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { | ||||||
|         xorg_list_add(&xwl_present_window->frame_callback_list, |         xorg_list_add(&xwl_present_window->frame_callback_list, | ||||||
|                       &xwl_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) */ |     /* We can flip directly to the main surface (full screen window without clips) */ | ||||||
|     wl_surface_attach(xwl_window->surface, buffer, 0, 0); |     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)) { |     if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { | ||||||
|         xorg_list_add(&xwl_present_window->frame_callback_list, |         xorg_list_add(&xwl_present_window->frame_callback_list, | ||||||
|                       &xwl_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, |     xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface, | ||||||
|                        damage_box->x1 - present_window->drawable.x, |                        damage_box->x1 - present_window->drawable.x, | ||||||
|                        damage_box->y1 - present_window->drawable.y, |                        damage_box->y1 - present_window->drawable.y, | ||||||
|  |  | ||||||
|  | @ -35,6 +35,8 @@ | ||||||
| 
 | 
 | ||||||
| #ifdef GLAMOR_HAS_GBM | #ifdef GLAMOR_HAS_GBM | ||||||
| struct xwl_present_window { | struct xwl_present_window { | ||||||
|  |     WindowPtr window; | ||||||
|  | 
 | ||||||
|     struct xorg_list frame_callback_list; |     struct xorg_list frame_callback_list; | ||||||
| 
 | 
 | ||||||
|     uint64_t msc; |     uint64_t msc; | ||||||
|  | @ -59,6 +61,7 @@ struct xwl_present_event { | ||||||
|     PixmapPtr pixmap; |     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); | void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window); | ||||||
| Bool xwl_present_init(ScreenPtr screen); | Bool xwl_present_init(ScreenPtr screen); | ||||||
| void xwl_present_cleanup(WindowPtr window); | 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); |     xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); | ||||||
|     wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, |     wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, | ||||||
|                              xwl_window); |                              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 | Bool | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue