Module: wine Branch: master Commit: eb5993a7c6fbc1cd9deac0dceabc8f1c76e14ba8 URL: https://gitlab.winehq.org/wine/wine/-/commit/eb5993a7c6fbc1cd9deac0dceabc8f1...
Author: Paul Gofman pgofman@codeweavers.com Date: Mon Jan 22 16:28:32 2024 -0600
winex11.drv: Fix wglSwapBuffers() with NULL current context with child window rendering.
---
dlls/opengl32/tests/opengl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/opengl.c | 10 ++++----- 2 files changed, 57 insertions(+), 5 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index e3ca82a9b03..74aff6b4bbd 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -2006,6 +2006,55 @@ static void test_copy_context(HDC hdc) ok(ret, "wglMakeCurrent failed, last error %#lx.\n", GetLastError()); }
+static void test_child_window(HWND hwnd, PIXELFORMATDESCRIPTOR *pfd) +{ + int pixel_format; + DWORD t1, t; + HGLRC hglrc; + HWND child; + HDC hdc; + int res; + + child = CreateWindowA("static", "Title", WS_CHILDWINDOW | WS_VISIBLE, 50, 50, 100, 100, hwnd, NULL, NULL, NULL); + ok(!!child, "got error %lu.\n", GetLastError()); + + hdc = GetDC(child); + pixel_format = ChoosePixelFormat(hdc, pfd); + res = SetPixelFormat(hdc, pixel_format, pfd); + ok(res, "got error %lu.\n", GetLastError()); + + hglrc = wglCreateContext(hdc); + ok(!!hglrc, "got error %lu.\n", GetLastError()); + + /* Test SwapBuffers with NULL context. */ + + glDrawBuffer(GL_BACK); + + /* Currently blit happening for child window in winex11 may not be updated with the latest GL frame + * even on glXWaitForSbcOML() path. So simulate continuous present for the test purpose. */ + trace("Child window rectangle should turn from red to green now.\n"); + t1 = GetTickCount(); + while ((t = GetTickCount()) - t1 < 3000) + { + res = wglMakeCurrent(hdc, hglrc); + ok(res, "got error %lu.\n", GetLastError()); + if (t - t1 > 1500) + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + else + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + res = wglMakeCurrent(NULL, NULL); + ok(res, "got error %lu.\n", GetLastError()); + SwapBuffers(hdc); + } + + res = wglDeleteContext(hglrc); + ok(res, "got error %lu.\n", GetLastError()); + + ReleaseDC(child, hdc); + DestroyWindow(child); +} + START_TEST(opengl) { HWND hwnd; @@ -2138,6 +2187,9 @@ START_TEST(opengl) else skip("WGL_EXT_swap_control not supported, skipping test\n");
+ if (winetest_interactive) + test_child_window(hwnd, &pfd); + cleanup: ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index bb8f13f78b9..d70f1928655 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -3378,7 +3378,7 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) case DC_GL_PIXMAP_WIN: if (ctx) sync_context( ctx ); escape.gl_drawable = gl->pixmap; - if (pglXCopySubBufferMESA) { + if (ctx && pglXCopySubBufferMESA) { /* (glX)SwapBuffers has an implicit glFlush effect, however * GLX_MESA_copy_sub_buffer doesn't. Make sure GL is flushed before * copying */ @@ -3387,7 +3387,7 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) gl->pixmap_size.cx, gl->pixmap_size.cy ); break; } - if (pglXSwapBuffersMscOML) + if (ctx && pglXSwapBuffersMscOML) { pglFlush(); target_sbc = pglXSwapBuffersMscOML( gdi_display, gl->drawable, 0, 0, 0 ); @@ -3401,7 +3401,7 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) if (gl->type == DC_GL_CHILD_WIN) escape.gl_drawable = gl->window; /* fall through */ default: - if (escape.gl_drawable && pglXSwapBuffersMscOML) + if (ctx && escape.gl_drawable && pglXSwapBuffersMscOML) { pglFlush(); target_sbc = pglXSwapBuffersMscOML( gdi_display, gl->drawable, 0, 0, 0 ); @@ -3411,13 +3411,13 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc ) break; }
- if (escape.gl_drawable && pglXWaitForSbcOML) + if (ctx && escape.gl_drawable && pglXWaitForSbcOML) pglXWaitForSbcOML( gdi_display, gl->drawable, target_sbc, &ust, &msc, &sbc );
release_gl_drawable( gl );
if (escape.gl_drawable) - NtGdiExtEscape( ctx->hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); + NtGdiExtEscape( ctx ? ctx->hdc : hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); return TRUE; }