Commit 4bba16fd authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Handle resizing of OpenGL content.

Wayland surfaces don't have an inherent native size that the EGL implementation can track, so we need to explicitly tell EGL about changes in the native size with wl_egl_window_resize. Since the resize can be triggered outside the GL render thread, and wl_egl_window_resize is not thread safe (with respect to other EGL/GL calls), we cannot call it directly at will. Instead we mark the wayland_gl_drawable as resized, and actually call the wl_egl_window_resize function from the thread in which the respective drawable is current. Note that the first EGL/GL operation that requires a new backbuffer latches whatever native size we have reported, until the next eglSwapBuffers. In order to ensure the current native size is applied as soon as possible (to avoid glitches), we check for and apply resizes at a few extra points where a new backbuffer may be required (e.g., glClear, eglMakeCurrent).
parent aed0c822
......@@ -68,6 +68,7 @@ DECL_FUNCPTR(eglInitialize);
DECL_FUNCPTR(eglMakeCurrent);
DECL_FUNCPTR(eglQueryString);
DECL_FUNCPTR(eglSwapBuffers);
DECL_FUNCPTR(glClear);
#undef DECL_FUNCPTR
static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER;
......@@ -82,6 +83,7 @@ struct wayland_gl_drawable
struct wayland_client_surface *client;
struct wl_egl_window *wl_egl_window;
EGLSurface surface;
LONG resized;
};
struct wgl_context
......@@ -228,6 +230,28 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne
if (old) wayland_gl_drawable_release(old);
}
static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl)
{
int client_width, client_height;
struct wayland_surface *wayland_surface;
if (InterlockedCompareExchange(&gl->resized, FALSE, TRUE))
{
if (!(wayland_surface = wayland_surface_lock_hwnd(gl->hwnd))) return;
client_width = wayland_surface->window.client_rect.right -
wayland_surface->window.client_rect.left;
client_height = wayland_surface->window.client_rect.bottom -
wayland_surface->window.client_rect.top;
if (client_width == 0 || client_height == 0)
client_width = client_height = 1;
wl_egl_window_resize(gl->wl_egl_window, client_width, client_height, 0, 0);
pthread_mutex_unlock(&wayland_surface->mutex);
}
}
static void wayland_gl_drawable_sync_surface_state(struct wayland_gl_drawable *gl)
{
struct wayland_surface *wayland_surface;
......@@ -263,6 +287,10 @@ static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd,
draw ? draw->surface : EGL_NO_SURFACE,
read ? read->surface : EGL_NO_SURFACE);
/* Since making an EGL surface current may latch the native size,
* perform any pending resizes before calling it. */
if (draw) wayland_gl_drawable_sync_size(draw);
pthread_mutex_lock(&gl_object_mutex);
ret = p_eglMakeCurrent(egl_display,
......@@ -380,6 +408,15 @@ out:
return ctx;
}
void wayland_glClear(GLbitfield mask)
{
struct wgl_context *ctx = NtCurrentTeb()->glContext;
/* Since glClear is one of the operations that may latch the native size,
* perform any pending resizes before calling it. */
if (ctx && ctx->draw) wayland_gl_drawable_sync_size(ctx->draw);
p_glClear(mask);
}
static BOOL wayland_wglCopyContext(struct wgl_context *src,
struct wgl_context *dst, UINT mask)
{
......@@ -528,6 +565,7 @@ static BOOL wayland_wglSwapBuffers(HDC hdc)
if (ctx) wgl_context_refresh(ctx);
wayland_gl_drawable_sync_surface_state(gl);
p_eglSwapBuffers(egl_display, gl->surface);
wayland_gl_drawable_sync_size(gl);
wayland_gl_drawable_release(gl);
......@@ -569,6 +607,9 @@ static BOOL init_opengl_funcs(void)
}
}
p_glClear = opengl_funcs.gl.p_glClear;
opengl_funcs.gl.p_glClear = wayland_glClear;
register_extension("WGL_ARB_extensions_string");
opengl_funcs.ext.p_wglGetExtensionsStringARB = wayland_wglGetExtensionsStringARB;
......@@ -768,6 +809,20 @@ void wayland_destroy_gl_drawable(HWND hwnd)
wayland_update_gl_drawable(hwnd, NULL);
}
/**********************************************************************
* wayland_resize_gl_drawable
*/
void wayland_resize_gl_drawable(HWND hwnd)
{
struct wayland_gl_drawable *gl;
if (!(gl = wayland_gl_drawable_get(hwnd))) return;
/* wl_egl_window_resize is not thread safe, so we just mark the
* drawable as resized and perform the resize in the proper thread. */
InterlockedExchange(&gl->resized, TRUE);
wayland_gl_drawable_release(gl);
}
#else /* No GL */
struct opengl_funcs *WAYLAND_wine_get_wgl_driver(UINT version)
......@@ -779,4 +834,8 @@ void wayland_destroy_gl_drawable(HWND hwnd)
{
}
void wayland_resize_gl_drawable(HWND hwnd)
{
}
#endif
......@@ -519,6 +519,8 @@ static void wayland_surface_reconfigure_client(struct wayland_surface *surface)
}
wl_surface_commit(surface->client->wl_surface);
wayland_resize_gl_drawable(surface->hwnd);
}
/**********************************************************************
......
......@@ -297,6 +297,7 @@ void wayland_pointer_clear_constraint(void);
*/
void wayland_destroy_gl_drawable(HWND hwnd);
void wayland_resize_gl_drawable(HWND hwnd);
/**********************************************************************
* Helpers
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment