[PATCH v3 0/7] MR11161: Draft: opengl32: Implement wglShareLists on the PE side and share all unix contexts together.
This makes wglShareLists implementation correct, and it makes our life easier on the unix side, for the framebuffer surface and any other GL related work, as we don't need to care as much about context switches, and allowing to use unix-only contexts to manipulate rendered images. -- v3: win32u: Get rid of opengl_drawable set_context callback. opengl32: Implement wglShareLists on the PE side. opengl32: Keep a global WOW64 buffer storage map. win32u: Share all unix-side GL contexts with a global context. opengl32: Ensure a context is current before display lists destruction. win32u: Create a default thread context when binding NULL. opengl32: Unset current context on thread detach. https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/wgl.c | 28 ++++++++++++++++++---------- dlls/win32u/opengl.c | 17 +++++++++++++++++ dlls/win32u/sysparams.c | 1 + dlls/win32u/win32u_private.h | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index aac6d7965e4..fc9bc94d6cd 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -546,6 +546,12 @@ static void free_client_context( struct handle_entry *ptr ) free( context ); } +static struct context *get_current_context(void) +{ + HGLRC current = NtCurrentTeb()->glCurrentRC; + return current ? context_from_handle( current ) : NULL; +} + void set_gl_error( GLenum error ) { struct opengl_client_context *context; @@ -564,7 +570,7 @@ void put_context_objects( enum object_type type, UINT n, GLuint *handles ) struct object_table *table; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return; + if (!(ctx = get_current_context())) return; if (!(table = get_object_table( ctx, type, TRUE ))) return; AcquireSRWLockExclusive( &table->lock ); @@ -578,7 +584,7 @@ GLuint put_context_object_range( enum object_type type, UINT range, GLuint base struct context *ctx; GLuint first; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return base; + if (!(ctx = get_current_context())) return base; if (!(table = get_object_table( ctx, type, TRUE ))) return base; AcquireSRWLockExclusive( &table->lock ); @@ -612,7 +618,7 @@ BOOL alloc_context_objects( enum object_type type, UINT n, const GLuint *handles struct object_table *table; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return TRUE; + if (!(ctx = get_current_context())) return TRUE; if (!(table = get_object_table( ctx, type, FALSE ))) return TRUE; /* only allow explicit allocation in some cases, use host allocated ids directly in that case */ @@ -658,7 +664,7 @@ GLuint *del_context_objects( enum object_type type, UINT n, GLuint *handles ) struct object_table *table; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return handles; + if (!(ctx = get_current_context())) return handles; if (!(table = get_object_table( ctx, type, FALSE ))) return handles; AcquireSRWLockExclusive( &table->lock ); @@ -673,7 +679,7 @@ GLuint *map_context_objects( enum object_type type, UINT n, GLuint *handles ) struct object_table *table; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return handles; + if (!(ctx = get_current_context())) return handles; if (!(table = get_object_table( ctx, type, FALSE ))) return handles; AcquireSRWLockShared( &table->lock ); @@ -777,7 +783,7 @@ static BOOL map_client_objects( enum object_type type, GLuint host_id, GLuint *r struct context *ctx; if (!host_id || type == OBJ_TYPE_COUNT) return FALSE; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return FALSE; + if (!(ctx = get_current_context())) return FALSE; if (!(table = get_object_table( ctx, type, FALSE ))) return FALSE; AcquireSRWLockShared( &table->lock ); @@ -1875,7 +1881,7 @@ PROC WINAPI wglGetProcAddress( LPCSTR name ) const enum opengl_extension *ext; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + if (!(ctx = get_current_context())) return NULL; if (!(func = get_function_entry( name ))) { @@ -2503,7 +2509,7 @@ static GLsync sync_from_handle( GLsync handle ) struct handle_entry *ptr; struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + if (!(ctx = get_current_context())) return NULL; if (!(ptr = get_handle_ptr( &ctx->lists->syncs, handle ))) return NULL; return ptr->user_data; } @@ -2621,7 +2627,7 @@ BOOL get_integer( GLenum name, GLuint index, GLint value, GLint *data ) { struct context *ctx; - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return FALSE; + if (!(ctx = get_current_context())) return FALSE; switch (name) { @@ -2658,7 +2664,7 @@ const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ) TRACE( "name %d, index %d\n", name, index ); - if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + if (!(ctx = get_current_context())) return NULL; switch (name) { @@ -2785,6 +2791,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { .call_gl_debug_message_callback = (UINT_PTR)call_gl_debug_message_callback, }; + struct context *context; NTSTATUS status; switch(reason) @@ -2814,6 +2821,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) #endif /* fallthrough */ case DLL_THREAD_DETACH: + if ((context = get_current_context())) context->base.current_tid = 0; free( NtCurrentTeb()->glReserved1[WINE_GL_RESERVED_FORMATS_PTR] ); return TRUE; } diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 3d03b41fc24..eeb29682e55 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -2830,3 +2830,20 @@ BOOL get_opengl_gpus( struct list *gpus ) return TRUE; } + +void cleanup_opengl_thread(void) +{ + struct opengl_context *context = NtCurrentTeb()->glContext; + + /* unset current context, this is sometimes missing from host drivers and leaks memory */ + if (context && context_unset_current( context )) + { + struct opengl_drawable *draw = NULL, *read = NULL; + + context_exchange_drawables( context, &draw, &read ); + if (draw->client) set_window_opengl_drawable( draw->client->hwnd, draw, FALSE ); + opengl_drawable_release( draw ); + if (read->client) set_window_opengl_drawable( read->client->hwnd, read, FALSE ); + opengl_drawable_release( read ); + } +} diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index f0cff127b26..239d13df6cc 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -7467,6 +7467,7 @@ static void thread_detach(void) free( thread_info->rawinput ); cleanup_imm_thread(); + cleanup_opengl_thread(); NtClose( thread_info->server_queue ); if (thread_info->idle_event) NtClose( thread_info->idle_event ); free( thread_info->session_data ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index be303ae4d13..5914f1c689f 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -229,6 +229,7 @@ extern NTSTATUS d3dkmt_destroy_sync( D3DKMT_HANDLE local ); /* opengl.c */ extern BOOL get_opengl_gpus( struct list *gpus ); +extern void cleanup_opengl_thread(void); /* winstation.c */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/opengl.c | 53 ++++++++++++++++++++++++++++++++++-- dlls/winemac.drv/opengl.c | 5 ++++ dlls/winex11.drv/opengl.c | 24 ++++++++++++++++ include/wine/opengl_driver.h | 1 + 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 978700a37aa..dc14811ce86 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -127,6 +127,7 @@ struct user_thread_info DWORD clipping_reset; /* time when clipping was last reset */ struct session_thread_data *session_data; /* shared session thread data */ struct mouse_tracking_info *mouse_tracking_info; /* NtUserTrackMouseEvent handling */ + struct opengl_thread_data *opengl_data; /* OpenGL private thread data */ }; extern struct user_thread_info *get_user_thread_info(void); diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index eeb29682e55..a3666665889 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -39,6 +39,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(wgl); +struct opengl_thread_data +{ + void *null_context; /* dummy context when no client context is active */ + struct opengl_drawable *null_surface; /* dummy surface when no client context is active */ +}; + +static struct opengl_thread_data *get_opengl_thread_data(void) +{ + struct user_thread_info *info = get_user_thread_info(); + struct opengl_thread_data *data; + + if ((data = info->opengl_data)) return data; + return (info->opengl_data = calloc( 1, sizeof(*data) )); +} + struct pbuffer { struct opengl_drawable *drawable; @@ -183,6 +198,30 @@ static BOOL opengl_drawable_swap( struct opengl_drawable *drawable ) return drawable->funcs->swap( drawable ); } +static BOOL make_null_context_current(void) +{ + struct opengl_thread_data *data = get_opengl_thread_data(); + int format; + + if (!data->null_context) + { + for (format = 1; format <= formats_count; format++) + { + struct wgl_pixel_format *desc = pixel_formats + format - 1; + if (!(desc->pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; + if (desc->pfd.iPixelType != PFD_TYPE_RGBA) continue; + if (desc->pfd.cColorBits < 24) continue; + break; + } + + if (format > formats_count) return FALSE; + driver_funcs->p_context_create( format, NULL, NULL, &data->null_context ); + if (driver_funcs->p_null_surface_create) driver_funcs->p_null_surface_create( format, &data->null_surface ); + } + + return driver_funcs->p_make_current( data->null_surface, data->null_surface, data->null_context ); +} + #ifdef SONAME_LIBEGL struct framebuffer_surface @@ -847,7 +886,8 @@ static BOOL egldrv_make_current( struct opengl_drawable *draw, struct opengl_dra TRACE( "draw %s, read %s, context %p\n", debugstr_opengl_drawable( draw ), debugstr_opengl_drawable( read ), context ); - return funcs->p_eglMakeCurrent( egl->display, context ? draw->surface : EGL_NO_SURFACE, context ? read->surface : EGL_NO_SURFACE, context ); + if (!context) return funcs->p_eglMakeCurrent( egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, NULL ); + return funcs->p_eglMakeCurrent( egl->display, draw ? draw->surface : EGL_NO_SURFACE, read ? read->surface : EGL_NO_SURFACE, context ); } static void egldrv_pbuffer_destroy( struct opengl_drawable *drawable ) @@ -1779,7 +1819,7 @@ static BOOL context_unset_current( struct opengl_context *context ) opengl_drawable_set_context( old_read, NULL ); if (old_read != old_draw) opengl_drawable_set_context( old_draw, NULL ); - if (driver_funcs->p_make_current( NULL, NULL, NULL )) return TRUE; + if (make_null_context_current()) return TRUE; opengl_drawable_set_context( old_read, context ); if (old_read != old_draw) opengl_drawable_set_context( old_draw, context ); @@ -1909,7 +1949,7 @@ static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC c { struct opengl_drawable *draw = NULL, *read = NULL; - if (!(context = prev_context)) return TRUE; + if (!(context = prev_context)) return make_null_context_current(); if (!context_unset_current( context )) return FALSE; NtCurrentTeb()->glContext = NULL; @@ -2834,6 +2874,8 @@ BOOL get_opengl_gpus( struct list *gpus ) void cleanup_opengl_thread(void) { struct opengl_context *context = NtCurrentTeb()->glContext; + struct user_thread_info *info = get_user_thread_info(); + struct opengl_thread_data *data; /* unset current context, this is sometimes missing from host drivers and leaks memory */ if (context && context_unset_current( context )) @@ -2846,4 +2888,9 @@ void cleanup_opengl_thread(void) if (read->client) set_window_opengl_drawable( read->client->hwnd, read, FALSE ); opengl_drawable_release( read ); } + + if (!(data = info->opengl_data)) return; + if (data->null_context) driver_funcs->p_context_destroy( data->null_context ); + if (data->null_surface) opengl_drawable_release( data->null_surface ); + free( data ); } diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 0af1d3f7192..2c18bce7635 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -2272,6 +2272,11 @@ static BOOL macdrv_make_current(struct opengl_drawable *draw_base, struct opengl NtCurrentTeb()->glReserved2 = NULL; return TRUE; } + if (!draw || !read) + { + CGLSetCurrentContext(context->cglcontext); + return TRUE; + } context->read_hwnd = context->draw_hwnd = NULL; context->read_view = context->draw_view = NULL; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 56c22ab7ee7..ebee3bb3e86 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1344,6 +1344,29 @@ static UINT x11drv_pbuffer_bind( HDC hdc, struct opengl_drawable *base, GLenum b return -1; /* use default implementation */ } +static BOOL x11drv_null_surface_create( int format, struct opengl_drawable **drawable ) +{ + const struct glx_pixel_format *fmt = glx_pixel_format_from_format( format ); + int glx_attribs[7], count = 0; + struct gl_drawable *gl; + + glx_attribs[count++] = GLX_PBUFFER_WIDTH; + glx_attribs[count++] = 1; + glx_attribs[count++] = GLX_PBUFFER_HEIGHT; + glx_attribs[count++] = 1; + glx_attribs[count++] = 0; + + if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_pbuffer_funcs, format, NULL ))) return FALSE; + if (!(gl->drawable = pglXCreatePbuffer( gdi_display, fmt->fbconfig, glx_attribs ))) + { + opengl_drawable_release( &gl->base ); + return FALSE; + } + + *drawable = &gl->base; + return TRUE; +} + static BOOL X11DRV_wglQueryCurrentRendererIntegerWINE( GLenum attribute, GLuint *value ) { return pglXQueryCurrentRendererIntegerMESA( attribute, value ); @@ -1520,6 +1543,7 @@ static struct opengl_driver_funcs x11drv_driver_funcs = .p_pbuffer_create = x11drv_pbuffer_create, .p_pbuffer_updated = x11drv_pbuffer_updated, .p_pbuffer_bind = x11drv_pbuffer_bind, + .p_null_surface_create = x11drv_null_surface_create, }; static const struct opengl_drawable_funcs x11drv_surface_funcs = diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index af745e038a6..79babe18ff3 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -252,6 +252,7 @@ struct opengl_driver_funcs GLint max_level, GLsizei *width, GLsizei *height, struct opengl_drawable **drawable ); BOOL (*p_pbuffer_updated)( HDC hdc, struct opengl_drawable *drawable, GLenum cube_face, GLint mipmap_level ); UINT (*p_pbuffer_bind)( HDC hdc, struct opengl_drawable *drawable, GLenum buffer ); + BOOL (*p_null_surface_create)( int format, struct opengl_drawable **drawable ); }; #endif /* WINE_UNIX_LIB */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/unix_wgl.c | 6 +++--- dlls/opengl32/wgl.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index fbf5654aeaa..fcaa5345c2d 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1363,7 +1363,7 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, c BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC client_context ) { - struct context *ctx, *prev = get_current_context( teb, NULL, NULL ); + struct context *ctx; if (client_context) { @@ -1372,12 +1372,12 @@ BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC if (!funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, client_context )) return FALSE; make_context_current( teb, funcs, draw_hdc, read_hdc, client_context, ctx ); } - else if (prev) + else { const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_wglMakeContextCurrentARB( NULL, NULL, NULL )) return FALSE; - teb->glTable = &null_opengl_funcs; } + return TRUE; } diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index fc9bc94d6cd..9172709b1e9 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -919,6 +919,8 @@ BOOL WINAPI wglDeleteContext( HGLRC handle ) if ((status = UNIX_CALL( wglDeleteContext, &args ))) WARN( "wglDeleteContext returned %#lx\n", status ); if (status || !args.ret) return FALSE; + /* make sure there's a (dummy) context before releasing and destroying display list objects */ + if (!teb->glCurrentRC) wglMakeCurrent( NULL, NULL ); free_client_context( ptr ); return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> This also requires to explicitly destroy objects when display lists are destroyed. --- dlls/opengl32/tests/opengl.c | 20 +++++++++---------- dlls/opengl32/unix_wgl.c | 4 ++-- dlls/opengl32/wgl.c | 31 ++++++++++++++++++++++++++++-- dlls/win32u/opengl.c | 37 +++++++++++++++++++++++++----------- include/wine/opengl_driver.h | 4 ++-- 5 files changed, 68 insertions(+), 28 deletions(-) diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index f4809b9e915..89d6d072f48 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -1982,7 +1982,7 @@ static void test_sharelists(HDC winhdc) ok_ret( TRUE, wglShareLists( ctx1, ctx3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* object 1 is now valid there as well */ - todo_wine ok_ret( TRUE, test->exists( obj1 ) ); + ok_ret( TRUE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* object 1 is still valid in ctx2 */ @@ -2052,21 +2052,19 @@ static void test_sharelists(HDC winhdc) ok_u4( obj3, ==, 3 ); ok_ret( TRUE, wglMakeCurrent( winhdc, ctx3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine ok_ret( TRUE, test->exists( obj1 ) ); + ok_ret( TRUE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, test->exists( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine ok_ret( TRUE, test->exists( obj3 ) ); + ok_ret( TRUE, test->exists( obj3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* test deleting objects in shared contexts */ delete_object( test->type, obj1 ); - todo_wine_if( test->type == OBJ_PROGRAM_OBJECT || test->type == OBJ_PROGRAM_OBJECT_ARB || - test->type == OBJ_SHADER_OBJECT || test->type == OBJ_SHADER_OBJECT_ARB ) ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( TRUE, wglMakeCurrent( winhdc, ctx2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine_if( i >= 14 ) ok_ret( FALSE, test->exists( obj1 ) ); + ok_ret( FALSE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, test->exists( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); @@ -2077,7 +2075,7 @@ static void test_sharelists(HDC winhdc) ok_ret( TRUE, wglDeleteContext( ctx3 ) ); /* objects are still valid after shared context destruction */ - todo_wine_if( i >= 14 ) ok_ret( FALSE, test->exists( obj1 ) ); + ok_ret( FALSE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, test->exists( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); @@ -2138,7 +2136,7 @@ static void test_sharelists(HDC winhdc) ok_ret( TRUE, wglShareLists( ctx1, ctx3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* object 1 is now valid there as well */ - todo_wine ok_ret( TRUE, ext.glIsSync( obj1 ) ); + ok_ret( TRUE, ext.glIsSync( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* object 1 is still valid in ctx2 */ @@ -2211,16 +2209,16 @@ static void test_sharelists(HDC winhdc) todo_wine ok_ptr( obj3, ==, (GLsync)3 ); ok_ret( TRUE, wglMakeCurrent( winhdc, ctx3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine ok_ret( TRUE, ext.glIsSync( obj1 ) ); + ok_ret( TRUE, ext.glIsSync( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, ext.glIsSync( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine ok_ret( TRUE, ext.glIsSync( obj3 ) ); + ok_ret( TRUE, ext.glIsSync( obj3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); /* test deleting objects in shared contexts */ ext.glDeleteSync( obj1 ); - todo_wine ok_ret( GL_NO_ERROR, glGetError() ); + ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( TRUE, wglMakeCurrent( winhdc, ctx2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, ext.glIsSync( obj1 ) ); diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index fcaa5345c2d..c1a21c58245 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -439,7 +439,7 @@ static struct context *update_context( TEB *teb, HGLRC client_context, struct co if (ctx->share == (HGLRC)-1) return ctx; /* not re-shared */ share = ctx->share ? get_updated_context( teb, ctx->share ) : NULL; - if (!funcs->p_context_reset( &ctx->base, share ? &share->base : NULL, ctx->attribs )) + if (!funcs->p_context_reset( &ctx->base, ctx->attribs )) { WARN( "Failed to re-create context for wglShareLists\n" ); return ctx; @@ -1350,7 +1350,7 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, c } } - if (!(funcs->p_context_create( &context->base, hdc, shared ? &shared->base : NULL, attribs ))) + if (!(funcs->p_context_create( &context->base, hdc, attribs ))) { free_context( context ); return 0; diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 9172709b1e9..dde1914191a 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -418,18 +418,41 @@ static GLuint create_object( enum object_type type ) return 0; } +static void destroy_object( enum object_type type, GLuint object ) +{ + switch (type) + { + case OBJ_TYPE_BUFFER: { MAKE_OBJECT_CALL( glDeleteBuffers, .n = 1, .buffers = &object ); return; } + case OBJ_TYPE_DISPLAY_LIST: { MAKE_OBJECT_CALL( glDeleteLists, .range = 1, .list = object ); return; } + case OBJ_TYPE_FRAMEBUFFER: { MAKE_OBJECT_CALL( glDeleteFramebuffers, .n = 1, .framebuffers = &object ); return; } + case OBJ_TYPE_MEMORY: { MAKE_OBJECT_CALL( glDeleteMemoryObjectsEXT, .n = 1, .memoryObjects = &object ); return; } + case OBJ_TYPE_PATH: { MAKE_OBJECT_CALL( glDeletePathsNV, .range = 1, .path = object ); return; } + case OBJ_TYPE_PROGRAM: { MAKE_OBJECT_CALL( glDeleteProgramsARB, .n = 1, .programs = &object ); return; } + case OBJ_TYPE_RENDERBUFFER: { MAKE_OBJECT_CALL( glDeleteRenderbuffers, .n = 1, .renderbuffers = &object ); return; } + case OBJ_TYPE_SAMPLER: { MAKE_OBJECT_CALL( glDeleteSamplers, .count = 1, .samplers = &object ); return; } + case OBJ_TYPE_SEMAPHORE: { MAKE_OBJECT_CALL( glDeleteSemaphoresEXT, .n = 1, .semaphores = &object ); return; } + case OBJ_TYPE_SHADER: { MAKE_OBJECT_CALL( glDeleteObjectARB, .obj = object ); return; } + case OBJ_TYPE_SHADER_ATI: { MAKE_OBJECT_CALL( glDeleteFragmentShaderATI, .id = object ); return; } + case OBJ_TYPE_SHADER_EXT: { MAKE_OBJECT_CALL( glDeleteVertexShaderEXT, .id = object ); return; } + case OBJ_TYPE_TEXTURE: { MAKE_OBJECT_CALL( glDeleteTextures, .n = 1, .textures = &object ); return; } + case OBJ_TYPE_COUNT: return; + } +} + #undef MAKE_OBJECT_CALL static void destroy_host_object( struct object_table *table, GLuint host_id, GLuint client_id ) { - WARN( "Leaking %s client %#x, host %#x\n", debugstr_object_type( table->type ), client_id, host_id ); + WARN( "Destroying %s client %#x, host %#x\n", debugstr_object_type( table->type ), client_id, host_id ); + destroy_object( table->type, host_id ); } static void destroy_host_shader( struct object_table *table, GLuint host_id, GLuint client_id ) { GLuint *object; if (!(object = find_object_id( table->client_ids, host_id )) || !(client_id = *object)) return; - WARN( "Leaking %s client %#x, host %#x\n", debugstr_object_type( table->type ), client_id, host_id ); + WARN( "Destroying %s client %#x, host %#x\n", debugstr_object_type( table->type ), client_id, host_id ); + destroy_object( table->type, host_id ); } static void free_object_table( struct object_table *table ) @@ -475,6 +498,8 @@ static struct display_lists *display_lists_acquire( struct display_lists *lists static void display_lists_release( struct display_lists *lists ) { + struct glDeleteSync_params delete_sync = { .teb = NtCurrentTeb() }; + if (InterlockedDecrement( &lists->refcount )) return; for (UINT i = 0; i < OBJ_TYPE_COUNT; i++) @@ -485,6 +510,8 @@ static void display_lists_release( struct display_lists *lists ) struct handle_entry *entry = lists->syncs.handles + i; if (LOWORD(entry->handle) == 0xffff) continue; WARN( "Leaking sync client %#x, host %p\n", entry->handle, entry->user_data ); + delete_sync.sync = entry->user_data; + UNIX_CALL( glDeleteSync, &delete_sync ); free( entry->user_data ); } diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index a3666665889..c7bfde36a1e 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -77,6 +77,7 @@ static const struct opengl_driver_funcs nulldrv_funcs, *driver_funcs = &nulldrv_ static struct list devices_egl = LIST_INIT( devices_egl ); static struct egl_platform display_egl; static struct opengl_funcs display_funcs; +static void *global_context; static BOOLEAN global_extensions[GL_EXTENSION_COUNT]; static struct wgl_pixel_format *pixel_formats; @@ -215,7 +216,7 @@ static BOOL make_null_context_current(void) } if (format > formats_count) return FALSE; - driver_funcs->p_context_create( format, NULL, NULL, &data->null_context ); + driver_funcs->p_context_create( format, global_context, NULL, &data->null_context ); if (driver_funcs->p_null_surface_create) driver_funcs->p_null_surface_create( format, &data->null_surface ); } @@ -1238,6 +1239,11 @@ static void init_device_info( struct egl_platform *egl, const struct opengl_func TRACE( " - device_uuid: %s\n", debugstr_guid(&egl->device_uuid) ); TRACE( " - driver_uuid: %s\n", debugstr_guid(&egl->driver_uuid) ); + if (egl == &display_egl) + { + if (core_context) core_context = InterlockedExchangePointer( &global_context, core_context ); + else if (compat_context) compat_context = InterlockedExchangePointer( &global_context, compat_context ); + } if (compat_context) funcs->p_eglDestroyContext( egl->display, compat_context ); if (core_context) funcs->p_eglDestroyContext( egl->display, core_context ); @@ -1923,7 +1929,7 @@ static void push_internal_context( struct opengl_context *context, struct opengl if (!context->internal_context) { - driver_funcs->p_context_create( format, context->driver_private, NULL, &context->internal_context ); + driver_funcs->p_context_create( format, global_context, NULL, &context->internal_context ); if (!context->internal_context) ERR( "Failed to create internal context\n" ); } @@ -2303,12 +2309,11 @@ static int get_window_swap_interval( HWND hwnd ) return interval; } -static BOOL win32u_context_create( struct opengl_context *context, HDC hdc, struct opengl_context *share, const int *attribs ) +static BOOL win32u_context_create( struct opengl_context *context, HDC hdc, const int *attribs ) { - void *share_private = share ? share->driver_private : NULL; int format; - TRACE( "context %p, hdc %p, share %p, attribs %p\n", context, hdc, share, attribs ); + TRACE( "context %p, hdc %p, attribs %p\n", context, hdc, attribs ); if ((format = get_dc_pixel_format( hdc )) <= 0 && (format = get_window_pixel_format( NtUserWindowFromDC( hdc ) )) <= 0) @@ -2317,7 +2322,7 @@ static BOOL win32u_context_create( struct opengl_context *context, HDC hdc, stru else RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return FALSE; } - if (!driver_funcs->p_context_create( format, share_private, attribs, &context->driver_private )) + if (!driver_funcs->p_context_create( format, global_context, attribs, &context->driver_private )) { WARN( "Failed to create driver context for context %p\n", context ); return FALSE; @@ -2347,14 +2352,12 @@ static BOOL win32u_context_destroy( struct opengl_context *context ) return TRUE; } -static BOOL win32u_context_reset( struct opengl_context *context, struct opengl_context *share, const int *attribs ) +static BOOL win32u_context_reset( struct opengl_context *context, const int *attribs ) { - void *share_private = share ? share->driver_private : NULL; - - TRACE( "context %p, share %p, attribs %p\n", context, share, attribs ); + TRACE( "context %p, attribs %p\n", context, attribs ); if (!win32u_context_destroy( context )) return FALSE; - return driver_funcs->p_context_create( context->format, share_private, attribs, &context->driver_private ); + return driver_funcs->p_context_create( context->format, global_context, attribs, &context->driver_private ); } static BOOL flush_memory_pbuffer( void (*flush)(void) ) @@ -2829,6 +2832,18 @@ static void display_funcs_init(void) LIST_FOR_EACH_ENTRY_SAFE( egl, next, &devices_egl, struct egl_platform, entry ) init_device_info( egl, &display_funcs ); } + + if (!global_context) + { + for (int format = 1; format <= formats_count; format++) + { + struct wgl_pixel_format *desc = pixel_formats + format - 1; + if (!(desc->pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; + if (desc->pfd.iPixelType != PFD_TYPE_RGBA) continue; + if (desc->pfd.cColorBits < 24) continue; + if (driver_funcs->p_context_create( format, NULL, NULL, &global_context )) break; + } + } } /*********************************************************************** diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 79babe18ff3..7c138d37e64 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -146,9 +146,9 @@ struct opengl_funcs void (*p_get_pixel_formats)( struct wgl_pixel_format *formats, UINT max_formats, UINT *num_formats, UINT *num_onscreen_formats ); BOOL (*p_query_renderer)( UINT attribute, void *value ); BOOL (*p_context_flush)( struct opengl_context *context, void (*flush)(void), UINT flags ); - BOOL (*p_context_create)( struct opengl_context *context, HDC hdc, struct opengl_context *share, const int *attribs ); + BOOL (*p_context_create)( struct opengl_context *context, HDC hdc, const int *attribs ); BOOL (*p_context_destroy)( struct opengl_context *context ); - BOOL (*p_context_reset)( struct opengl_context *context, struct opengl_context *share, const int *attribs ); + BOOL (*p_context_reset)( struct opengl_context *context, const int *attribs ); BOOL (*p_pbuffer_create)( HDC hdc, int format, int width, int height, const int *attribs, HPBUFFERARB client_pbuffer ); void *egl_handle; }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> Buffer names on the unix side are now valid across contexts. --- dlls/opengl32/unix_wgl.c | 56 ++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index c1a21c58245..2abeda46196 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -187,6 +187,7 @@ struct vk_device static ULONG_PTR zero_bits; +static struct buffers *buffers; static const struct vulkan_funcs *vk_funcs; static VkInstance vk_instance; static PFN_vkDestroyInstance p_vkDestroyInstance; @@ -409,7 +410,7 @@ void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) free( buffer ); } -static void release_buffers( const struct opengl_funcs *funcs, struct buffers *buffers ) +static void release_buffers( const struct opengl_funcs *funcs ) { struct buffer *buffer, *next; @@ -418,6 +419,18 @@ static void release_buffers( const struct opengl_funcs *funcs, struct buffers *b RB_FOR_EACH_ENTRY_DESTRUCTOR( buffer, next, &buffers->map, struct buffer, entry ) free_buffer( funcs, buffer ); free( buffers ); + buffers = NULL; +} + +static struct buffers *acquire_buffers(void) +{ + if (buffers) buffers->ref++; + else if ((buffers = malloc( sizeof(*buffers )))) + { + buffers->ref = 1; + rb_init( &buffers->map, compare_buffer_name ); + } + return buffers; } static struct context *context_from_client_context( HGLRC client_context ) @@ -433,23 +446,15 @@ static struct context *update_context( TEB *teb, HGLRC client_context, struct co { struct opengl_client_context *client = opengl_client_context_from_client( client_context ); const struct opengl_funcs *funcs = get_context_funcs( client_context ); - struct context *share; if (client->current_tid) return ctx; /* currently in use */ if (ctx->share == (HGLRC)-1) return ctx; /* not re-shared */ - share = ctx->share ? get_updated_context( teb, ctx->share ) : NULL; if (!funcs->p_context_reset( &ctx->base, ctx->attribs )) { WARN( "Failed to re-create context for wglShareLists\n" ); return ctx; } - if (share && share->buffers) - { - release_buffers( funcs, ctx->buffers ); - ctx->buffers = share->buffers; - ctx->buffers->ref++; - } ctx->share = (HGLRC)-1; /* initial shared context */ copy_context_attributes( teb, client_context, ctx, client_context, ctx, ctx->used ); return ctx; @@ -869,7 +874,7 @@ static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) static PFN_vkGetPhysicalDeviceMemoryProperties p_vkGetPhysicalDeviceMemoryProperties; static PFN_vkGetPhysicalDeviceProperties2KHR p_vkGetPhysicalDeviceProperties2KHR; - if (ctx->buffers->vk_device) return TRUE; /* already initialized */ + if (buffers->vk_device) return TRUE; /* already initialized */ if (!client->extensions[GL_EXT_memory_object_win32] ) { TRACE( "GL_EXT_memory_object_win32 is not supported\n" ); @@ -930,7 +935,7 @@ static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) vk_device = RB_ENTRY_VALUE( entry, struct vk_device, entry ); if (!vk_device->vk_device) continue; /* known incompatible device */ TRACE( "Found existing device %p for uuid %s\n", vk_device, debugstr_guid(&vk_device->uuid) ); - ctx->buffers->vk_device = vk_device; + buffers->vk_device = vk_device; free( vk_physical_devices ); return TRUE; } @@ -1140,8 +1145,9 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD ctx->pixel_mode.read_buffer = ctx->base.draw->doublebuffer ? GL_BACK : GL_FRONT; } -static void free_context( struct context *ctx ) +static void free_context( const struct opengl_funcs *funcs, struct context *ctx ) { + if (ctx->buffers) release_buffers( funcs ); free( ctx->wow64_version ); free( ctx->extensions ); free( ctx->attribs ); @@ -1153,7 +1159,7 @@ BOOL wrap_wglDeleteContext( TEB *teb, HGLRC client_context ) const struct opengl_funcs *funcs = get_context_funcs( client_context ); struct context *ctx = context_from_client_context( client_context ); funcs->p_context_destroy( &ctx->base ); - free_context( ctx ); + free_context( funcs, ctx ); return TRUE; } @@ -1318,7 +1324,7 @@ BOOL wrap_wglShareLists( TEB *teb, HGLRC client_src, HGLRC client_dst ) HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, const int *attribs, HGLRC client_context ) { const struct opengl_funcs *funcs = get_dc_funcs( hdc ); - struct context *context, *shared = get_updated_context( teb, client_shared ); + struct context *context; if (!funcs->p_context_create) return 0; if (!(context = calloc( 1, sizeof(*context) ))) @@ -1330,29 +1336,11 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, c context->share = (HGLRC)-1; /* initial shared context */ context->attribs = memdup_attribs( attribs ); - if (is_win64 && is_wow64()) - { - if (shared) - { - context->buffers = shared->buffers; - context->buffers->ref++; - } - else if (!(context->buffers = malloc( sizeof(*context->buffers )))) - { - free_context( context ); - return 0; - } - else - { - context->buffers->ref = 1; - context->buffers->vk_device = NULL; - rb_init( &context->buffers->map, compare_buffer_name ); - } - } + if (is_win64 && is_wow64()) context->buffers = acquire_buffers(); if (!(funcs->p_context_create( &context->base, hdc, attribs ))) { - free_context( context ); + free_context( funcs, context ); return 0; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> Getting rid of now unnecessary unix-side context recreation. --- dlls/opengl32/make_opengl | 2 +- dlls/opengl32/unix_thunks.c | 33 ------------------------ dlls/opengl32/unix_thunks.h | 1 - dlls/opengl32/unix_wgl.c | 50 +++--------------------------------- dlls/opengl32/unixlib.h | 9 ------- dlls/opengl32/wgl.c | 7 ----- dlls/win32u/opengl.c | 9 ------- include/wine/opengl_driver.h | 1 - 8 files changed, 4 insertions(+), 108 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 9bc9c0a1746..fcca05838bf 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -150,6 +150,7 @@ my %manual_win_functions = "wglMakeCurrent" => 1, "wglRealizeLayerPalette" => 1, "wglSetLayerPaletteEntries" => 1, + "wglShareLists" => 1, "wglSwapLayerBuffers" => 1, "wglUseFontBitmapsA" => 1, "wglUseFontBitmapsW" => 1, @@ -176,7 +177,6 @@ my %manual_win_thunks = "wglMakeContextCurrentARB" => 1, "wglQueryCurrentRendererStringWINE" => 1, "wglQueryRendererStringWINE" => 1, - "wglShareLists" => 1, "wglSwapBuffers" => 1, ); diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 74e1e0d5087..1d3f8a8dbd3 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -58,15 +58,6 @@ static NTSTATUS wgl_wglSetPixelFormat( void *args ) return STATUS_SUCCESS; } -static NTSTATUS wgl_wglShareLists( void *args ) -{ - struct wglShareLists_params *params = args; - const struct opengl_funcs *funcs = get_context_funcs( params->hrcSrvShare ); - if (!funcs || !funcs->p_wglShareLists) return STATUS_NOT_IMPLEMENTED; - params->ret = wrap_wglShareLists( params->teb, params->hrcSrvShare, params->hrcSrvSource ); - return STATUS_SUCCESS; -} - static NTSTATUS wgl_wglSwapBuffers( void *args ) { struct wglSwapBuffers_params *params = args; @@ -30537,7 +30528,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = wgl_wglDeleteContext, wgl_wglGetPixelFormat, wgl_wglSetPixelFormat, - wgl_wglShareLists, wgl_wglSwapBuffers, gl_glAccum, gl_glAlphaFunc, @@ -33699,22 +33689,6 @@ static NTSTATUS wow64_wgl_wglSetPixelFormat( void *args ) return STATUS_SUCCESS; } -static NTSTATUS wow64_wgl_wglShareLists( void *args ) -{ - struct - { - PTR32 teb; - PTR32 hrcSrvShare; - PTR32 hrcSrvSource; - BOOL ret; - } *params = args; - TEB *teb = get_teb64( params->teb ); - const struct opengl_funcs *funcs = get_context_funcs( ULongToPtr(params->hrcSrvShare) ); - if (!funcs || !funcs->p_wglShareLists) return STATUS_NOT_IMPLEMENTED; - params->ret = wrap_wglShareLists( teb, ULongToPtr(params->hrcSrvShare), ULongToPtr(params->hrcSrvSource) ); - return STATUS_SUCCESS; -} - static NTSTATUS wow64_wgl_wglSwapBuffers( void *args ) { struct @@ -86870,7 +86844,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = wow64_wgl_wglDeleteContext, wow64_wgl_wglGetPixelFormat, wow64_wgl_wglSetPixelFormat, - wow64_wgl_wglShareLists, wow64_wgl_wglSwapBuffers, wow64_gl_glAccum, wow64_gl_glAlphaFunc, @@ -89987,11 +89960,6 @@ static BOOL null_wglSetPixelFormat( HDC hdc, int ipfd, const PIXELFORMATDESCRIPT WARN( "unsupported\n" ); return 0; } -static BOOL null_wglShareLists( HGLRC hrcSrvShare, HGLRC hrcSrvSource ) -{ - WARN( "unsupported\n" ); - return 0; -} static BOOL null_wglSwapBuffers( HDC hdc ) { WARN( "unsupported\n" ); @@ -91356,7 +91324,6 @@ struct opengl_funcs null_opengl_funcs = .p_wglDeleteContext = null_wglDeleteContext, .p_wglGetPixelFormat = null_wglGetPixelFormat, .p_wglSetPixelFormat = null_wglSetPixelFormat, - .p_wglShareLists = null_wglShareLists, .p_wglSwapBuffers = null_wglSwapBuffers, .p_glAccum = null_glAccum, .p_glAlphaFunc = null_glAlphaFunc, diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index 77c5b81218d..bc83223cdef 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -4,7 +4,6 @@ typedef ULONG PTR32; extern BOOL wrap_wglCopyContext( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ); extern BOOL wrap_wglDeleteContext( TEB *teb, HGLRC oldContext ); -extern BOOL wrap_wglShareLists( TEB *teb, HGLRC hrcSrvShare, HGLRC hrcSrvSource ); extern BOOL wrap_wglSwapBuffers( TEB *teb, HDC hdc ); extern void wrap_glClear( TEB *teb, GLbitfield mask, PFN_glClear func ); extern void wrap_glDrawBuffer( TEB *teb, GLenum buf, PFN_glDrawBuffer func ); diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 2abeda46196..f1c42b1b579 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -127,7 +127,6 @@ struct context struct opengl_context base; HGLRC client; /* client-side context handle */ - HGLRC share; /* context to be shared with */ int *attribs; /* creation attributes */ UINT64 debug_callback; /* client pointer */ UINT64 debug_user; /* client pointer */ @@ -439,33 +438,6 @@ static struct context *context_from_client_context( HGLRC client_context ) return base ? CONTAINING_RECORD( base, struct context, base ) : NULL; } -static struct context *get_updated_context( TEB *teb, HGLRC client_context ); - -/* update context if it has been re-shared with another one */ -static struct context *update_context( TEB *teb, HGLRC client_context, struct context *ctx ) -{ - struct opengl_client_context *client = opengl_client_context_from_client( client_context ); - const struct opengl_funcs *funcs = get_context_funcs( client_context ); - - if (client->current_tid) return ctx; /* currently in use */ - if (ctx->share == (HGLRC)-1) return ctx; /* not re-shared */ - - if (!funcs->p_context_reset( &ctx->base, ctx->attribs )) - { - WARN( "Failed to re-create context for wglShareLists\n" ); - return ctx; - } - ctx->share = (HGLRC)-1; /* initial shared context */ - copy_context_attributes( teb, client_context, ctx, client_context, ctx, ctx->used ); - return ctx; -} - -static struct context *get_updated_context( TEB *teb, HGLRC client_context ) -{ - struct context *context = context_from_client_context( client_context ); - return client_context ? update_context( teb, client_context, context ) : NULL; -} - static int *memdup_attribs( const int *attribs ) { const int *attr; @@ -854,8 +826,8 @@ const GLubyte *wrap_glGetString( TEB *teb, GLenum name, PFN_glGetString p_glGetS BOOL wrap_wglCopyContext( TEB *teb, HGLRC client_src, HGLRC client_dst, UINT mask ) { struct context *src, *dst; - if (!(src = get_updated_context( teb, client_src ))) return FALSE; - if (!(dst = get_updated_context( teb, client_dst ))) return FALSE; + if (!(src = context_from_client_context( client_src ))) return FALSE; + if (!(dst = context_from_client_context( client_dst ))) return FALSE; return copy_context_attributes( teb, client_dst, dst, client_src, src, mask ); } @@ -1306,21 +1278,6 @@ BOOL wrap_wglSwapBuffers( TEB *teb, HDC hdc ) return ret; } -BOOL wrap_wglShareLists( TEB *teb, HGLRC client_src, HGLRC client_dst ) -{ - const struct opengl_funcs *src_funcs = get_context_funcs( client_src ), *dst_funcs = get_context_funcs( client_dst ); - struct context *src, *dst; - BOOL ret = FALSE; - - if (!(src = context_from_client_context( client_src ))) return FALSE; - if (!(dst = context_from_client_context( client_dst ))) return FALSE; - if (src_funcs != dst_funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - else if ((ret = dst->used != -1)) dst->share = client_src; - else FIXME( "Unsupported attributes on context %p/%p\n", client_dst, dst ); - - return ret; -} - HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, const int *attribs, HGLRC client_context ) { const struct opengl_funcs *funcs = get_dc_funcs( hdc ); @@ -1333,7 +1290,6 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, c return 0; } context->base.client_context = client_context; - context->share = (HGLRC)-1; /* initial shared context */ context->attribs = memdup_attribs( attribs ); if (is_win64 && is_wow64()) context->buffers = acquire_buffers(); @@ -1356,7 +1312,7 @@ BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC if (client_context) { const struct opengl_funcs *funcs = get_context_funcs( client_context ); - if (!(ctx = get_updated_context( teb, client_context ))) return FALSE; + if (!(ctx = context_from_client_context( client_context ))) return FALSE; if (!funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, client_context )) return FALSE; make_context_current( teb, funcs, draw_hdc, read_hdc, client_context, ctx ); } diff --git a/dlls/opengl32/unixlib.h b/dlls/opengl32/unixlib.h index 0151d66f824..8f5f6391bbe 100644 --- a/dlls/opengl32/unixlib.h +++ b/dlls/opengl32/unixlib.h @@ -53,14 +53,6 @@ struct wglSetPixelFormat_params BOOL ret; }; -struct wglShareLists_params -{ - TEB *teb; - HGLRC hrcSrvShare; - HGLRC hrcSrvSource; - BOOL ret; -}; - struct wglSwapBuffers_params { TEB *teb; @@ -25823,7 +25815,6 @@ enum unix_funcs unix_wglDeleteContext, unix_wglGetPixelFormat, unix_wglSetPixelFormat, - unix_wglShareLists, unix_wglSwapBuffers, unix_glAccum, unix_glAlphaFunc, diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index dde1914191a..ebd7447250a 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -996,10 +996,8 @@ BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC handle ) */ BOOL WINAPI wglShareLists( HGLRC src_handle, HGLRC dst_handle ) { - struct wglShareLists_params args = { .teb = NtCurrentTeb() }; struct context *src_context, *dst_context; struct display_lists *lists; - NTSTATUS status; TRACE( "src_handle %p, dst_handle %p\n", src_handle, dst_handle ); @@ -1007,11 +1005,6 @@ BOOL WINAPI wglShareLists( HGLRC src_handle, HGLRC dst_handle ) if (!(dst_context = context_from_handle( dst_handle ))) return FALSE; if (ReadNoFence( &dst_context->lists->modified )) return FALSE; - args.hrcSrvShare = &src_context->base.obj; - args.hrcSrvSource = &dst_context->base.obj; - if ((status = UNIX_CALL( wglShareLists, &args ))) WARN( "wglShareLists returned %#lx\n", status ); - if (!args.ret) return FALSE; - lists = display_lists_acquire( src_context->lists ); lists = InterlockedExchangePointer( (void *)&dst_context->lists, lists ); display_lists_release( lists ); diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index c7bfde36a1e..eda0797b3a4 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -2352,14 +2352,6 @@ static BOOL win32u_context_destroy( struct opengl_context *context ) return TRUE; } -static BOOL win32u_context_reset( struct opengl_context *context, const int *attribs ) -{ - TRACE( "context %p, attribs %p\n", context, attribs ); - - if (!win32u_context_destroy( context )) return FALSE; - return driver_funcs->p_context_create( context->format, global_context, attribs, &context->driver_private ); -} - static BOOL flush_memory_pbuffer( void (*flush)(void) ) { HDC draw_hdc = NtCurrentTeb()->glReserved1[0], read_hdc = NtCurrentTeb()->glReserved1[1]; @@ -2756,7 +2748,6 @@ static void display_funcs_init(void) display_funcs.p_context_flush = win32u_context_flush; display_funcs.p_context_create = win32u_context_create; display_funcs.p_context_destroy = win32u_context_destroy; - display_funcs.p_context_reset = win32u_context_reset; global_extensions[WGL_ARB_multisample] = 1; diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 7c138d37e64..cf271fbd411 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -148,7 +148,6 @@ struct opengl_funcs BOOL (*p_context_flush)( struct opengl_context *context, void (*flush)(void), UINT flags ); BOOL (*p_context_create)( struct opengl_context *context, HDC hdc, const int *attribs ); BOOL (*p_context_destroy)( struct opengl_context *context ); - BOOL (*p_context_reset)( struct opengl_context *context, const int *attribs ); BOOL (*p_pbuffer_create)( HDC hdc, int format, int width, int height, const int *attribs, HPBUFFERARB client_pbuffer ); void *egl_handle; }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
From: Rémi Bernon <rbernon@codeweavers.com> Any current context is valid, as they are now all shared with each other, we use the null context in order to avoid touching the client side context at all. --- dlls/win32u/opengl.c | 105 +++++++++++++---------------------- include/wine/opengl_driver.h | 2 - 2 files changed, 40 insertions(+), 67 deletions(-) diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index eda0797b3a4..4170d8312e2 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -172,12 +172,6 @@ void opengl_drawable_release( struct opengl_drawable *drawable ) } } -static void opengl_drawable_set_context( struct opengl_drawable *drawable, struct opengl_context *context ) -{ - if (!drawable->funcs->set_context) return; - drawable->funcs->set_context( drawable, context ? context->driver_private : NULL ); -} - static void opengl_drawable_flush( struct opengl_drawable *drawable, int interval, UINT flags ) { if (!is_client_surface_window( drawable->client, 0 )) return; @@ -225,6 +219,13 @@ static BOOL make_null_context_current(void) #ifdef SONAME_LIBEGL +static void make_client_context_current(void) +{ + struct opengl_context *context; + if (!(context = NtCurrentTeb()->glContext)) return; + driver_funcs->p_make_current( context->draw, context->read, context->driver_private ); +} + struct framebuffer_surface { struct opengl_drawable base; @@ -381,7 +382,18 @@ static void destroy_framebuffer( struct opengl_drawable *drawable, const struct static void framebuffer_surface_destroy( struct opengl_drawable *drawable ) { + struct wgl_pixel_format draw_desc = pixel_formats[drawable->format - 1], read_desc = draw_desc; + read_desc.samples = read_desc.sample_buffers = 0; + TRACE( "%s\n", debugstr_opengl_drawable( drawable ) ); + + make_null_context_current(); + + if (drawable->draw_fbo != drawable->read_fbo) + destroy_framebuffer( drawable, &draw_desc, drawable->draw_fbo ); + destroy_framebuffer( drawable, &read_desc, drawable->read_fbo ); + + make_client_context_current(); } static void framebuffer_surface_resize( struct opengl_drawable *drawable ) @@ -389,6 +401,8 @@ static void framebuffer_surface_resize( struct opengl_drawable *drawable ) struct wgl_pixel_format draw_desc = pixel_formats[drawable->format - 1], read_desc = draw_desc; RECT rect; + make_null_context_current(); + NtUserGetClientRect( drawable->client->hwnd, &rect, NtUserGetDpiForWindow( drawable->client->hwnd ) ); if (!rect.right) rect.right = 1; if (!rect.bottom) rect.bottom = 1; @@ -403,36 +417,8 @@ static void framebuffer_surface_resize( struct opengl_drawable *drawable ) TRACE( "Resizing drawable %p/%u to %ux%u\n", drawable, drawable->draw_fbo, rect.right, rect.bottom ); resize_framebuffer( drawable, &draw_desc, drawable->draw_fbo, rect.right, rect.bottom ); } -} - -static void framebuffer_surface_set_context( struct opengl_drawable *drawable, void *private ) -{ - struct wgl_pixel_format draw_desc = pixel_formats[drawable->format - 1], read_desc = draw_desc; - read_desc.samples = read_desc.sample_buffers = 0; - - TRACE( "%s, private %p\n", debugstr_opengl_drawable( drawable ), private ); - if (!private) - { - if (drawable->draw_fbo != drawable->read_fbo) - { - destroy_framebuffer( drawable, &draw_desc, drawable->draw_fbo ); - drawable->draw_fbo = 0; - } - destroy_framebuffer( drawable, &read_desc, drawable->read_fbo ); - drawable->read_fbo = 0; - } - else - { - drawable->read_fbo = create_framebuffer( drawable, &read_desc ); - if (!drawable->read_fbo) ERR( "Failed to create read framebuffer object\n" ); - - if (!draw_desc.sample_buffers) drawable->draw_fbo = drawable->read_fbo; - else drawable->draw_fbo = create_framebuffer( drawable, &draw_desc ); - if (!drawable->draw_fbo) ERR( "Failed to create draw framebuffer object\n" ); - - framebuffer_surface_resize( drawable ); - } + make_client_context_current(); } static void framebuffer_surface_flush( struct opengl_drawable *drawable, UINT flags ) @@ -452,12 +438,13 @@ static const struct opengl_drawable_funcs framebuffer_surface_funcs = .destroy = framebuffer_surface_destroy, .flush = framebuffer_surface_flush, .swap = framebuffer_surface_swap, - .set_context = framebuffer_surface_set_context, }; static struct opengl_drawable *framebuffer_surface_create( int format, struct client_surface *client ) { + struct wgl_pixel_format draw_desc = pixel_formats[format - 1], read_desc = draw_desc; struct framebuffer_surface *surface; + if (!(surface = opengl_drawable_create( sizeof(*surface), &framebuffer_surface_funcs, format, client ))) return NULL; opengl_drawable_map_buffer( &surface->base, GL_FRONT_LEFT, GL_COLOR_ATTACHMENT0 ); @@ -478,6 +465,19 @@ static struct opengl_drawable *framebuffer_surface_create( int format, struct cl if (surface->base.doublebuffer) opengl_drawable_map_buffer( &surface->base, GL_BACK_RIGHT, GL_COLOR_ATTACHMENT3 ); } + make_null_context_current(); + + read_desc.samples = read_desc.sample_buffers = 0; + surface->base.read_fbo = create_framebuffer( &surface->base, &read_desc ); + if (!surface->base.read_fbo) ERR( "Failed to create read framebuffer object\n" ); + + if (!draw_desc.sample_buffers) surface->base.draw_fbo = surface->base.read_fbo; + else surface->base.draw_fbo = create_framebuffer( &surface->base, &draw_desc ); + if (!surface->base.draw_fbo) ERR( "Failed to create draw framebuffer object\n" ); + + make_client_context_current(); + + framebuffer_surface_resize( &surface->base ); return &surface->base; } @@ -1817,21 +1817,6 @@ static void context_exchange_drawables( struct opengl_context *context, struct o *read = old_read; } -static BOOL context_unset_current( struct opengl_context *context ) -{ - struct opengl_drawable *old_draw = context->draw, *old_read = context->read; - - TRACE( "context %p\n", context ); - - opengl_drawable_set_context( old_read, NULL ); - if (old_read != old_draw) opengl_drawable_set_context( old_draw, NULL ); - if (make_null_context_current()) return TRUE; - opengl_drawable_set_context( old_read, context ); - if (old_read != old_draw) opengl_drawable_set_context( old_draw, context ); - - return FALSE; -} - /* return an updated drawable, recreating one if the window drawables have been invalidated (mostly wineandroid) */ static struct opengl_drawable *get_updated_drawable( HDC hdc, int format, struct opengl_drawable *drawable ) { @@ -1877,12 +1862,7 @@ static BOOL context_sync_drawables( struct opengl_context *context, HDC draw_hdc } if (previous == context && new_draw == context->draw && new_read == context->read) ret = TRUE; - else if (previous) - { - context_exchange_drawables( previous, &old_draw, &old_read ); /* take ownership of the previous context drawables */ - opengl_drawable_set_context( old_read, NULL ); - if (old_read != old_draw) opengl_drawable_set_context( old_draw, NULL ); - } + else if (previous) context_exchange_drawables( previous, &old_draw, &old_read ); /* take ownership of the previous context drawables */ if (!ret && (ret = driver_funcs->p_make_current( new_draw, new_read, context->driver_private ))) { @@ -1897,9 +1877,6 @@ static BOOL context_sync_drawables( struct opengl_context *context, HDC draw_hdc if (old_draw) opengl_drawable_release( old_draw ); if (old_read) opengl_drawable_release( old_read ); - opengl_drawable_set_context( new_read, context ); - if (new_read != new_draw) opengl_drawable_set_context( new_draw, context ); - opengl_drawable_flush( new_read, new_read->interval, 0 ); opengl_drawable_flush( new_draw, new_draw->interval, 0 ); } @@ -1912,8 +1889,6 @@ static BOOL context_sync_drawables( struct opengl_context *context, HDC draw_hdc } else if (previous) { - opengl_drawable_set_context( old_read, context ); - if (old_read != old_draw) opengl_drawable_set_context( old_draw, context ); context_exchange_drawables( previous, &old_draw, &old_read ); /* give back ownership of the previous drawables */ assert( !old_draw && !old_read ); } @@ -1955,8 +1930,8 @@ static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC c { struct opengl_drawable *draw = NULL, *read = NULL; - if (!(context = prev_context)) return make_null_context_current(); - if (!context_unset_current( context )) return FALSE; + if (!make_null_context_current()) return FALSE; + if (!(context = prev_context)) return TRUE; NtCurrentTeb()->glContext = NULL; context_exchange_drawables( context, &draw, &read ); @@ -2884,7 +2859,7 @@ void cleanup_opengl_thread(void) struct opengl_thread_data *data; /* unset current context, this is sometimes missing from host drivers and leaks memory */ - if (context && context_unset_current( context )) + if (context && driver_funcs->p_make_current( NULL, NULL, NULL )) { struct opengl_drawable *draw = NULL, *read = NULL; diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index cf271fbd411..237c7af1b4f 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -189,8 +189,6 @@ struct opengl_drawable_funcs void (*flush)( struct opengl_drawable *iface, UINT flags ); /* swap and present the drawable buffers, called from render thread */ BOOL (*swap)( struct opengl_drawable *iface ); - /* drawable is being unset or made current, called from render thread */ - void (*set_context)( struct opengl_drawable *iface, void *private ); }; /* flags for opengl_drawable flush */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11161
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)