From: Miklós Máté Subject: [PATCH resend] winex11: fix destroying of top-level windows v5 Message-Id: <20161128225330.30720-1-mtmkls@gmail.com> Date: Mon, 28 Nov 2016 23:53:30 +0100 Fixes https://bugs.winehq.org/show_bug.cgi?id=40767 v2: move glXDestroyWindow before XDestroyWindow v3: fix critical section, fix command serialization with xsync now it passes the ddraw and d3d9 tests (both vanilla and csmt) v4: fix uninitialized variable, more xsync v5: the xsync calls added in v4 are not needed, fix SetParent Signed-off-by: Miklós Máté --- dlls/winex11.drv/opengl.c | 35 +++++++++++++++++++++++++++++------ dlls/winex11.drv/window.c | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index d89a193..ae2e231 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1314,6 +1314,9 @@ static void free_gl_drawable( struct gl_drawable *gl ) { switch (gl->type) { + case DC_GL_WINDOW: + pglXDestroyWindow( gdi_display, gl->drawable ); + break; case DC_GL_CHILD_WIN: pglXDestroyWindow( gdi_display, gl->drawable ); XDestroyWindow( gdi_display, gl->window ); @@ -1334,21 +1337,21 @@ static void free_gl_drawable( struct gl_drawable *gl ) /*********************************************************************** * create_gl_drawable */ -static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl ) +static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl, struct x11drv_win_data *data ) { gl->drawable = 0; if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow()) /* top-level window */ { - struct x11drv_win_data *data = get_win_data( hwnd ); - if (data) { gl->type = DC_GL_WINDOW; gl->window = create_client_window( data, gl->visual ); if (gl->window) + { gl->drawable = pglXCreateWindow( gdi_display, gl->format->fbconfig, gl->window, NULL ); - release_win_data( data ); + XSync( gdi_display, False ); + } } } #ifdef SONAME_LIBXCOMPOSITE @@ -1416,6 +1419,8 @@ static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl ) static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format ) { struct gl_drawable *gl, *prev; + Window old_client_window = None; + struct x11drv_win_data *data; gl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*gl) ); /* Default GLX and WGL swap interval is 1, but in case of glXSwapIntervalSGI @@ -1435,12 +1440,19 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format ) gl->rect.right = min( max( 1, gl->rect.right ), 65535 ); gl->rect.bottom = min( max( 1, gl->rect.bottom ), 65535 ); - if (!create_gl_drawable( hwnd, gl )) + data = get_win_data( hwnd ); + if (data) { + old_client_window = data->client_window; + } + + if (!create_gl_drawable( hwnd, gl, data )) { + release_win_data( data ); XFree( gl->visual ); HeapFree( GetProcessHeap(), 0, gl ); return FALSE; } + release_win_data( data ); TRACE( "created GL drawable %lx for win %p %s\n", gl->drawable, hwnd, debugstr_fbconfig( format->fbconfig )); @@ -1452,6 +1464,10 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format ) { gl->swap_interval = prev->swap_interval; free_gl_drawable( prev ); + XSync( gdi_display, False ); + if (old_client_window) { + XDestroyWindow( data->display, old_client_window ); + } } XSaveContext( gdi_display, (XID)hwnd, gl_hwnd_context, (char *)gl ); LeaveCriticalSection( &context_section ); @@ -1566,6 +1582,7 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent ) { struct gl_drawable *gl; GLXDrawable old_drawable; + struct x11drv_win_data *data; if (!(gl = get_gl_drawable( hwnd, 0 ))) return; @@ -1575,6 +1592,7 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent ) switch (gl->type) { case DC_GL_WINDOW: + pglXDestroyWindow( gdi_display, gl->drawable ); break; case DC_GL_CHILD_WIN: if (parent != GetDesktopWindow()) goto done; @@ -1590,16 +1608,20 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent ) default: goto done; } + XSync( gdi_display, False ); - if (!create_gl_drawable( hwnd, gl )) + data = get_win_data( hwnd ); + if (!create_gl_drawable( hwnd, gl, data )) { XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context ); + release_win_data( data ); release_gl_drawable( gl ); XFree( gl->visual ); HeapFree( GetProcessHeap(), 0, gl ); __wine_set_pixel_format( hwnd, 0 ); return; } + release_win_data( data ); mark_drawable_dirty( old_drawable, gl->drawable ); done: @@ -1620,6 +1642,7 @@ void destroy_gl_drawable( HWND hwnd ) { XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context ); free_gl_drawable( gl ); + XSync( gdi_display, False ); } LeaveCriticalSection( &context_section ); } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 0de7955..0f23c72 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1437,7 +1437,6 @@ Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *vi if (data->client_window) { XDeleteContext( data->display, data->client_window, winContext ); - XDestroyWindow( data->display, data->client_window ); } if (data->colormap) XFreeColormap( data->display, data->colormap ); @@ -2169,6 +2168,7 @@ void CDECL X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ) if (old_parent == GetDesktopWindow()) { /* destroy the old X windows */ + destroy_gl_drawable( hwnd ); destroy_whole_window( data, FALSE ); data->managed = FALSE; } -- 2.9.3