From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58846 --- dlls/win32u/dce.c | 10 ++++++-- dlls/win32u/ntuser_private.h | 2 +- dlls/win32u/opengl.c | 49 ++++++++++++++++++++++++++---------- 3 files changed, 45 insertions(+), 16 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index c70482d4522..c84ba693509 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -1070,6 +1070,7 @@ static struct dce *get_window_dce( HWND hwnd ) */ void free_dce( struct dce *dce, HWND hwnd ) { + struct opengl_drawable *drawable = NULL; struct dce *dce_to_free = NULL;
user_lock(); @@ -1102,7 +1103,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_dc_pixel_format_internal( dce->hdc, 0, &drawable ); set_dce_flags( dce->hdc, DCHF_DISABLEDC ); } } @@ -1116,6 +1117,8 @@ void free_dce( struct dce *dce, HWND hwnd ) NtGdiDeleteObjectApp( dce_to_free->hdc ); free( dce_to_free ); } + + if (drawable) opengl_drawable_release( drawable ); }
BOOL is_cache_dc( HDC hdc ) @@ -1223,6 +1226,7 @@ void invalidate_dce( WND *win, const RECT *old_rect ) */ static INT release_dc( HWND hwnd, HDC hdc, BOOL end_paint ) { + struct opengl_drawable *drawable = NULL; struct dce *dce; BOOL ret = FALSE;
@@ -1237,12 +1241,14 @@ 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_dc_pixel_format_internal( hdc, 0, &drawable ); set_dce_flags( dce->hdc, DCHF_DISABLEDC ); } ret = TRUE; } user_unlock(); + + if (drawable) opengl_drawable_release( drawable ); return ret; }
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index f62b7691ba2..2e03f0d732a 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -220,7 +220,7 @@ extern void check_for_events( UINT flags ); 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 ); +extern BOOL set_dc_pixel_format_internal( HDC hdc, int format, struct opengl_drawable **drawable );
/* vulkan.c */ extern PFN_vkGetDeviceProcAddr p_vkGetDeviceProcAddr; diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 4ceffe35b07..2c12c0da6ea 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -1454,7 +1454,7 @@ static BOOL flush_memory_dc( struct wgl_context *context, HDC hdc, BOOL write, v return ret; }
-static BOOL set_dc_pixel_format( HDC hdc, int new_format, BOOL internal ) +static BOOL win32u_wglSetPixelFormat( HDC hdc, int new_format, const PIXELFORMATDESCRIPTOR *pfd ) { const struct opengl_funcs *funcs = &display_funcs; UINT total, onscreen; @@ -1474,9 +1474,9 @@ static BOOL set_dc_pixel_format( HDC hdc, int new_format, BOOL internal ) return FALSE; }
- TRACE( "%p/%p format %d, internal %u\n", hdc, hwnd, new_format, internal ); + TRACE( "%p/%p format %d\n", hdc, hwnd, new_format );
- if ((old_format = get_window_pixel_format( hwnd, FALSE )) && !internal) return old_format == new_format; + if ((old_format = get_window_pixel_format( hwnd, FALSE ))) return old_format == new_format;
if ((drawable = get_window_unused_drawable( hwnd, new_format ))) { @@ -1485,24 +1485,21 @@ static BOOL set_dc_pixel_format( HDC hdc, int new_format, BOOL internal ) opengl_drawable_release( drawable ); }
- return set_window_pixel_format( hwnd, new_format, internal ); + return set_window_pixel_format( hwnd, new_format, FALSE ); }
- TRACE( "%p/%p format %d, internal %u\n", hdc, hwnd, new_format, internal ); + TRACE( "%p/%p format %d\n", hdc, hwnd, new_format ); return NtGdiSetPixelFormat( hdc, new_format ); }
-static BOOL win32u_wglSetPixelFormat( HDC hdc, int format, const PIXELFORMATDESCRIPTOR *pfd ) -{ - return set_dc_pixel_format( hdc, format, FALSE ); -} - -BOOL set_dc_pixel_format_internal( HDC hdc, int format ) +BOOL set_dc_pixel_format_internal( HDC hdc, int format, struct opengl_drawable **drawable ) { DC *dc;
if (!(dc = get_dc_ptr( hdc ))) return FALSE; dc->pixel_format = format; + *drawable = dc->opengl_drawable; + dc->opengl_drawable = NULL; release_dc_ptr( dc );
return TRUE; @@ -1510,13 +1507,35 @@ BOOL set_dc_pixel_format_internal( HDC hdc, int format )
static BOOL win32u_wglSetPixelFormatWINE( HDC hdc, int format ) { + const struct opengl_funcs *funcs = &display_funcs; + struct opengl_drawable *drawable; + UINT total, onscreen; 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 ); + TRACE( "%p/%p format %d\n", hdc, hwnd, format ); + + funcs->p_get_pixel_formats( NULL, 0, &total, &onscreen ); + if (format < 0 || format > total) return FALSE; + if (format > onscreen) return FALSE; + + if (!set_dc_pixel_format_internal( hdc, format, &drawable )) return FALSE; + + if (drawable && drawable->format != format) + { + opengl_drawable_release( drawable ); + drawable = NULL; + } + if (format && (drawable || (drawable = get_window_unused_drawable( hwnd, format )))) + { + set_window_opengl_drawable( hwnd, drawable, TRUE ); + set_dc_opengl_drawable( hdc, drawable ); + opengl_drawable_release( drawable ); + } + + return TRUE; }
static PROC win32u_wglGetProcAddress( const char *name ) @@ -1586,6 +1605,10 @@ static BOOL context_sync_drawables( struct wgl_context *context, HDC draw_hdc, H struct wgl_context *previous = NtCurrentTeb()->glContext; BOOL ret = FALSE;
+ /* retrieve the D3D internal drawables from the DCs if they have any */ + if (draw_hdc && !context->draw) context->draw = get_dc_opengl_drawable( draw_hdc ); + if (read_hdc && !context->read) context->read = get_dc_opengl_drawable( read_hdc ); + new_draw = get_updated_drawable( draw_hdc, context->format, context->draw ); if (!draw_hdc && context->draw == context->read) opengl_drawable_add_ref( (new_read = new_draw) ); else if (draw_hdc && draw_hdc == read_hdc) opengl_drawable_add_ref( (new_read = new_draw) );