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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39077>
This commit is contained in:
Jesse Natalie 2025-12-23 08:46:04 -08:00 committed by Marge Bot
parent fe45960b8a
commit 2805822141
5 changed files with 18 additions and 19 deletions

View file

@ -640,7 +640,7 @@ wgl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1] const struct stw_pixelformat_info *stw_conf = wgl_conf->stw_config[1]
? wgl_conf->stw_config[1] ? wgl_conf->stw_config[1]
: wgl_conf->stw_config[0]; : 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); native_window, stw_conf, STW_FRAMEBUFFER_EGL_WINDOW, &wgl_dpy->base);
if (!wgl_surf->fb) { if (!wgl_surf->fb) {
free(wgl_surf); free(wgl_surf);

View file

@ -544,7 +544,7 @@ get_unlocked_refd_framebuffer_from_dc(HDC hDC)
*/ */
int iPixelFormat = stw_pixelformat_guess(hDC); int iPixelFormat = stw_pixelformat_guess(hDC);
if (iPixelFormat) 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) if (!fb)
return NULL; return NULL;
} }

View file

@ -147,7 +147,7 @@ stw_pbuffer_create(const struct stw_pixelformat_info *pfi, int iWidth, int iHeig
assert(rect.bottom - rect.top == iHeight); assert(rect.bottom - rect.top == iHeight);
#endif #endif
return stw_framebuffer_create(hWnd, pfi, STW_FRAMEBUFFER_PBUFFER, fscreen); return stw_framebuffer_create(NULL, hWnd, pfi, STW_FRAMEBUFFER_PBUFFER, fscreen);
} }

View file

@ -54,12 +54,12 @@
* Else, return NULL. * Else, return NULL.
*/ */
static struct stw_framebuffer * 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; struct stw_framebuffer *fb;
for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next) 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); stw_framebuffer_lock(fb);
/* When running with Zink, during the Vulkan surface creation /* When running with Zink, during the Vulkan surface creation
@ -143,7 +143,6 @@ stw_framebuffer_get_size(struct stw_framebuffer *fb)
/* /*
* Sanity checking. * Sanity checking.
*/ */
assert(fb->hWnd);
assert(fb->width && fb->height); assert(fb->width && fb->height);
assert(fb->client_rect.right == fb->client_rect.left + fb->width); assert(fb->client_rect.right == fb->client_rect.left + fb->width);
assert(fb->client_rect.bottom == fb->client_rect.top + fb->height); 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. * Get the client area size.
*/ */
if (!GetClientRect(fb->hWnd, &client_rect)) { if (!fb->hWnd || !GetClientRect(fb->hWnd, &client_rect)) {
return; return;
} }
@ -254,7 +253,7 @@ stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam)
} }
else if (pParams->message == WM_DESTROY) { else if (pParams->message == WM_DESTROY) {
stw_lock_framebuffers(stw_dev); 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) { if (fb) {
struct stw_context *current_context = stw_current_context(); struct stw_context *current_context = stw_current_context();
struct st_context *st = 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 (stw_dev && stw_dev->initialized) {
if (message == WM_DESTROY) { if (message == WM_DESTROY) {
stw_lock_framebuffers(stw_dev); 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) { if (fb) {
struct stw_context *current_context = stw_current_context(); struct stw_context *current_context = stw_current_context();
struct st_context *st = 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. * with its mutex locked.
*/ */
struct stw_framebuffer * 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 pipe_frontend_screen *fscreen)
{ {
struct stw_framebuffer *fb; struct stw_framebuffer *fb;
@ -319,8 +318,9 @@ stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum s
return NULL; return NULL;
fb->hWnd = hWnd; 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 = fb->winsys_framebuffer =
stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, pfi->iPixelFormat); stw_dev->stw_winsys->create_framebuffer(stw_dev->screen, hWnd, pfi->iPixelFormat);
@ -330,6 +330,7 @@ stw_framebuffer_create(HWND hWnd, const struct stw_pixelformat_info *pfi, enum s
} }
#ifdef _GAMING_XBOX #ifdef _GAMING_XBOX
if (fb->hWnd)
fb->prev_wndproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&stw_call_window_proc_xbox); fb->prev_wndproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&stw_call_window_proc_xbox);
#endif #endif
@ -473,11 +474,8 @@ stw_framebuffer_from_hdc_locked(HDC hdc)
HWND hwnd; HWND hwnd;
hwnd = WindowFromDC(hdc); 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; struct stw_framebuffer *fb;
stw_lock_framebuffers(stw_dev); 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); stw_unlock_framebuffers(stw_dev);
return fb; return fb;
@ -548,7 +546,7 @@ DrvSetPixelFormat(HDC hdc, LONG iPixelFormat)
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(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) { if (!fb) {
return false; return false;
} }

View file

@ -83,6 +83,7 @@ struct stw_framebuffer
*/ */
HWND hWnd; HWND hWnd;
HDC hDC;
const struct stw_pixelformat_info *pfi; const struct stw_pixelformat_info *pfi;
@ -158,7 +159,7 @@ struct stw_framebuffer
* must be called when done * must be called when done
*/ */
struct stw_framebuffer * 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 pipe_frontend_screen *fscreen);
struct stw_framebuffer * struct stw_framebuffer *