From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58846 --- dlls/win32u/dc.c | 23 ++++++++++++++ dlls/win32u/dce.c | 14 +++++++++ dlls/win32u/ntgdi_private.h | 2 ++ dlls/win32u/ntuser_private.h | 4 +++ dlls/win32u/opengl.c | 59 +++++++++++++++++++++--------------- dlls/win32u/window.c | 2 +- 6 files changed, 78 insertions(+), 26 deletions(-)
diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c index 553be987946..839fd821175 100644 --- a/dlls/win32u/dc.c +++ b/dlls/win32u/dc.c @@ -326,6 +326,29 @@ void release_dc_ptr( DC *dc ) if (ref) dc->thread = GetCurrentThreadId(); /* we still own it */ }
+BOOL is_dc_display( HDC hdc ) +{ + int ret; + DC *dc; + + if (!(dc = get_dc_ptr( hdc ))) return FALSE; + ret = dc->is_display; + release_dc_ptr( dc ); + + return ret; +} + +int get_dc_pixel_format( HDC hdc ) +{ + int ret; + DC *dc; + + if (!(dc = get_dc_ptr( hdc ))) return -1; + ret = dc->pixel_format; + release_dc_ptr( dc ); + + return ret; +}
static void set_bk_color( DC *dc, COLORREF color ) { diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 4dcddd2059a..c70482d4522 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1102,6 +1102,7 @@ void free_dce( struct dce *dce, HWND hwnd ) { WARN( "GetDC() without ReleaseDC() for window %p\n", hwnd ); dce->count = 0; + set_dc_pixel_format_internal( dce->hdc, 0 ); set_dce_flags( dce->hdc, DCHF_DISABLEDC ); } } @@ -1117,6 +1118,18 @@ void free_dce( struct dce *dce, HWND hwnd ) } }
+BOOL is_cache_dc( HDC hdc ) +{ + BOOL ret = FALSE; + struct dce *dce; + + user_lock(); + if ((dce = get_dc_dce( hdc ))) ret = !!(dce->flags & DCX_CACHE); + user_unlock(); + + return ret; +} + /*********************************************************************** * make_dc_dirty * @@ -1224,6 +1237,7 @@ static INT release_dc( HWND hwnd, HDC hdc, BOOL end_paint ) if (dce->flags & DCX_CACHE) { dce->count = 0; + set_dc_pixel_format_internal( hdc, 0 ); set_dce_flags( dce->hdc, DCHF_DISABLEDC ); } ret = TRUE; diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h index ba61a7369b5..fcfbce58fea 100644 --- a/dlls/win32u/ntgdi_private.h +++ b/dlls/win32u/ntgdi_private.h @@ -181,6 +181,8 @@ extern DC *alloc_dc_ptr( DWORD magic ); extern void free_dc_ptr( DC *dc ); extern DC *get_dc_ptr( HDC hdc ); extern void release_dc_ptr( DC *dc ); +extern BOOL is_dc_display( HDC hdc ); +extern int get_dc_pixel_format( HDC hdc ); extern struct dce *get_dc_dce( HDC hdc ); extern void set_dc_dce( HDC hdc, struct dce *dce ); extern WORD set_dce_flags( HDC hdc, WORD flags ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 1d0131e5886..f62b7691ba2 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -211,6 +211,7 @@ HICON alloc_cursoricon_handle( BOOL is_icon ); /* dce.c */ extern void free_dce( struct dce *dce, HWND hwnd ); extern void invalidate_dce( WND *win, const RECT *old_rect ); +extern BOOL is_cache_dc( HDC hdc );
/* message.c */ extern void check_for_events( UINT flags ); @@ -218,6 +219,9 @@ extern void check_for_events( UINT flags ); /* systray.c */ extern LRESULT system_tray_call( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *data );
+/* opengl.c */ +extern BOOL set_dc_pixel_format_internal( HDC hdc, int format ); + /* vulkan.c */ extern PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; extern PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index fc0be5795d4..4ceffe35b07 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -1269,39 +1269,27 @@ static const char *win32u_wglGetExtensionsStringEXT(void) return wgl_extensions; }
-static int get_dc_pixel_format( HDC hdc, BOOL internal ) +static int win32u_wglGetPixelFormat( HDC hdc ) { - int ret = 0; + BOOL is_display = is_dc_display( hdc ); + int format; HWND hwnd; - DC *dc;
if ((hwnd = NtUserWindowFromDC( hdc ))) - ret = get_window_pixel_format( hwnd, internal ); - else if ((dc = get_dc_ptr( hdc ))) - { - BOOL is_display = dc->is_display; - ret = dc->pixel_format; - release_dc_ptr( dc ); - - /* Offscreen formats can't be used with traditional WGL calls. As has been - * verified on Windows GetPixelFormat doesn't fail but returns 1. - */ - if (is_display && ret >= 0 && ret > onscreen_count) ret = 1; - } - else + format = get_window_pixel_format( hwnd, FALSE ); + else if ((format = get_dc_pixel_format( hdc )) < 0) { WARN( "Invalid DC handle %p\n", hdc ); RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return -1; }
- TRACE( "%p/%p -> %d\n", hdc, hwnd, ret ); - return ret; -} + /* Offscreen formats can't be used with traditional WGL calls. As has been + * verified on Windows GetPixelFormat doesn't fail but returns 1. + */ + if (is_display && format > onscreen_count) format = 1;
-static int win32u_wglGetPixelFormat( HDC hdc ) -{ - int format = get_dc_pixel_format( hdc, FALSE ); + TRACE( "%p/%p -> %d\n", hdc, hwnd, format ); return format > 0 ? format : 0; }
@@ -1509,9 +1497,26 @@ static BOOL win32u_wglSetPixelFormat( HDC hdc, int format, const PIXELFORMATDESC return set_dc_pixel_format( hdc, format, FALSE ); }
+BOOL set_dc_pixel_format_internal( HDC hdc, int format ) +{ + DC *dc; + + if (!(dc = get_dc_ptr( hdc ))) return FALSE; + dc->pixel_format = format; + release_dc_ptr( dc ); + + return TRUE; +} + static BOOL win32u_wglSetPixelFormatWINE( HDC hdc, int format ) { - return set_dc_pixel_format( hdc, format, TRUE ); + HWND hwnd; + + if (!(hwnd = NtUserWindowFromDC( hdc )) || !is_cache_dc( hdc )) return FALSE; + if (format && get_window_pixel_format( hwnd, FALSE ) == format) return TRUE; + + if (!set_dc_pixel_format( hdc, format, TRUE )) return FALSE; + return set_dc_pixel_format_internal( hdc, format ); }
static PROC win32u_wglGetProcAddress( const char *name ) @@ -1684,10 +1689,12 @@ static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct return TRUE; }
- if ((format = get_dc_pixel_format( draw_hdc, TRUE )) <= 0) + if ((format = get_dc_pixel_format( draw_hdc )) <= 0 && + (format = get_window_pixel_format( NtUserWindowFromDC( draw_hdc ), FALSE )) <= 0) { WARN( "Invalid draw_hdc %p format %u\n", draw_hdc, format ); if (!format) RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); + else RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return FALSE; } if (context->format != format) @@ -2144,9 +2151,11 @@ static BOOL win32u_wgl_context_reset( struct wgl_context *context, HDC hdc, stru context->driver_private = NULL; if (!hdc) return TRUE;
- if ((format = get_dc_pixel_format( hdc, TRUE )) <= 0) + if ((format = get_dc_pixel_format( hdc )) <= 0 && + (format = get_window_pixel_format( NtUserWindowFromDC( hdc ), FALSE )) <= 0) { if (!format) RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); + else RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return FALSE; } if (!driver_funcs->p_context_create( format, share_private, attribs, &context->driver_private )) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index c5c5d0522c8..8a026a3c189 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1568,7 +1568,7 @@ int get_window_pixel_format( HWND hwnd, BOOL internal ) if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) { WARN( "getting format on win %p not supported\n", hwnd ); - return 0; + return -1; }
ret = internal && win->internal_pixel_format ? win->internal_pixel_format : win->pixel_format;