From ac83c29e7a2502f578f1513a2548ecf1959a1b96 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Fri, 29 Apr 2022 12:28:17 +0300 Subject: [PATCH] simple-egl: Defer EGL surface/window creation Rather than creating the wl_egl_window at the same time as wl_surface, do it after we get the first configure event. With it, we also defer eglMakeCurrent() as according to the spec, the first time a OpenGL or OpenGL ES context is made current, the viewport and scissor dimensions are set to the size of the draw surface. This is particulary important when attempting to start simple-egl either as fullscreen or as maximized, as not doing so will either incorrectly commit a buffer with the original dimensions, and later on to resize to the correct dimensions (which is the case for fullscreen), or it will terminate the wayland connection abruptly due to xdg-shell protocol violation, with a mismatch for the client's geometry (the case for maximized). Signed-off-by: Marius Vlad Suggested-by: Daniel Stone (cherry picked from commit 0277046a1da6058ed574b5b788ebd2a2592a84ff) --- clients/simple-egl.c | 51 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/clients/simple-egl.c b/clients/simple-egl.c index 93ff3e59..e48dbc69 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -262,6 +262,19 @@ init_gl(struct window *window) GLuint frag, vert; GLuint program; GLint status; + EGLBoolean ret; + + window->native = wl_egl_window_create(window->surface, + window->geometry.width, + window->geometry.height); + window->egl_surface = + weston_platform_create_egl_surface(window->display->egl.dpy, + window->display->egl.conf, + window->native, NULL); + + ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, + window->egl_surface, window->display->egl.ctx); + assert(ret == EGL_TRUE); frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER); vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER); @@ -362,19 +375,9 @@ static void create_surface(struct window *window) { struct display *display = window->display; - EGLBoolean ret; window->surface = wl_compositor_create_surface(display->compositor); - window->native = - wl_egl_window_create(window->surface, - window->geometry.width, - window->geometry.height); - window->egl_surface = - weston_platform_create_egl_surface(display->egl.dpy, - display->egl.conf, - window->native, NULL); - window->xdg_surface = xdg_wm_base_get_xdg_surface(display->wm_base, window->surface); xdg_surface_add_listener(window->xdg_surface, @@ -392,10 +395,6 @@ create_surface(struct window *window) window->wait_for_configure = true; wl_surface_commit(window->surface); - ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, - window->egl_surface, window->display->egl.ctx); - assert(ret == EGL_TRUE); - if (!window->frame_sync) eglSwapInterval(display->egl.dpy, 0); @@ -866,7 +865,17 @@ main(int argc, char **argv) init_egl(&display, &window); create_surface(&window); - init_gl(&window); + + /* we already have wait_for_configure set after create_surface() */ + while (running && ret != -1 && window.wait_for_configure) { + ret = wl_display_dispatch(display.display); + + /* wait until xdg_surface::configure acks the new dimensions */ + if (window.wait_for_configure) + continue; + + init_gl(&window); + } display.cursor_surface = wl_compositor_create_surface(display.compositor); @@ -876,17 +885,9 @@ main(int argc, char **argv) sigint.sa_flags = SA_RESETHAND; sigaction(SIGINT, &sigint, NULL); - /* The mainloop here is a little subtle. Redrawing will cause - * EGL to read events so we can just call - * wl_display_dispatch_pending() to handle any events that got - * queued up as a side effect. */ while (running && ret != -1) { - if (window.wait_for_configure) { - ret = wl_display_dispatch(display.display); - } else { - ret = wl_display_dispatch_pending(display.display); - redraw(&window, NULL, 0); - } + ret = wl_display_dispatch_pending(display.display); + redraw(&window, NULL, 0); } fprintf(stderr, "simple-egl exiting\n");