[PATCH 2/2] winex11: track glx windows per thread
Miklós Máté
mtmkls at gmail.com
Wed Jul 20 16:35:56 CDT 2016
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é <mtmkls at gmail.com>
---
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
More information about the wine-patches
mailing list