summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clients/window.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/clients/window.c b/clients/window.c
index b12c21c..ab9a36e 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -3363,6 +3363,36 @@ surface_resize(struct surface *surface)
}
static void
+hack_prevent_EGL_sub_surface_deadlock(struct window *window)
+{
+ /*
+ * This hack should be removed, when EGL respects
+ * eglSwapInterval(0).
+ *
+ * If this window has sub-surfaces, especially a free-running
+ * EGL-widget, we need to post the parent surface once with
+ * all the old state to guarantee, that the EGL-widget will
+ * receive its frame callback soon. Otherwise, a forced call
+ * to eglSwapBuffers may end up blocking, waiting for a frame
+ * event that will never come, because we will commit the parent
+ * surface with all new state only after eglSwapBuffers returns.
+ *
+ * This assumes, that:
+ * 1. When the EGL widget's resize hook is called, it pauses.
+ * 2. When the EGL widget's redraw hook is called, it forces a
+ * repaint and a call to eglSwapBuffers(), and maybe resumes.
+ * In a single threaded application condition 1 is a no-op.
+ *
+ * XXX: This should actually be after the surface_resize() calls,
+ * but cannot, because then it would commit the incomplete state
+ * accumulated from the widget resize hooks.
+ */
+ if (window->subsurface_list.next != &window->main_surface->link ||
+ window->subsurface_list.prev != &window->main_surface->link)
+ wl_surface_commit(window->main_surface->surface);
+}
+
+static void
idle_resize(struct window *window)
{
struct surface *surface;
@@ -3370,6 +3400,8 @@ idle_resize(struct window *window)
window->resize_needed = 0;
window->redraw_needed = 1;
+ hack_prevent_EGL_sub_surface_deadlock(window);
+
widget_set_allocation(window->main_surface->widget,
window->pending_allocation.x,
window->pending_allocation.y,