From 2805822141bb392cc282d9ffaad2ff49f57a23e0 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Tue, 23 Dec 2025 08:46:04 -0800 Subject: [PATCH] wgl: Support contexts created from non-window DCs Store the original HDC along with the HWND if we can get an HWND. If we have the HWND, then the original HDC is basically useless, but if we don't, we can use the HDC as a lookup key for the framebuffer. Part-of: --- src/egl/drivers/wgl/egl_wgl.c | 2 +- src/gallium/frontends/wgl/stw_context.c | 2 +- src/gallium/frontends/wgl/stw_ext_pbuffer.c | 2 +- src/gallium/frontends/wgl/stw_framebuffer.c | 28 ++++++++++----------- src/gallium/frontends/wgl/stw_framebuffer.h | 3 ++- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/egl/drivers/wgl/egl_wgl.c b/src/egl/drivers/wgl/egl_wgl.c index 2dc596076c7..f670c18d524 100644 --- a/src/egl/drivers/wgl/egl_wgl.c +++ b/src/egl/drivers/wgl/egl_wgl.c @@ -640,7 +640,7 @@ wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] ? wgl_conf->stw_config[1] : wgl_conf->stw_config[0]; - wgl_surf->fb = stw_framebuffer_create( + wgl_surf->fb = stw_framebuffer_create(NULL, native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base); if (!wgl_surf->fb) { free(wgl_surf); diff --git a/src/gallium/frontends/wgl/stw_context.c b/src/gallium/frontends/wgl/stw_context.c index 946dbc430c9..7297d3f1e51 100644 --- a/src/gallium/frontends/wgl/stw_context.c +++ b/src/gallium/frontends/wgl/stw_context.c @@ -544,7 +544,7 @@ get_unlocked_refd_framebuffer_from_dc(HDC hDC) */ int iPixelFormat = stw_pixelformat_guess(hDC); if (iPixelFormat) - fb = stw_framebuffer_create(WindowFromDC(hDC), stw_pixelformat_get_info(iPixelFormat), STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->fscreen); + fb = stw_framebuffer_create(hDC, WindowFromDC(hDC), stw_pixelformat_get_info(iPixelFormat), STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->fscreen); if (!fb) return NULL; } diff --git a/src/gallium/frontends/wgl/stw_ext_pbuffer.c b/src/gallium/frontends/wgl/stw_ext_pbuffer.c index 8522e88ab59..d45a37359bc 100644 --- a/src/gallium/frontends/wgl/stw_ext_pbuffer.c +++ b/src/gallium/frontends/wgl/stw_ext_pbuffer.c @@ -147,7 +147,7 @@ stw_pbuffer_create(const struct stw_pixelformat_info *pfi, int iWidth, int iHeig assert(rect.bottom - rect.top == iHeight); #endif - return stw_framebuffer_create(hWnd, pfi, STW_FRAMEBUFFER_PBUFFER, fscreen); + return stw_framebuffer_create(NULL, hWnd, pfi, STW_FRAMEBUFFER_PBUFFER, fscreen); } diff --git a/src/gallium/frontends/wgl/stw_framebuffer.c b/src/gallium/frontends/wgl/stw_framebuffer.c index 25da923278e..820f3dd5ac2 100644 --- a/src/gallium/frontends/wgl/stw_framebuffer.c +++ b/src/gallium/frontends/wgl/stw_framebuffer.c @@ -54,12 +54,12 @@ * Else, return NULL. */ static struct stw_framebuffer * -stw_framebuffer_from_hwnd_locked(HWND hwnd) +stw_framebuffer_from_hwnd_hdc_locked(HWND hwnd, HDC hdc) { struct stw_framebuffer *fb; for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) - if (fb->hWnd == hwnd) { + if ((hwnd && fb->hWnd == hwnd) || (hdc && fb->hDC == hdc)) { stw_framebuffer_lock(fb); /* When running with Zink, during the Vulkan surface creation @@ -143,7 +143,6 @@ stw_framebuffer_get_size(struct stw_framebuffer *fb) /* * Sanity checking. */ - assert(fb->hWnd); assert(fb->width && fb->height); assert(fb->client_rect.right == fb->client_rect.left + fb->width); assert(fb->client_rect.bottom == fb->client_rect.top + fb->height); @@ -151,7 +150,7 @@ stw_framebuffer_get_size(struct stw_framebuffer *fb) /* * Get the client area size. */ - if (!GetClientRect(fb->hWnd, &client_rect)) { + if (!fb->hWnd || !GetClientRect(fb->hWnd, &client_rect)) { return; } @@ -254,7 +253,7 @@ stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam) } else if (pParams->message == WM_DESTROY) { stw_lock_framebuffers(stw_dev); - fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd ); + fb = stw_framebuffer_from_hwnd_hdc_locked( pParams->hwnd, NULL ); if (fb) { struct stw_context *current_context = stw_current_context(); struct st_context *st = current_context && @@ -282,7 +281,7 @@ stw_call_window_proc_xbox(HWND hWnd, UINT message, if (stw_dev && stw_dev->initialized) { if (message == WM_DESTROY) { stw_lock_framebuffers(stw_dev); - struct stw_framebuffer *fb = stw_framebuffer_from_hwnd_locked(hWnd); + struct stw_framebuffer *fb = stw_framebuffer_from_hwnd_hdc_locked(hWnd, NULL); if (fb) { struct stw_context *current_context = stw_current_context(); struct st_context *st = current_context && @@ -309,7 +308,7 @@ stw_call_window_proc_xbox(HWND hWnd, UINT message, * with its mutex locked. */ struct stw_framebuffer * -stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner, +stw_framebuffer_create(HDC hdc, HWND hWnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner, struct pipe_frontend_screen *fscreen) { struct stw_framebuffer *fb; @@ -319,8 +318,9 @@ stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum s return NULL; fb->hWnd = hWnd; + fb->hDC = hdc; - if (stw_dev->stw_winsys->create_framebuffer) + if (fb->hWnd && stw_dev->stw_winsys->create_framebuffer) fb->winsys_framebuffer = stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, pfi->iPixelFormat); @@ -330,7 +330,8 @@ stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum s } #ifdef _GAMING_XBOX - fb->prev_wndproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&stw_call_window_proc_xbox); + if (fb->hWnd) + fb->prev_wndproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&stw_call_window_proc_xbox); #endif /* @@ -473,11 +474,8 @@ stw_framebuffer_from_hdc_locked(HDC hdc) HWND hwnd; hwnd = WindowFromDC(hdc); - if (!hwnd) { - return NULL; - } - return stw_framebuffer_from_hwnd_locked(hwnd); + return stw_framebuffer_from_hwnd_hdc_locked(hwnd, hdc); } @@ -511,7 +509,7 @@ stw_framebuffer_from_hwnd(HWND hwnd) struct stw_framebuffer *fb; stw_lock_framebuffers(stw_dev); - fb = stw_framebuffer_from_hwnd_locked(hwnd); + fb = stw_framebuffer_from_hwnd_hdc_locked(hwnd, NULL); stw_unlock_framebuffers(stw_dev); return fb; @@ -548,7 +546,7 @@ DrvSetPixelFormat(HDC hdc, LONG iPixelFormat) const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(iPixelFormat); - fb = stw_framebuffer_create(WindowFromDC(hdc), pfi, STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->fscreen); + fb = stw_framebuffer_create(hdc, WindowFromDC(hdc), pfi, STW_FRAMEBUFFER_WGL_WINDOW, stw_dev->fscreen); if (!fb) { return false; } diff --git a/src/gallium/frontends/wgl/stw_framebuffer.h b/src/gallium/frontends/wgl/stw_framebuffer.h index 01ec4ee72d4..bb3c242b283 100644 --- a/src/gallium/frontends/wgl/stw_framebuffer.h +++ b/src/gallium/frontends/wgl/stw_framebuffer.h @@ -83,6 +83,7 @@ struct stw_framebuffer */ HWND hWnd; + HDC hDC; const struct stw_pixelformat_info *pfi; @@ -158,7 +159,7 @@ struct stw_framebuffer * must be called when done */ struct stw_framebuffer * -stw_framebuffer_create(HWND hwnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner, +stw_framebuffer_create(HDC hdc, HWND hwnd, const struct stw_pixelformat_info *pfi, enum stw_framebuffer_owner owner, struct pipe_frontend_screen *fscreen); struct stw_framebuffer *