From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/opengl.c | 91 ++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 8 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 8c1336fffcb..70334658296 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -67,6 +67,7 @@ DECL_FUNCPTR(eglGetProcAddress); DECL_FUNCPTR(eglInitialize); DECL_FUNCPTR(eglMakeCurrent); DECL_FUNCPTR(eglQueryString); +DECL_FUNCPTR(eglSwapBuffers); #undef DECL_FUNCPTR
static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -88,7 +89,7 @@ struct wgl_context struct list entry; EGLConfig config; EGLContext context; - struct wayland_gl_drawable *draw, *read; + struct wayland_gl_drawable *draw, *read, *new_draw, *new_read; };
static struct wayland_gl_drawable *wayland_gl_drawable_get(HWND hwnd) @@ -206,17 +207,17 @@ static void update_context_drawables(struct wayland_gl_drawable *new,
LIST_FOR_EACH_ENTRY(ctx, &gl_contexts, struct wgl_context, entry) { - if (ctx->draw == old) + if (ctx->draw == old || ctx->new_draw == old) { - wayland_gl_drawable_array_add(release, ctx->draw); + if (ctx->new_draw) wayland_gl_drawable_array_add(release, ctx->new_draw); InterlockedIncrement(&new->ref); - ctx->draw = new; + ctx->new_draw = new; } - if (ctx->read == old) + if (ctx->read == old || ctx->new_read == old) { - wayland_gl_drawable_array_add(release, ctx->read); + if (ctx->new_read) wayland_gl_drawable_array_add(release, ctx->new_read); InterlockedIncrement(&new->ref); - ctx->read = new; + ctx->new_read = new; } } } @@ -249,12 +250,32 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne wl_array_release(&release); }
+static void wayland_gl_drawable_sync_surface_state(struct wayland_gl_drawable *gl) +{ + struct wayland_surface *wayland_surface; + + if (!(wayland_surface = wayland_surface_lock_hwnd(gl->hwnd))) return; + + wayland_surface_ensure_contents(wayland_surface); + + /* Handle any processed configure request, to ensure the related + * surface state is applied by the compositor. */ + if (wayland_surface->processing.serial && + wayland_surface->processing.processed && + wayland_surface_reconfigure(wayland_surface)) + { + wl_surface_commit(wayland_surface->wl_surface); + } + + pthread_mutex_unlock(&wayland_surface->mutex); +} + static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, HWND read_hwnd) { BOOL ret; struct wayland_gl_drawable *draw_gl = NULL, *read_gl = NULL; - struct wayland_gl_drawable *release[2]; + struct wayland_gl_drawable *release[4]; int i;
draw_gl = wayland_gl_drawable_get(draw_hwnd); @@ -275,14 +296,18 @@ static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, { release[0] = ctx->draw; release[1] = ctx->read; + release[2] = ctx->new_draw; + release[3] = ctx->new_read; ctx->draw = draw_gl; ctx->read = read_gl; + ctx->new_draw = ctx->new_read = NULL; NtCurrentTeb()->glContext = ctx; } else { release[0] = draw_gl; release[1] = read_gl; + release[2] = release[3] = NULL; }
pthread_mutex_unlock(&gl_object_mutex); @@ -295,6 +320,35 @@ static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, return ret; }
+static void wgl_context_refresh(struct wgl_context *ctx) +{ + BOOL refresh = FALSE; + struct wayland_gl_drawable *old_draw = NULL, *old_read = NULL; + + pthread_mutex_lock(&gl_object_mutex); + + if (ctx->new_draw) + { + old_draw = ctx->draw; + ctx->draw = ctx->new_draw; + ctx->new_draw = NULL; + refresh = TRUE; + } + if (ctx->new_read) + { + old_read = ctx->read; + ctx->read = ctx->new_read; + ctx->new_read = NULL; + refresh = TRUE; + } + if (refresh) p_eglMakeCurrent(egl_display, ctx->draw, ctx->read, ctx->context); + + pthread_mutex_unlock(&gl_object_mutex); + + if (old_draw) wayland_gl_drawable_release(old_draw); + if (old_read) wayland_gl_drawable_release(old_read); +} + static BOOL set_pixel_format(HDC hdc, int format, BOOL internal) { HWND hwnd = NtUserWindowFromDC(hdc); @@ -376,6 +430,8 @@ static BOOL wayland_wglDeleteContext(struct wgl_context *ctx) p_eglDestroyContext(egl_display, ctx->context); if (ctx->draw) wayland_gl_drawable_release(ctx->draw); if (ctx->read) wayland_gl_drawable_release(ctx->read); + if (ctx->new_draw) wayland_gl_drawable_release(ctx->new_draw); + if (ctx->new_read) wayland_gl_drawable_release(ctx->new_read); free(ctx); return TRUE; } @@ -489,6 +545,23 @@ static BOOL wayland_wglSetPixelFormatWINE(HDC hdc, int format) return set_pixel_format(hdc, format, TRUE); }
+static BOOL wayland_wglSwapBuffers(HDC hdc) +{ + struct wgl_context *ctx = NtCurrentTeb()->glContext; + HWND hwnd = NtUserWindowFromDC(hdc); + struct wayland_gl_drawable *gl; + + if (!(gl = wayland_gl_drawable_get(hwnd))) return FALSE; + + if (ctx) wgl_context_refresh(ctx); + wayland_gl_drawable_sync_surface_state(gl); + p_eglSwapBuffers(egl_display, gl->surface); + + wayland_gl_drawable_release(gl); + + return TRUE; +} + static BOOL has_extension(const char *list, const char *ext) { size_t len = strlen(ext); @@ -641,6 +714,7 @@ static void init_opengl(void) LOAD_FUNCPTR_EGL(eglGetPlatformDisplay); LOAD_FUNCPTR_EGL(eglInitialize); LOAD_FUNCPTR_EGL(eglMakeCurrent); + LOAD_FUNCPTR_EGL(eglSwapBuffers); #undef LOAD_FUNCPTR_EGL
egl_display = p_eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, @@ -695,6 +769,7 @@ static struct opengl_funcs opengl_funcs = .p_wglGetProcAddress = wayland_wglGetProcAddress, .p_wglMakeCurrent = wayland_wglMakeCurrent, .p_wglSetPixelFormat = wayland_wglSetPixelFormat, + .p_wglSwapBuffers = wayland_wglSwapBuffers, } };