From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/ntuser_private.h | 3 +++ dlls/win32u/opengl.c | 38 +++++++++++++++++++++++++++++++ dlls/win32u/window.c | 2 ++ dlls/wineandroid.drv/opengl.c | 6 +++++ dlls/wineandroid.drv/window.c | 2 -- dlls/winemac.drv/opengl.c | 10 ++++++++ dlls/winewayland.drv/opengl.c | 27 ++++++++++++---------- dlls/winewayland.drv/waylanddrv.h | 1 - dlls/winewayland.drv/window.c | 1 - dlls/winex11.drv/opengl.c | 20 ++++++++++------ dlls/winex11.drv/window.c | 1 - dlls/winex11.drv/x11drv.h | 1 - include/wine/opengl_driver.h | 3 +++ 13 files changed, 90 insertions(+), 25 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index a3714cd8994..fc2d2947210 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -223,6 +223,9 @@ extern PFN_vkGetInstanceProcAddr p_vkGetInstanceProcAddr; extern BOOL vulkan_init(void); extern void vulkan_detach_surfaces( struct list *surfaces );
+/* opengl.c */ +extern void detach_opengl_drawables( HWND hwnd ); + /* window.c */ HANDLE alloc_user_handle( void *ptr, unsigned short type ); void *free_user_handle( HANDLE handle, unsigned short type ); diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 7f73742fe42..6eec6552c78 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -163,6 +163,32 @@ static void register_extension( char *list, size_t size, const char *name ) } }
+static pthread_mutex_t drawables_lock = PTHREAD_MUTEX_INITIALIZER; +static struct list drawables = LIST_INIT( drawables ); + +/* drawables_lock must be held */ +static void opengl_drawable_detach( struct opengl_drawable *drawable ) +{ + drawable->funcs->detach( drawable ); + list_remove( &drawable->entry ); + list_init( &drawable->entry ); +} + +void detach_opengl_drawables( HWND hwnd ) +{ + struct opengl_drawable *drawable, *next; + + pthread_mutex_lock( &drawables_lock ); + + LIST_FOR_EACH_ENTRY_SAFE( drawable, next, &drawables, struct opengl_drawable, entry ) + { + if (drawable->hwnd != hwnd) continue; + opengl_drawable_detach( drawable ); + } + + pthread_mutex_unlock( &drawables_lock ); +} + void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *funcs, int format, HWND hwnd, HDC hdc ) { struct opengl_drawable *drawable; @@ -176,6 +202,14 @@ void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *fun drawable->hwnd = hwnd; drawable->hdc = hdc;
+ if (!hwnd) list_init( &drawable->entry ); /* pbuffer, keep it unlinked */ + else + { + pthread_mutex_lock( &drawables_lock ); + list_add_tail( &drawables, &drawable->entry ); + pthread_mutex_unlock( &drawables_lock ); + } + TRACE( "created %s\n", debugstr_opengl_drawable( drawable ) ); return drawable; } @@ -193,6 +227,10 @@ void opengl_drawable_release( struct opengl_drawable *drawable )
if (!ref) { + pthread_mutex_lock( &drawables_lock ); + opengl_drawable_detach( drawable ); + pthread_mutex_unlock( &drawables_lock ); + drawable->funcs->destroy( drawable ); free( drawable ); } diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 352dc938b66..d0293aa0dc6 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5054,6 +5054,7 @@ LRESULT destroy_window( HWND hwnd ) window_surface_release( surface ); }
+ detach_opengl_drawables( hwnd ); vulkan_detach_surfaces( &vulkan_surfaces ); if (win->opengl_drawable) opengl_drawable_release( win->opengl_drawable ); user_driver->pDestroyWindow( hwnd ); @@ -5210,6 +5211,7 @@ void destroy_thread_windows(void) TRACE( "destroying %p\n", entry );
user_driver->pDestroyWindow( entry->handle ); + detach_opengl_drawables( win->handle ); if (win->opengl_drawable) opengl_drawable_release( win->opengl_drawable );
NtUserDestroyMenu( entry->menu ); diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c index 4637a04eec9..ff8f2a13027 100644 --- a/dlls/wineandroid.drv/opengl.c +++ b/dlls/wineandroid.drv/opengl.c @@ -108,6 +108,11 @@ static void android_drawable_destroy( struct opengl_drawable *base ) release_ioctl_window( gl->window ); }
+static void android_drawable_detach( struct opengl_drawable *base ) +{ + TRACE( "%s\n", debugstr_opengl_drawable( base ) ); +} + void update_gl_drawable( HWND hwnd ) { struct gl_drawable *old, *new; @@ -278,6 +283,7 @@ static struct opengl_driver_funcs android_driver_funcs = static const struct opengl_drawable_funcs android_drawable_funcs = { .destroy = android_drawable_destroy, + .detach = android_drawable_detach, .flush = android_drawable_flush, .swap = android_drawable_swap, }; diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index c71778f32d4..d1017fd8764 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -984,8 +984,6 @@ void ANDROID_DestroyWindow( HWND hwnd ) struct android_win_data *data;
if (!(data = get_win_data( hwnd ))) return; - - destroy_gl_drawable( hwnd ); free_win_data( data ); }
diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 9a28ec10b51..36cb0854acc 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -2074,6 +2074,10 @@ static void macdrv_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, make_context_current(context, FALSE); }
+static void macdrv_surface_detach(struct opengl_drawable *base) +{ + TRACE("%s\n", debugstr_opengl_drawable(base)); +}
static void macdrv_surface_flush(struct opengl_drawable *base, UINT flags) { @@ -2374,6 +2378,10 @@ static void macdrv_pbuffer_destroy(struct opengl_drawable *base) CGLReleasePBuffer(gl->pbuffer); }
+static void macdrv_pbuffer_detach(struct opengl_drawable *base) +{ +} + static void macdrv_pbuffer_flush(struct opengl_drawable *base, UINT flags) { } @@ -3021,6 +3029,7 @@ static const struct opengl_driver_funcs macdrv_driver_funcs = static const struct opengl_drawable_funcs macdrv_surface_funcs = { .destroy = macdrv_surface_destroy, + .detach = macdrv_surface_detach, .flush = macdrv_surface_flush, .swap = macdrv_surface_swap, }; @@ -3028,6 +3037,7 @@ static const struct opengl_drawable_funcs macdrv_surface_funcs = static const struct opengl_drawable_funcs macdrv_pbuffer_funcs = { .destroy = macdrv_pbuffer_destroy, + .detach = macdrv_pbuffer_detach, .flush = macdrv_pbuffer_flush, .swap = macdrv_pbuffer_swap, }; diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index ede1b5982fa..9c239faa340 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -144,6 +144,20 @@ static void wayland_drawable_destroy(struct opengl_drawable *base) } }
+static void wayland_drawable_detach(struct opengl_drawable *base) +{ + struct wayland_gl_drawable *gl = impl_from_opengl_drawable(base), *old; + HWND hwnd = base->hwnd; + + TRACE("%s\n", debugstr_opengl_drawable(base)); + + pthread_mutex_lock(&gl_object_mutex); + if ((old = find_drawable(hwnd, 0)) && old == gl) list_remove(&gl->entry); + pthread_mutex_unlock(&gl_object_mutex); + + if (gl) opengl_drawable_release(&gl->base); +} + static inline BOOL is_onscreen_format(int format) { return format > 0 && format <= egl->config_count; @@ -477,6 +491,7 @@ static struct opengl_driver_funcs wayland_driver_funcs = static const struct opengl_drawable_funcs wayland_drawable_funcs = { .destroy = wayland_drawable_destroy, + .detach = wayland_drawable_detach, .flush = wayland_drawable_flush, .swap = wayland_drawable_swap, }; @@ -505,14 +520,6 @@ UINT WAYLAND_OpenGLInit(UINT version, const struct opengl_funcs *opengl_funcs, c return STATUS_SUCCESS; }
-/********************************************************************** - * wayland_destroy_gl_drawable - */ -void wayland_destroy_gl_drawable(HWND hwnd) -{ - wayland_update_gl_drawable(hwnd, NULL); -} - /********************************************************************** * wayland_resize_gl_drawable */ @@ -534,10 +541,6 @@ UINT WAYLAND_OpenGLInit(UINT version, const struct opengl_funcs *opengl_funcs, c return STATUS_NOT_IMPLEMENTED; }
-void wayland_destroy_gl_drawable(HWND hwnd) -{ -} - void wayland_resize_gl_drawable(HWND hwnd) { } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index e0be6970b05..e31be8d294a 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -416,7 +416,6 @@ void wayland_data_device_init(void); * OpenGL */
-void wayland_destroy_gl_drawable(HWND hwnd); void wayland_resize_gl_drawable(HWND hwnd);
/********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index dbcbd90be00..8077767a26f 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -403,7 +403,6 @@ void WAYLAND_DestroyWindow(HWND hwnd)
if (!(data = wayland_win_data_get(hwnd))) return; wayland_win_data_destroy(data); - wayland_destroy_gl_drawable(hwnd); }
/*********************************************************************** diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 7f0b3215ffd..569cb29943a 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1020,18 +1020,18 @@ void sync_gl_drawable( HWND hwnd ) }
-/*********************************************************************** - * destroy_gl_drawable - */ -void destroy_gl_drawable( HWND hwnd ) +static void x11drv_surface_detach( struct opengl_drawable *base ) { - struct gl_drawable *gl; + struct gl_drawable *gl = impl_from_opengl_drawable( base ), *current; + HWND hwnd = base->hwnd; + + TRACE( "%s\n", debugstr_opengl_drawable( base ) );
pthread_mutex_lock( &context_mutex ); - if (!XFindContext( gdi_display, (XID)hwnd, gl_hwnd_context, (char **)&gl )) + if (!XFindContext( gdi_display, (XID)hwnd, gl_hwnd_context, (char **)¤t ) && current == gl) { XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context ); - opengl_drawable_release( &gl->base ); + opengl_drawable_release( ¤t->base ); } pthread_mutex_unlock( &context_mutex ); } @@ -1480,6 +1480,10 @@ static void x11drv_pbuffer_destroy( struct opengl_drawable *base ) pglXDestroyPbuffer( gdi_display, gl->drawable ); }
+static void x11drv_pbuffer_detach( struct opengl_drawable *base ) +{ +} + static void x11drv_pbuffer_flush( struct opengl_drawable *base, UINT flags ) { } @@ -1653,6 +1657,7 @@ static const struct opengl_driver_funcs x11drv_driver_funcs = static const struct opengl_drawable_funcs x11drv_surface_funcs = { .destroy = x11drv_surface_destroy, + .detach = x11drv_surface_detach, .flush = x11drv_surface_flush, .swap = x11drv_surface_swap, }; @@ -1660,6 +1665,7 @@ static const struct opengl_drawable_funcs x11drv_surface_funcs = static const struct opengl_drawable_funcs x11drv_pbuffer_funcs = { .destroy = x11drv_pbuffer_destroy, + .detach = x11drv_pbuffer_detach, .flush = x11drv_pbuffer_flush, .swap = x11drv_pbuffer_swap, }; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 726478ff040..e68d8d9d552 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2551,7 +2551,6 @@ void X11DRV_DestroyWindow( HWND hwnd ) XDeleteContext( gdi_display, (XID)hwnd, win_data_context ); release_win_data( data ); free( data ); - destroy_gl_drawable( hwnd ); }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 421d394de20..47a413974f5 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -682,7 +682,6 @@ extern Window X11DRV_get_whole_window( HWND hwnd ); extern Window get_dummy_parent(void);
extern void sync_gl_drawable( HWND hwnd ); -extern void destroy_gl_drawable( HWND hwnd );
extern BOOL window_is_reparenting( HWND hwnd ); extern BOOL window_should_take_focus( HWND hwnd, Time time ); diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index c319d93ce27..9e914e98d38 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -131,6 +131,8 @@ struct opengl_drawable; struct opengl_drawable_funcs { void (*destroy)( struct opengl_drawable *iface ); + /* detach the drawable from its window, called from window message thread */ + void (*detach)( struct opengl_drawable *drawable ); /* flush and update the drawable front buffer, called from render thread */ void (*flush)( struct opengl_drawable *iface, UINT flags ); /* swap and present the drawable buffers, called from render thread */ @@ -144,6 +146,7 @@ struct opengl_drawable_funcs struct opengl_drawable { const struct opengl_drawable_funcs *funcs; + struct list entry; /* entry in win32u managed list */ LONG ref;
int format; /* pixel format of the drawable */