From: Miklós Máté Subject: [PATCH 2/2] winex11: track glx windows per thread Message-Id: <1469050556-5610-3-git-send-email-mtmkls@gmail.com> Date: Wed, 20 Jul 2016 23:35:56 +0200 In-Reply-To: <1469050556-5610-1-git-send-email-mtmkls@gmail.com> References: <1469050556-5610-1-git-send-email-mtmkls@gmail.com> XCloseDisplay in thread_detach() closes all X windows, but the GLX windows remain, and become zombies. If a new X window is created with the same XID, Mesa refuses to attach a GLX window to it because of the zombie. Observed in the ddraw test. Signed-off-by: Miklós Máté --- dlls/winex11.drv/opengl.c | 52 ++++++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/x11drv_main.c | 2 ++ 3 files changed, 56 insertions(+) diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 86b91ec..d11a9b6 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -265,6 +265,12 @@ struct gl_drawable BOOL refresh_swap_interval; }; +struct gl_hwnd +{ + HWND hwnd; + struct list entry; +}; + enum glx_swap_control_method { GLX_SWAP_CONTROL_NONE, @@ -1419,6 +1425,8 @@ static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl, struct x11drv static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format ) { struct gl_drawable *gl, *prev; + struct gl_hwnd *glh; + struct x11drv_thread_data *thr_data; Window old_client_window; struct x11drv_win_data *data; @@ -1457,6 +1465,13 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format ) TRACE( "created GL drawable %lx for win %p %s\n", gl->drawable, hwnd, debugstr_fbconfig( format->fbconfig )); + thr_data = TlsGetValue( thread_data_tls_index ); + if (thr_data) + { + glh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*glh) ); + glh->hwnd = hwnd; + list_add_head( &thr_data->gl_drawables, &glh->entry ); + } XFlush( gdi_display ); EnterCriticalSection( &context_section ); @@ -1636,17 +1651,54 @@ done: void destroy_gl_drawable( HWND hwnd ) { struct gl_drawable *gl; + struct gl_hwnd *glh, *glh2; + struct x11drv_thread_data *thr_data; EnterCriticalSection( &context_section ); if (!XFindContext( gdi_display, (XID)hwnd, gl_hwnd_context, (char **)&gl )) { XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context ); free_gl_drawable( gl ); + + thr_data = TlsGetValue( thread_data_tls_index ); + if (thr_data) + { + LIST_FOR_EACH_ENTRY_SAFE( glh, glh2, &thr_data->gl_drawables, struct gl_hwnd, entry ) + { + if (glh->hwnd == hwnd) + { + list_remove( &glh->entry ); + HeapFree( GetProcessHeap(), 0, glh ); + } + } + } XSync( gdi_display, False ); } LeaveCriticalSection( &context_section ); } +/*********************************************************************** + * destroy_all_gl_drawables + */ +void destroy_all_gl_drawables( struct x11drv_thread_data *data ) +{ + struct gl_drawable *gl; + struct gl_hwnd *glh, *glh2; + + EnterCriticalSection( &context_section ); + LIST_FOR_EACH_ENTRY_SAFE( glh, glh2, &data->gl_drawables, struct gl_hwnd, entry ) + { + if (!XFindContext( gdi_display, (XID)(glh->hwnd), gl_hwnd_context, (char **)&gl )) + { + XDeleteContext( gdi_display, (XID)(glh->hwnd), gl_hwnd_context ); + free_gl_drawable( gl ); + } + list_remove( &glh->entry ); + HeapFree( GetProcessHeap(), 0, glh->hwnd ); + } + XSync( gdi_display, False ); + LeaveCriticalSection( &context_section ); +} /** * glxdrv_DescribePixelFormat diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 2180851..2dfff6e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -326,6 +326,7 @@ struct x11drv_thread_data void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */ int xi2_device_count; int xi2_core_pointer; /* XInput2 core pointer id */ + struct list gl_drawables; /* list of gl drawables created */ }; extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; @@ -576,6 +577,7 @@ extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN; extern void sync_gl_drawable( HWND hwnd, const RECT *visible_rect, const RECT *client_rect ) DECLSPEC_HIDDEN; extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN; extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN; +extern void destroy_all_gl_drawables( struct x11drv_thread_data *data ) DECLSPEC_HIDDEN; extern void wait_for_withdrawn_state( HWND hwnd, BOOL set ) DECLSPEC_HIDDEN; extern Window init_clip_window(void) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index d4f5c84..0b90afd 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -608,6 +608,7 @@ static void thread_detach(void) X11DRV_ResetSelectionOwner(); if (data->xim) XCloseIM( data->xim ); if (data->font_set) XFreeFontSet( data->display, data->font_set ); + destroy_all_gl_drawables( data ); XCloseDisplay( data->display ); HeapFree( GetProcessHeap(), 0, data ); /* clear data in case we get re-entered from user32 before the thread is truly dead */ @@ -672,6 +673,7 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) if (TRACE_ON(synchronous)) XSynchronize( data->display, True ); set_queue_display_fd( data->display ); + list_init( &data->gl_drawables ); TlsSetValue( thread_data_tls_index, data ); if (use_xim) X11DRV_SetupXIM(); -- 2.8.1