summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <mdaenzer@redhat.com>2022-03-15 17:47:56 +0100
committerOlivier Fourdan <ofourdan@redhat.com>2022-03-24 09:22:29 +0100
commit1a7e4e72182cf530504ea88053b0652872da3c13 (patch)
tree2925b11a26a34c565b66ee70dc127888bc61d341
parent88ed88e8a70a759f5269f828fc0e54b1120c4a5b (diff)
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: 9b31358c52e9 ("xwayland: Use frame callbacks for Present vblank events") Reviewed-by: Olivier Fourdan <ofourdan@redhat.com> (cherry picked from commit 9e5a3796108e2b89212fa440f80e918d24b971c8)
-rw-r--r--hw/xwayland/xwayland-present.c17
-rw-r--r--hw/xwayland/xwayland-present.h3
-rw-r--r--hw/xwayland/xwayland-window.c12
3 files changed, 25 insertions, 7 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c
index d727f8419..ce74482ef 100644
--- a/hw/xwayland/xwayland-present.c
+++ b/hw/xwayland/xwayland-present.c
@@ -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,
diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h
index 5d880e822..ab7f04a3b 100644
--- a/hw/xwayland/xwayland-present.h
+++ b/hw/xwayland/xwayland-present.h
@@ -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);
diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c
index 92bcae326..41061e344 100644
--- a/hw/xwayland/xwayland-window.c
+++ b/hw/xwayland/xwayland-window.c
@@ -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