[PATCH v3 0/5] MR11226: opengl32: Finer WOW64 buffer storage locking.
-- v3: opengl32: Reduce WOW64 locking to the buffer storage map accesses. opengl32: Use an array instead of rb_tree for the buffer storage map. opengl32: Use a static variable for the buffer storage map. opengl32: Move more wow64 wrappers out of the generated code. opengl32: Flag GL_EXT_external_buffer extension as unsupported. https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
From: Rémi Bernon <rbernon@codeweavers.com> It is EGL specific. --- dlls/opengl32/make_opengl | 3 +- dlls/opengl32/thunks.c | 21 ----------- dlls/opengl32/unix_thunks.c | 72 ------------------------------------- dlls/opengl32/unixlib.h | 22 ------------ include/wine/wgl.h | 5 --- 5 files changed, 1 insertion(+), 122 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index fcca05838bf..9824efd3375 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -301,14 +301,12 @@ my %wow64_invalidate_buffer = "glBufferData" => 1, "glBufferDataARB" => 1, "glBufferStorage" => 1, - "glBufferStorageExternalEXT" => 1, "glBufferStorageMemEXT" => 1, "glNamedBufferAttachMemoryNV" => 1, "glNamedBufferData" => 1, "glNamedBufferDataEXT" => 1, "glNamedBufferStorage" => 1, "glNamedBufferStorageEXT" => 1, - "glNamedBufferStorageExternalEXT" => 1, "glNamedBufferStorageMemEXT" => 1, ); my %pointer_array_count = @@ -1106,6 +1104,7 @@ my %unsupported_extgroups = ); my %unsupported_extensions = ( + "GL_EXT_external_buffer" => 1, "WGL_AMD_gpu_association" => 1, "WGL_ARB_buffer_region" => 1, "WGL_EXT_display_color_table" => 1, diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index 1c471268d8b..3083ad3ad60 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -4022,14 +4022,6 @@ static void WINAPI glBufferStorage( GLenum target, GLsizeiptr size, const void * if ((status = UNIX_CALL( glBufferStorage, &args ))) WARN( "glBufferStorage returned %#lx\n", status ); } -static void WINAPI glBufferStorageExternalEXT( GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags ) -{ - struct glBufferStorageExternalEXT_params args = { .teb = NtCurrentTeb(), .target = target, .offset = offset, .size = size, .clientBuffer = clientBuffer, .flags = flags }; - NTSTATUS status; - TRACE( "target %d, offset %Id, size %Id, clientBuffer %p, flags %d\n", target, offset, size, clientBuffer, flags ); - if ((status = UNIX_CALL( glBufferStorageExternalEXT, &args ))) WARN( "glBufferStorageExternalEXT returned %#lx\n", status ); -} - static void WINAPI glBufferStorageMemEXT( GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset ) { struct glBufferStorageMemEXT_params args = { .teb = NtCurrentTeb(), .target = target, .size = size, .offset = offset }; @@ -15220,15 +15212,6 @@ static void WINAPI glNamedBufferStorageEXT( GLuint buffer, GLsizeiptr size, cons if ((status = UNIX_CALL( glNamedBufferStorageEXT, &args ))) WARN( "glNamedBufferStorageEXT returned %#lx\n", status ); } -static void WINAPI glNamedBufferStorageExternalEXT( GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags ) -{ - struct glNamedBufferStorageExternalEXT_params args = { .teb = NtCurrentTeb(), .offset = offset, .size = size, .clientBuffer = clientBuffer, .flags = flags }; - NTSTATUS status; - TRACE( "buffer %d, offset %Id, size %Id, clientBuffer %p, flags %d\n", buffer, offset, size, clientBuffer, flags ); - args.buffer = *map_context_objects( OBJ_TYPE_BUFFER, 1, &buffer ); - if ((status = UNIX_CALL( glNamedBufferStorageExternalEXT, &args ))) WARN( "glNamedBufferStorageExternalEXT returned %#lx\n", status ); -} - static void WINAPI glNamedBufferStorageMemEXT( GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset ) { struct glNamedBufferStorageMemEXT_params args = { .teb = NtCurrentTeb(), .size = size, .offset = offset }; @@ -26248,7 +26231,6 @@ const void *extension_procs[] = glBufferParameteriAPPLE, glBufferRegionEnabled, glBufferStorage, - glBufferStorageExternalEXT, glBufferStorageMemEXT, glBufferSubData, glBufferSubDataARB, @@ -27569,7 +27551,6 @@ const void *extension_procs[] = glNamedBufferPageCommitmentMemNV, glNamedBufferStorage, glNamedBufferStorageEXT, - glNamedBufferStorageExternalEXT, glNamedBufferStorageMemEXT, glNamedBufferSubData, glNamedBufferSubDataEXT, @@ -29009,7 +28990,6 @@ const struct registry_entry extension_registry[] = { "glBufferParameteriAPPLE", glBufferParameteriAPPLE, 0, 0, { GL_APPLE_flush_buffer_range, GL_EXTENSION_COUNT }}, { "glBufferRegionEnabled", glBufferRegionEnabled, 0, 0, { GL_KTX_buffer_region, GL_EXTENSION_COUNT }}, { "glBufferStorage", glBufferStorage, 4, 4, { GL_ARB_buffer_storage, GL_EXTENSION_COUNT }}, - { "glBufferStorageExternalEXT", glBufferStorageExternalEXT, 0, 0, { GL_EXT_external_buffer, GL_EXTENSION_COUNT }}, { "glBufferStorageMemEXT", glBufferStorageMemEXT, 0, 0, { GL_EXT_memory_object, GL_EXTENSION_COUNT }}, { "glBufferSubData", glBufferSubData, 1, 5, { GL_EXTENSION_COUNT }}, { "glBufferSubDataARB", glBufferSubDataARB, 0, 0, { GL_ARB_vertex_buffer_object, GL_EXTENSION_COUNT }}, @@ -30330,7 +30310,6 @@ const struct registry_entry extension_registry[] = { "glNamedBufferPageCommitmentMemNV", glNamedBufferPageCommitmentMemNV, 0, 0, { GL_NV_memory_object_sparse, GL_EXTENSION_COUNT }}, { "glNamedBufferStorage", glNamedBufferStorage, 4, 5, { GL_ARB_direct_state_access, GL_EXTENSION_COUNT }}, { "glNamedBufferStorageEXT", glNamedBufferStorageEXT, 0, 0, { GL_EXT_direct_state_access, GL_EXTENSION_COUNT }}, - { "glNamedBufferStorageExternalEXT", glNamedBufferStorageExternalEXT, 0, 0, { GL_EXT_external_buffer, GL_EXTENSION_COUNT }}, { "glNamedBufferStorageMemEXT", glNamedBufferStorageMemEXT, 0, 0, { GL_EXT_memory_object, GL_EXTENSION_COUNT }}, { "glNamedBufferSubData", glNamedBufferSubData, 4, 5, { GL_ARB_direct_state_access, GL_EXTENSION_COUNT }}, { "glNamedBufferSubDataEXT", glNamedBufferSubDataEXT, 0, 0, { GL_EXT_direct_state_access, GL_EXTENSION_COUNT }}, diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 1d3f8a8dbd3..04b6b25bfd5 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -4818,16 +4818,6 @@ static NTSTATUS ext_glBufferStorage( void *args ) return STATUS_SUCCESS; } -static NTSTATUS ext_glBufferStorageExternalEXT( void *args ) -{ - struct glBufferStorageExternalEXT_params *params = args; - const struct opengl_funcs *funcs = params->teb->glTable; - if (!funcs->p_glBufferStorageExternalEXT) return STATUS_NOT_IMPLEMENTED; - funcs->p_glBufferStorageExternalEXT( params->target, params->offset, params->size, params->clientBuffer, params->flags ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); - return STATUS_SUCCESS; -} - static NTSTATUS ext_glBufferStorageMemEXT( void *args ) { struct glBufferStorageMemEXT_params *params = args; @@ -17627,16 +17617,6 @@ static NTSTATUS ext_glNamedBufferStorageEXT( void *args ) return STATUS_SUCCESS; } -static NTSTATUS ext_glNamedBufferStorageExternalEXT( void *args ) -{ - struct glNamedBufferStorageExternalEXT_params *params = args; - const struct opengl_funcs *funcs = params->teb->glTable; - if (!funcs->p_glNamedBufferStorageExternalEXT) return STATUS_NOT_IMPLEMENTED; - funcs->p_glNamedBufferStorageExternalEXT( params->buffer, params->offset, params->size, params->clientBuffer, params->flags ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); - return STATUS_SUCCESS; -} - static NTSTATUS ext_glNamedBufferStorageMemEXT( void *args ) { struct glNamedBufferStorageMemEXT_params *params = args; @@ -31006,7 +30986,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = ext_glBufferParameteriAPPLE, ext_glBufferRegionEnabled, ext_glBufferStorage, - ext_glBufferStorageExternalEXT, ext_glBufferStorageMemEXT, ext_glBufferSubData, ext_glBufferSubDataARB, @@ -32327,7 +32306,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = ext_glNamedBufferPageCommitmentMemNV, ext_glNamedBufferStorage, ext_glNamedBufferStorageEXT, - ext_glNamedBufferStorageExternalEXT, ext_glNamedBufferStorageMemEXT, ext_glNamedBufferSubData, ext_glNamedBufferSubDataEXT, @@ -41649,30 +41627,6 @@ static NTSTATUS wow64_ext_glBufferStorage( void *args ) return STATUS_SUCCESS; } -static NTSTATUS wow64_ext_glBufferStorageExternalEXT( void *args ) -{ - struct - { - PTR32 teb; - GLenum target; - PTR32 offset; - PTR32 size; - PTR32 clientBuffer; - GLbitfield flags; - } *params = args; - TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; - const struct opengl_funcs *funcs = teb->glTable; - if (!funcs->p_glBufferStorageExternalEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); - funcs->p_glBufferStorageExternalEXT( params->target, (GLintptr)ULongToPtr(params->offset), (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->clientBuffer), params->flags ); - pthread_mutex_unlock( &wgl_lock ); - set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); - return STATUS_SUCCESS; -} - static NTSTATUS wow64_ext_glBufferStorageMemEXT( void *args ) { struct @@ -64353,30 +64307,6 @@ static NTSTATUS wow64_ext_glNamedBufferStorageEXT( void *args ) return STATUS_SUCCESS; } -static NTSTATUS wow64_ext_glNamedBufferStorageExternalEXT( void *args ) -{ - struct - { - PTR32 teb; - GLuint buffer; - PTR32 offset; - PTR32 size; - PTR32 clientBuffer; - GLbitfield flags; - } *params = args; - TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; - const struct opengl_funcs *funcs = teb->glTable; - if (!funcs->p_glNamedBufferStorageExternalEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); - funcs->p_glNamedBufferStorageExternalEXT( params->buffer, (GLintptr)ULongToPtr(params->offset), (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->clientBuffer), params->flags ); - pthread_mutex_unlock( &wgl_lock ); - set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); - return STATUS_SUCCESS; -} - static NTSTATUS wow64_ext_glNamedBufferStorageMemEXT( void *args ) { struct @@ -87322,7 +87252,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = wow64_ext_glBufferParameteriAPPLE, wow64_ext_glBufferRegionEnabled, wow64_ext_glBufferStorage, - wow64_ext_glBufferStorageExternalEXT, wow64_ext_glBufferStorageMemEXT, wow64_ext_glBufferSubData, wow64_ext_glBufferSubDataARB, @@ -88643,7 +88572,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = wow64_ext_glNamedBufferPageCommitmentMemNV, wow64_ext_glNamedBufferStorage, wow64_ext_glNamedBufferStorageEXT, - wow64_ext_glNamedBufferStorageExternalEXT, wow64_ext_glNamedBufferStorageMemEXT, wow64_ext_glNamedBufferSubData, wow64_ext_glNamedBufferSubDataEXT, diff --git a/dlls/opengl32/unixlib.h b/dlls/opengl32/unixlib.h index 8f5f6391bbe..6df1d2fafd4 100644 --- a/dlls/opengl32/unixlib.h +++ b/dlls/opengl32/unixlib.h @@ -3699,16 +3699,6 @@ struct glBufferStorage_params GLbitfield flags; }; -struct glBufferStorageExternalEXT_params -{ - TEB *teb; - GLenum target; - GLintptr offset; - GLsizeiptr size; - GLeglClientBufferEXT clientBuffer; - GLbitfield flags; -}; - struct glBufferStorageMemEXT_params { TEB *teb; @@ -14898,16 +14888,6 @@ struct glNamedBufferStorageEXT_params GLbitfield flags; }; -struct glNamedBufferStorageExternalEXT_params -{ - TEB *teb; - GLuint buffer; - GLintptr offset; - GLsizeiptr size; - GLeglClientBufferEXT clientBuffer; - GLbitfield flags; -}; - struct glNamedBufferStorageMemEXT_params { TEB *teb; @@ -26293,7 +26273,6 @@ enum unix_funcs unix_glBufferParameteriAPPLE, unix_glBufferRegionEnabled, unix_glBufferStorage, - unix_glBufferStorageExternalEXT, unix_glBufferStorageMemEXT, unix_glBufferSubData, unix_glBufferSubDataARB, @@ -27614,7 +27593,6 @@ enum unix_funcs unix_glNamedBufferPageCommitmentMemNV, unix_glNamedBufferStorage, unix_glNamedBufferStorageEXT, - unix_glNamedBufferStorageExternalEXT, unix_glNamedBufferStorageMemEXT, unix_glNamedBufferSubData, unix_glNamedBufferSubDataEXT, diff --git a/include/wine/wgl.h b/include/wine/wgl.h index 3b46ee51b87..36df3a2d5ee 100644 --- a/include/wine/wgl.h +++ b/include/wine/wgl.h @@ -7880,7 +7880,6 @@ typedef void (GLAPIENTRY *PFN_glBufferParameteriAPPLE)( GLenum target, GLe typedef GLuint (GLAPIENTRY *PFN_glBufferRegionEnabled)(void); typedef void (GLAPIENTRY *PFN_glBufferStorage)( GLenum target, GLsizeiptr size, const void *data, GLbitfield flags ); typedef void (GLAPIENTRY *PFN_glBufferStorageEXT)( GLenum target, GLsizeiptr size, const void *data, GLbitfield flags ); -typedef void (GLAPIENTRY *PFN_glBufferStorageExternalEXT)( GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags ); typedef void (GLAPIENTRY *PFN_glBufferStorageMemEXT)( GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset ); typedef void (GLAPIENTRY *PFN_glBufferSubData)( GLenum target, GLintptr offset, GLsizeiptr size, const void *data ); typedef void (GLAPIENTRY *PFN_glBufferSubDataARB)( GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data ); @@ -9353,7 +9352,6 @@ typedef void (GLAPIENTRY *PFN_glNamedBufferPageCommitmentEXT)( GLuint buff typedef void (GLAPIENTRY *PFN_glNamedBufferPageCommitmentMemNV)( GLuint buffer, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit ); typedef void (GLAPIENTRY *PFN_glNamedBufferStorage)( GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags ); typedef void (GLAPIENTRY *PFN_glNamedBufferStorageEXT)( GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags ); -typedef void (GLAPIENTRY *PFN_glNamedBufferStorageExternalEXT)( GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags ); typedef void (GLAPIENTRY *PFN_glNamedBufferStorageMemEXT)( GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset ); typedef void (GLAPIENTRY *PFN_glNamedBufferSubData)( GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data ); typedef void (GLAPIENTRY *PFN_glNamedBufferSubDataEXT)( GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data ); @@ -11444,7 +11442,6 @@ typedef BOOL (GLAPIENTRY *PFN_wglSwapIntervalEXT)( int interval ); USE_GL_EXT(GL_EXT_draw_buffers2) \ USE_GL_EXT(GL_EXT_draw_instanced) \ USE_GL_EXT(GL_EXT_draw_range_elements) \ - USE_GL_EXT(GL_EXT_external_buffer) \ USE_GL_EXT(GL_EXT_float_blend) \ USE_GL_EXT(GL_EXT_fog_coord) \ USE_GL_EXT(GL_EXT_frag_depth) \ @@ -12434,7 +12431,6 @@ typedef BOOL (GLAPIENTRY *PFN_wglSwapIntervalEXT)( int interval ); USE_GL_FUNC(glBufferRegionEnabled) \ USE_GL_FUNC(glBufferStorage) \ USE_GL_FUNC(glBufferStorageEXT) \ - USE_GL_FUNC(glBufferStorageExternalEXT) \ USE_GL_FUNC(glBufferStorageMemEXT) \ USE_GL_FUNC(glBufferSubData) \ USE_GL_FUNC(glBufferSubDataARB) \ @@ -13907,7 +13903,6 @@ typedef BOOL (GLAPIENTRY *PFN_wglSwapIntervalEXT)( int interval ); USE_GL_FUNC(glNamedBufferPageCommitmentMemNV) \ USE_GL_FUNC(glNamedBufferStorage) \ USE_GL_FUNC(glNamedBufferStorageEXT) \ - USE_GL_FUNC(glNamedBufferStorageExternalEXT) \ USE_GL_FUNC(glNamedBufferStorageMemEXT) \ USE_GL_FUNC(glNamedBufferSubData) \ USE_GL_FUNC(glNamedBufferSubDataEXT) \ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/make_opengl | 39 ++--------- dlls/opengl32/unix_private.h | 5 -- dlls/opengl32/unix_thunks.c | 71 +++----------------- dlls/opengl32/unix_thunks.h | 6 ++ dlls/opengl32/unix_wgl.c | 127 +++++++++++++++++++++++++---------- 5 files changed, 110 insertions(+), 138 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 9824efd3375..e9b584859c5 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -276,8 +276,9 @@ sub map_default_fbo($$) sub manual_wow64_wrapper($) { my $name = shift; - return 0 if $name =~ /^glBufferStorageExternal/; - return 0 if $name =~ /^glBufferStorageMem/; + return "glBufferAttachMemoryNV" if $name =~ /^glBufferAttachMemory/; + return "glBufferData" if $name =~ /^glBufferData/; + return "glBufferStorageMemEXT" if $name =~ /^glBufferStorageMem/; return "glBufferStorage" if $name =~ /^glBufferStorage/; return "glDeleteBuffers" if $name =~ /^glDeleteBuffers/; return "glFlushMappedBufferRange" if $name =~ /^glFlushMappedBufferRange/; @@ -288,27 +289,14 @@ sub manual_wow64_wrapper($) return "glMapBuffer" if $name =~ /^glMapBuffer/; return "glMapNamedBufferRange" if $name =~ /^glMapNamedBufferRange/; return "glMapNamedBuffer" if $name =~ /^glMapNamedBuffer/; - return 0 if $name =~ /^glNamedBufferStorageExternal/; - return 0 if $name =~ /^glNamedBufferStorageMem/; + return "glNamedBufferAttachMemoryNV" if $name =~ /^glNamedBufferAttachMemory/; + return "glNamedBufferData" if $name =~ /^glNamedBufferData/; + return "glNamedBufferStorageMemEXT" if $name =~ /^glNamedBufferStorageMem/; return "glNamedBufferStorage" if $name =~ /^glNamedBufferStorage/; return "glUnmapBuffer" if $name =~ /^glUnmapBuffer/; return "glUnmapNamedBuffer" if $name =~ /^glUnmapNamedBuffer/; } -my %wow64_invalidate_buffer = - ( - "glBufferAttachMemoryNV" => 1, - "glBufferData" => 1, - "glBufferDataARB" => 1, - "glBufferStorage" => 1, - "glBufferStorageMemEXT" => 1, - "glNamedBufferAttachMemoryNV" => 1, - "glNamedBufferData" => 1, - "glNamedBufferDataEXT" => 1, - "glNamedBufferStorage" => 1, - "glNamedBufferStorageEXT" => 1, - "glNamedBufferStorageMemEXT" => 1, - ); my %pointer_array_count = ( "glCompileShaderIncludeARB" => "count", @@ -410,11 +398,9 @@ sub generate_unix_thunk($$$$) my $func_ret = get_func_ret( $func ); my $wow64_wrap = $is_wow64 ? manual_wow64_wrapper( $name ) : 0; my $wrapper = $wow64_wrap || needs_wrapper( $name, $func ); - my $need_lock = 0; my $need_funcs = !$wrapper || $name !~ /^wgl/; my $teb = $is_wow64 ? "teb" : "params->teb"; my $ret_stat = "return STATUS_SUCCESS;"; - my $invalidation = ""; my $input_conv = ""; my $output_conv = ""; my $use_pbuffer = 0; @@ -495,7 +481,6 @@ sub generate_unix_thunk($$$$) { $call_args .= " ULongToPtr(params->$pname),"; $need_manual_thunk = 1 if $arg_type =~ /(\*.*\*|(sizei|int)ptr.*\*)/; - $need_lock = 1 if $arg_type =~ /GLsync/; } } $call_args .= " UlongToHandle( params->ret )," if $func_ret =~ /HPBUFFERARB|HGLRC|GLsync/; @@ -524,16 +509,6 @@ sub generate_unix_thunk($$$$) $ret .= "}\n\n"; return $ret; } - if (defined $wow64_invalidate_buffer{$name}) - { - $need_lock = 1; - $need_funcs = 1; - $vars .= " struct buffer *buffer;\n"; - $invalidation .= $name =~ /NamedBuffer/ - ? " buffer = invalidate_buffer_name( $teb, params->buffer );\n" - : " buffer = invalidate_buffer_target( $teb, params->target );\n"; - $output_conv .= " if (buffer) free_buffer( funcs, buffer );\n"; - } $ret .= " TEB *teb = get_teb64( params->teb );\n" if $wrapper || (!$use_dc && !$use_pbuffer && !$use_context); } else @@ -597,7 +572,6 @@ sub generate_unix_thunk($$$$) } $ret .= " resolve_default_fbo( $teb, TRUE );\n" if resolve_default_fbo( $name ); $ret .= " push_default_fbo( $teb );\n" if hide_default_fbo( $name ); - $ret .= " pthread_mutex_lock( &wgl_lock );\n$invalidation" if $need_lock; $ret .= " $ret_expr"; if ($wow64_wrap) { @@ -614,7 +588,6 @@ sub generate_unix_thunk($$$$) $call_args =~ s/,$/ /; $ret .= "funcs->p_$name($call_args);\n"; } - $ret .= " pthread_mutex_unlock( &wgl_lock );\n" if $need_lock; $ret .= " set_current_fbo( $teb, params->target, params->framebuffer );\n" if $name =~ /glBindFramebuffer/; $ret .= " pop_default_fbo( $teb );\n" if hide_default_fbo( $name ); if (defined $state_attrib_funcs{$name}) diff --git a/dlls/opengl32/unix_private.h b/dlls/opengl32/unix_private.h index 8f05f6218e7..10722acf7ec 100644 --- a/dlls/opengl32/unix_private.h +++ b/dlls/opengl32/unix_private.h @@ -81,15 +81,10 @@ static inline TEB *get_teb64( ULONG teb32 ) return (TEB *)((char *)teb32_ptr + teb32_ptr->WowTebOffset); } -extern struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ); -extern struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ); -extern void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ); extern NTSTATUS return_wow64_string( const void *str, PTR32 *wow64_str ); #endif -extern pthread_mutex_t wgl_lock; - extern NTSTATUS process_attach( void *args ); extern NTSTATUS thread_attach( void *args ); extern NTSTATUS process_detach( void *args ); diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 04b6b25bfd5..ee35199ffc0 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -41476,15 +41476,10 @@ static NTSTATUS wow64_ext_glBufferAttachMemoryNV( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glBufferAttachMemoryNV) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); - funcs->p_glBufferAttachMemoryNV( params->target, params->memory, params->offset ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glBufferAttachMemoryNV( teb, params->target, params->memory, params->offset, funcs->p_glBufferAttachMemoryNV ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -41499,15 +41494,10 @@ static NTSTATUS wow64_ext_glBufferData( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glBufferData) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); - funcs->p_glBufferData( params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glBufferData( teb, params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage, funcs->p_glBufferData ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -41522,15 +41512,10 @@ static NTSTATUS wow64_ext_glBufferDataARB( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glBufferDataARB) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); - funcs->p_glBufferDataARB( params->target, (GLsizeiptrARB)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glBufferData( teb, params->target, (GLsizeiptrARB)ULongToPtr(params->size), ULongToPtr(params->data), params->usage, funcs->p_glBufferDataARB ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -41615,15 +41600,10 @@ static NTSTATUS wow64_ext_glBufferStorage( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glBufferStorage) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); wow64_glBufferStorage( teb, params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags, funcs->p_glBufferStorage ); - pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -41638,15 +41618,10 @@ static NTSTATUS wow64_ext_glBufferStorageMemEXT( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glBufferStorageMemEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, params->target ); - funcs->p_glBufferStorageMemEXT( params->target, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glBufferStorageMemEXT( teb, params->target, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset, funcs->p_glBufferStorageMemEXT ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64147,15 +64122,10 @@ static NTSTATUS wow64_ext_glNamedBufferAttachMemoryNV( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferAttachMemoryNV) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); - funcs->p_glNamedBufferAttachMemoryNV( params->buffer, params->memory, params->offset ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glNamedBufferAttachMemoryNV( teb, params->buffer, params->memory, params->offset, funcs->p_glNamedBufferAttachMemoryNV ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64170,15 +64140,10 @@ static NTSTATUS wow64_ext_glNamedBufferData( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferData) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); - funcs->p_glNamedBufferData( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glNamedBufferData( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage, funcs->p_glNamedBufferData ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64193,15 +64158,10 @@ static NTSTATUS wow64_ext_glNamedBufferDataEXT( void *args ) GLenum usage; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferDataEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); - funcs->p_glNamedBufferDataEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glNamedBufferData( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->usage, funcs->p_glNamedBufferDataEXT ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64272,15 +64232,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorage( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferStorage) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); wow64_glNamedBufferStorage( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags, funcs->p_glNamedBufferStorage ); - pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64295,15 +64250,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorageEXT( void *args ) GLbitfield flags; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferStorageEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); wow64_glNamedBufferStorage( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags, funcs->p_glNamedBufferStorageEXT ); - pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } @@ -64318,15 +64268,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorageMemEXT( void *args ) GLuint64 offset; } *params = args; TEB *teb = get_teb64( params->teb ); - struct buffer *buffer; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glNamedBufferStorageMemEXT) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, params->buffer ); - funcs->p_glNamedBufferStorageMemEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); - pthread_mutex_unlock( &wgl_lock ); + wow64_glNamedBufferStorageMemEXT( teb, params->buffer, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset, funcs->p_glNamedBufferStorageMemEXT ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); - if (buffer) free_buffer( funcs, buffer ); return STATUS_SUCCESS; } diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index bc83223cdef..1ba8ad4c5a0 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -39,7 +39,10 @@ extern HPBUFFERARB wrap_wglCreatePbufferARB( TEB *teb, HDC hDC, int iPixelFormat extern BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC hDrawDC, HDC hReadDC, HGLRC hglrc ); #ifdef _WIN64 +extern void wow64_glBufferAttachMemoryNV( TEB *teb, GLenum target, GLuint memory, GLuint64 offset, PFN_glBufferAttachMemoryNV func ); +extern void wow64_glBufferData( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLenum usage, PFN_glBufferData func ); extern void wow64_glBufferStorage( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLbitfield flags, PFN_glBufferStorage func ); +extern void wow64_glBufferStorageMemEXT( TEB *teb, GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glBufferStorageMemEXT func ); extern void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers, PFN_glDeleteBuffers func ); extern void wow64_glFlushMappedBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr length, PFN_glFlushMappedBufferRange func ); extern void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint buffer, GLintptr offset, GLsizeiptr length, PFN_glFlushMappedNamedBufferRange func ); @@ -49,7 +52,10 @@ extern void *wow64_glMapBuffer( TEB *teb, GLenum target, GLenum access, PFN_glMa extern void *wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, PFN_glMapBufferRange func ); extern void *wow64_glMapNamedBuffer( TEB *teb, GLuint buffer, GLenum access, PFN_glMapNamedBuffer func ); extern void *wow64_glMapNamedBufferRange( TEB *teb, GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access, PFN_glMapNamedBufferRange func ); +extern void wow64_glNamedBufferAttachMemoryNV( TEB *teb, GLuint buffer, GLuint memory, GLuint64 offset, PFN_glNamedBufferAttachMemoryNV func ); +extern void wow64_glNamedBufferData( TEB *teb, GLuint buffer, GLsizeiptr size, const void *data, GLenum usage, PFN_glNamedBufferData func ); extern void wow64_glNamedBufferStorage( TEB *teb, GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags, PFN_glNamedBufferStorage func ); +extern void wow64_glNamedBufferStorageMemEXT( TEB *teb, GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glNamedBufferStorageMemEXT func ); extern GLboolean wow64_glUnmapBuffer( TEB *teb, GLenum target, PFN_glUnmapBuffer func ); extern GLboolean wow64_glUnmapNamedBuffer( TEB *teb, GLuint buffer, PFN_glUnmapNamedBuffer func ); #endif diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 9786a32e209..5f5fae6a2a1 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -53,7 +53,6 @@ static BOOL is_wow64(void) } static UINT64 call_gl_debug_message_callback; -pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER; /* context state management */ @@ -397,7 +396,7 @@ static int compare_buffer_name( const void *key, const struct rb_entry *entry ) return memcmp( key, &buffer->name, sizeof(buffer->name) ); } -void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) +static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) { if (buffer->vk_memory) { @@ -1798,6 +1797,8 @@ NTSTATUS get_pixel_formats( void *args ) #ifdef _WIN64 +static pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER; + struct wow64_string_entry { const char *str; @@ -1884,7 +1885,7 @@ static struct buffer *get_named_buffer( TEB *teb, GLuint name ) return NULL; } -struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) +static struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) { struct buffer *buffer = get_named_buffer( teb, name ); if (buffer) @@ -1895,7 +1896,7 @@ struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) return buffer; } -struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) +static struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) { GLuint name = get_target_name( teb, target ); return name ? invalidate_buffer_name( teb, name ) : NULL; @@ -2218,34 +2219,37 @@ void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers, PFN_glDe void wow64_glBufferStorage( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLbitfield flags, PFN_glBufferStorage p_glBufferStorage ) { - struct buffer *buffer = NULL; + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer = NULL, *previous; + + pthread_mutex_lock( &wgl_lock ); + previous = invalidate_buffer_target( teb, target ); if (flags & GL_MAP_PERSISTENT_BIT) buffer = create_buffer_storage( teb, target, 0, size, data, flags ); if (!buffer) p_glBufferStorage( target, size, data, flags ); + + pthread_mutex_unlock( &wgl_lock ); + if (previous) free_buffer( funcs, previous ); } void wow64_glNamedBufferStorage( TEB *teb, GLuint name, GLsizeiptr size, const void *data, GLbitfield flags, PFN_glNamedBufferStorage p_glNamedBufferStorage ) { - struct buffer *buffer = NULL; + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer = NULL, *previous; + + pthread_mutex_lock( &wgl_lock ); + previous = invalidate_buffer_name( teb, name ); if (flags & GL_MAP_PERSISTENT_BIT) buffer = create_buffer_storage( teb, 0, name, size, data, flags ); if (!buffer) p_glNamedBufferStorage( name, size, data, flags ); -} -void wow64_glNamedBufferStorageEXT( TEB *teb, GLuint name, GLsizeiptr size, const void *data, - GLbitfield flags, PFN_glNamedBufferStorageEXT p_glNamedBufferStorageEXT ) -{ - struct buffer *buffer = NULL; - - if (flags & GL_MAP_PERSISTENT_BIT) - buffer = create_buffer_storage( teb, 0, name, size, data, flags ); - - if (!buffer) p_glNamedBufferStorageEXT( name, size, data, flags ); + pthread_mutex_unlock( &wgl_lock ); + if (previous) free_buffer( funcs, previous ); } static BOOL wow64_gl_get_buffer_pointer_v( TEB *teb, GLenum target, GLuint name, GLenum pname, PTR32 *wow_ptr ) @@ -2274,15 +2278,6 @@ void wow64_glGetBufferPointerv( TEB *teb, GLenum target, GLenum pname, PTR32 *pa *params = PtrToUlong(ptr); } -void wow64_glGetBufferPointervARB( TEB *teb, GLenum target, GLenum pname, PTR32 *params ) -{ - const struct opengl_funcs *funcs = teb->glTable; - void *ptr; - if (wow64_gl_get_buffer_pointer_v( teb, target, 0, pname, params )) return; - funcs->p_glGetBufferPointerv( target, pname, &ptr ); - *params = PtrToUlong(ptr); -} - void wow64_glGetNamedBufferPointerv( TEB *teb, GLuint buffer, GLenum pname, PTR32 *params, PFN_glGetNamedBufferPointerv p_glGetNamedBufferPointerv ) { @@ -2292,15 +2287,6 @@ void wow64_glGetNamedBufferPointerv( TEB *teb, GLuint buffer, GLenum pname, PTR3 *params = PtrToUlong(ptr); } -void wow64_glGetNamedBufferPointervEXT( TEB *teb, GLuint buffer, GLenum pname, PTR32 *params ) -{ - const struct opengl_funcs *funcs = teb->glTable; - void *ptr; - if (buffer && wow64_gl_get_buffer_pointer_v( teb, 0, buffer, pname, params )) return; - funcs->p_glGetNamedBufferPointervEXT( buffer, pname, &ptr ); - *params = PtrToUlong(ptr); -} - void *wow64_glMapBuffer( TEB *teb, GLenum target, GLenum access, PFN_glMapBuffer p_glMapBuffer ) { GLbitfield range_access = map_range_flags_from_map_flags( access ); @@ -2427,15 +2413,82 @@ void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset pthread_mutex_unlock( &wgl_lock ); } -void wow64_glFlushMappedNamedBufferRangeEXT( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length ) +void wow64_glBufferAttachMemoryNV( TEB *teb, GLenum target, GLuint memory, GLuint64 offset, PFN_glBufferAttachMemoryNV p_glBufferAttachMemoryNV ) { const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_named_buffer( teb, name ))) flush_buffer( teb, buffer, offset, length ); - if (use_driver_buffer_map( buffer )) funcs->p_glFlushMappedNamedBufferRangeEXT( name, offset, length ); + buffer = invalidate_buffer_target( teb, target ); + p_glBufferAttachMemoryNV( target, memory, offset ); pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); +} + +void wow64_glBufferData( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLenum usage, PFN_glBufferData p_glBufferData ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; + + pthread_mutex_lock( &wgl_lock ); + buffer = invalidate_buffer_target( teb, target ); + p_glBufferData( target, size, data, usage ); + pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); +} + +void wow64_glBufferStorageMemEXT( TEB *teb, GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glBufferStorageMemEXT p_glBufferStorageMemEXT ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; + + pthread_mutex_lock( &wgl_lock ); + buffer = invalidate_buffer_target( teb, target ); + p_glBufferStorageMemEXT( target, size, memory, offset ); + pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); +} + +void wow64_glNamedBufferAttachMemoryNV( TEB *teb, GLuint name, GLuint memory, GLuint64 offset, PFN_glNamedBufferAttachMemoryNV p_glNamedBufferAttachMemoryNV ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; + + pthread_mutex_lock( &wgl_lock ); + buffer = invalidate_buffer_name( teb, name ); + p_glNamedBufferAttachMemoryNV( name, memory, offset ); + pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); +} + +void wow64_glNamedBufferData( TEB *teb, GLuint name, GLsizeiptr size, const void *data, GLenum usage, PFN_glNamedBufferData p_glNamedBufferData ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; + + pthread_mutex_lock( &wgl_lock ); + buffer = invalidate_buffer_name( teb, name ); + p_glNamedBufferData( name, size, data, usage ); + pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); +} + +void wow64_glNamedBufferStorageMemEXT( TEB *teb, GLuint name, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glNamedBufferStorageMemEXT p_glNamedBufferStorageMemEXT ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct buffer *buffer; + + pthread_mutex_lock( &wgl_lock ); + buffer = invalidate_buffer_name( teb, name ); + p_glNamedBufferStorageMemEXT( name, size, memory, offset ); + pthread_mutex_unlock( &wgl_lock ); + + if (buffer) free_buffer( funcs, buffer ); } NTSTATUS wow64_thread_attach( void *args ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/unix_wgl.c | 83 +++++++++++++--------------------------- 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 5f5fae6a2a1..b614879911f 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -114,13 +114,6 @@ struct hint_state GLenum multisample_nv; }; -struct buffers -{ - unsigned int ref; - struct rb_tree map; - struct vk_device *vk_device; -}; - struct context { struct opengl_context base; @@ -131,7 +124,6 @@ struct context UINT64 debug_user; /* client pointer */ GLubyte *extensions; /* extension string */ char *wow64_version; /* wow64 GL version override */ - struct buffers *buffers; /* wow64 buffers map */ BOOL use_pinned_memory; /* use GL_AMD_pinned_memory to emulate persistent maps */ /* semi-stub state tracker for wglCopyContext */ @@ -185,7 +177,6 @@ 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; @@ -396,6 +387,12 @@ static int compare_buffer_name( const void *key, const struct rb_entry *entry ) return memcmp( key, &buffer->name, sizeof(buffer->name) ); } +static struct +{ + struct rb_tree map; + struct vk_device *vk_device; +} buffers = { .map = { compare_buffer_name } }; + static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) { if (buffer->vk_memory) @@ -403,34 +400,11 @@ static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer if (buffer->map_ptr) unmap_vk_buffer( buffer ); buffer->vk_device->p_vkFreeMemory( buffer->vk_device->vk_device, buffer->vk_memory, NULL ); } - if (buffer->gl_memory) funcs->p_glDeleteMemoryObjectsEXT( 1, &buffer->gl_memory ); + if (buffer->gl_memory && funcs) funcs->p_glDeleteMemoryObjectsEXT( 1, &buffer->gl_memory ); if (buffer->vm_ptr) NtFreeVirtualMemory( GetCurrentProcess(), &buffer->vm_ptr, &buffer->vm_size, MEM_RELEASE ); free( buffer ); } -static void release_buffers( const struct opengl_funcs *funcs ) -{ - struct buffer *buffer, *next; - - if (--buffers->ref) return; - - 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 = calloc( 1, sizeof(*buffers )))) - { - buffers->ref = 1; - rb_init( &buffers->map, compare_buffer_name ); - } - return buffers; -} - static struct context *context_from_client_context( HGLRC client_context ) { struct opengl_context *base = opengl_context_from_handle( client_context ); @@ -845,7 +819,7 @@ static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) static PFN_vkGetPhysicalDeviceMemoryProperties p_vkGetPhysicalDeviceMemoryProperties; static PFN_vkGetPhysicalDeviceProperties2KHR p_vkGetPhysicalDeviceProperties2KHR; - if (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" ); @@ -906,7 +880,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) ); - buffers->vk_device = vk_device; + buffers.vk_device = vk_device; free( vk_physical_devices ); return TRUE; } @@ -1091,7 +1065,7 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD TRACE( "-- %s (disabled by config)\n", all_extensions[i].name ); } - if (is_win64 && ctx->buffers && !initialize_vk_device( teb, ctx ) + if (is_win64 && is_wow64() && !initialize_vk_device( teb, ctx ) && !(ctx->use_pinned_memory = client->extensions[GL_AMD_pinned_memory])) { if (client->major_version > 4 || (client->major_version == 4 && client->minor_version > 3)) @@ -1121,7 +1095,6 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD 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 ); @@ -1294,8 +1267,6 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, c context->base.client_context = client_context; context->attribs = memdup_attribs( attribs ); - if (is_win64 && is_wow64()) context->buffers = acquire_buffers(); - if (!(funcs->p_context_create( &context->base, hdc, attribs ))) { free_context( funcs, context ); @@ -1768,8 +1739,15 @@ NTSTATUS thread_attach( void *args ) NTSTATUS process_detach( void *args ) { - struct vk_device *vk_device, *next; + struct vk_device *vk_device; + struct buffer *buffer; + void *next; + RB_FOR_EACH_ENTRY_DESTRUCTOR( buffer, next, &buffers.map, struct buffer, entry ) + { + WARN( "Leaked buffer %p\n", buffer ); + free_buffer( NULL, buffer ); + } RB_FOR_EACH_ENTRY_DESTRUCTOR( vk_device, next, &vk_devices, struct vk_device, entry ) { if (vk_device->vk_device) vk_device->p_vkDestroyDevice( vk_device->vk_device, NULL ); @@ -1877,22 +1855,15 @@ static GLuint get_target_name( TEB *teb, GLenum target ) static struct buffer *get_named_buffer( TEB *teb, GLuint name ) { - struct context *ctx = get_current_context( teb, NULL, NULL ); struct rb_entry *entry; - - if (ctx && (entry = rb_get( &ctx->buffers->map, &name ))) - return RB_ENTRY_VALUE( entry, struct buffer, entry ); - return NULL; + if (!(entry = rb_get( &buffers.map, &name ))) return NULL; + return RB_ENTRY_VALUE( entry, struct buffer, entry ); } static struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) { struct buffer *buffer = get_named_buffer( teb, name ); - if (buffer) - { - struct context *ctx = get_current_context( teb, NULL, NULL ); - rb_remove( &ctx->buffers->map, &buffer->entry ); - } + if (buffer) rb_remove( &buffers.map, &buffer->entry ); return buffer; } @@ -1990,7 +1961,7 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam VkResult vr; if (!(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) return NULL; - if ((!(vk_device = ctx->buffers->vk_device) || !vk_device->vk_device) && !ctx->use_pinned_memory) return NULL; + if ((!(vk_device = buffers.vk_device) || !vk_device->vk_device) && !ctx->use_pinned_memory) return NULL; if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; buffer->name = buffer_name; @@ -2010,7 +1981,7 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam * to support it. */ funcs->p_glBindBuffer( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer_name ); funcs->p_glBufferData( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, buffer->vm_ptr, GL_DYNAMIC_COPY ); - rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + rb_put( &buffers.map, &buffer->name, &buffer->entry ); TRACE( "created buffer %p with pinned memory %p\n", buffer, buffer->vm_ptr ); return buffer; } @@ -2077,7 +2048,7 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam funcs->p_glNamedBufferStorageMemEXT( buffer->name, size, buffer->gl_memory, 0 ); else funcs->p_glBufferStorageMemEXT( target, size, buffer->gl_memory, 0 ); - rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + rb_put( &buffers.map, &buffer->name, &buffer->entry ); TRACE( "created buffer_storage %p\n", buffer ); return buffer; } @@ -2108,8 +2079,7 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G .size = VK_WHOLE_SIZE, }; VkResult vr; - struct context *ctx = get_current_context( teb, NULL, NULL ); - struct vk_device *vk_device = ctx->buffers->vk_device; + struct vk_device *vk_device = buffers.vk_device; if (!buffer_vm_alloc( teb, buffer, buffer->size )) return NULL; placed_info.pPlacedAddress = buffer->vm_ptr; @@ -2136,7 +2106,6 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G if (!buffer) { - struct context *ctx = get_current_context( teb, NULL, NULL ); GLint size; if (name) funcs->p_glGetNamedBufferParameteriv( name, GL_BUFFER_SIZE, &size ); @@ -2145,7 +2114,7 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; buffer->name = name ? name : get_target_name( teb, target ); buffer->size = size; - rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + rb_put( &buffers.map, &buffer->name, &buffer->entry ); TRACE( "allocated buffer %p for %u\n", buffer, buffer->name ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
From: Rémi Bernon <rbernon@codeweavers.com> As we now implement implicit buffer names on the PE side, names are now always explicitly, and therefore sequentially, allocated. --- dlls/opengl32/unix_wgl.c | 92 +++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index b614879911f..91ae50af2db 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -142,8 +142,6 @@ struct context struct buffer { - struct rb_entry entry; - GLuint name; size_t size; void *host_ptr; void *map_ptr; @@ -156,7 +154,6 @@ struct buffer struct vk_device *vk_device; VkDeviceMemory vk_memory; GLuint gl_memory; - GLbitfield flags; }; struct vk_device @@ -381,17 +378,13 @@ static void unmap_vk_buffer( struct buffer *buffer ) if (vr) ERR( "VkMemoryUnmapInfoKHR failed: %x\n", vr); } -static int compare_buffer_name( const void *key, const struct rb_entry *entry ) -{ - struct buffer *buffer = RB_ENTRY_VALUE( entry, struct buffer, entry ); - return memcmp( key, &buffer->name, sizeof(buffer->name) ); -} - static struct { - struct rb_tree map; + UINT size; + UINT capacity; + struct buffer **map; struct vk_device *vk_device; -} buffers = { .map = { compare_buffer_name } }; +} buffers; static void free_buffer( const struct opengl_funcs *funcs, struct buffer *buffer ) { @@ -1743,11 +1736,14 @@ NTSTATUS process_detach( void *args ) struct buffer *buffer; void *next; - RB_FOR_EACH_ENTRY_DESTRUCTOR( buffer, next, &buffers.map, struct buffer, entry ) + for (UINT i = 0; i < buffers.size; i++) { + if (!(buffer = buffers.map[i])) continue; WARN( "Leaked buffer %p\n", buffer ); free_buffer( NULL, buffer ); } + free( buffers.map ); + RB_FOR_EACH_ENTRY_DESTRUCTOR( vk_device, next, &vk_devices, struct vk_device, entry ) { if (vk_device->vk_device) vk_device->p_vkDestroyDevice( vk_device->vk_device, NULL ); @@ -1853,18 +1849,40 @@ static GLuint get_target_name( TEB *teb, GLenum target ) return name; } -static struct buffer *get_named_buffer( TEB *teb, GLuint name ) +static struct buffer *set_buffer_storage( GLuint idx, struct buffer *buffer ) +{ + struct buffer *previous = buffer; + + if (idx >= buffers.capacity && buffer) + { + size_t capacity = max( idx + 1, buffers.capacity ? buffers.capacity : 16 ) * 3 / 2; + struct buffer **tmp; + + if (!(tmp = realloc( buffers.map, capacity * sizeof(*tmp) ))) return buffer; + memset( tmp + buffers.capacity, 0, (capacity - buffers.capacity) * sizeof(*tmp) ); + buffers.capacity = capacity; + buffers.map = tmp; + } + if (idx < buffers.capacity) + { + previous = buffers.map[idx]; + buffers.map[idx] = buffer; + buffers.size = max( buffers.size, idx + 1 ); + } + + TRACE( "idx %#x capacity %#x size %#x buffer %p -> %p\n", idx, buffers.capacity, buffers.size, previous, buffer ); + return previous; +} + +static struct buffer *get_named_buffer_storage( TEB *teb, GLuint name ) { - struct rb_entry *entry; - if (!(entry = rb_get( &buffers.map, &name ))) return NULL; - return RB_ENTRY_VALUE( entry, struct buffer, entry ); + if (!name || name > buffers.size) return NULL; + return buffers.map[name - 1]; } static struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) { - struct buffer *buffer = get_named_buffer( teb, name ); - if (buffer) rb_remove( &buffers.map, &buffer->entry ); - return buffer; + return name ? set_buffer_storage( name - 1, NULL ) : NULL; } static struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) @@ -1873,10 +1891,10 @@ static struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) return name ? invalidate_buffer_name( teb, name ) : NULL; } -static struct buffer *get_target_buffer( TEB *teb, GLenum target ) +static struct buffer *get_target_buffer_storage( TEB *teb, GLenum target ) { GLuint name = get_target_name( teb, target ); - return name ? get_named_buffer( teb, name ) : NULL; + return name ? get_named_buffer_storage( teb, name ) : NULL; } static BOOL use_driver_buffer_map( struct buffer *buffer ) @@ -1964,8 +1982,6 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam if ((!(vk_device = buffers.vk_device) || !vk_device->vk_device) && !ctx->use_pinned_memory) return NULL; if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; - buffer->name = buffer_name; - buffer->flags = flags; buffer->size = size; buffer->vk_device = vk_device; @@ -1981,7 +1997,7 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam * to support it. */ funcs->p_glBindBuffer( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer_name ); funcs->p_glBufferData( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, buffer->vm_ptr, GL_DYNAMIC_COPY ); - rb_put( &buffers.map, &buffer->name, &buffer->entry ); + set_buffer_storage( buffer_name - 1, buffer ); TRACE( "created buffer %p with pinned memory %p\n", buffer, buffer->vm_ptr ); return buffer; } @@ -2045,10 +2061,10 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam funcs->p_glCreateMemoryObjectsEXT( 1, &buffer->gl_memory ); funcs->p_glImportMemoryFdEXT( buffer->gl_memory, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd ); if (name) - funcs->p_glNamedBufferStorageMemEXT( buffer->name, size, buffer->gl_memory, 0 ); + funcs->p_glNamedBufferStorageMemEXT( buffer_name, size, buffer->gl_memory, 0 ); else funcs->p_glBufferStorageMemEXT( target, size, buffer->gl_memory, 0 ); - rb_put( &buffers.map, &buffer->name, &buffer->entry ); + set_buffer_storage( buffer_name - 1, buffer ); TRACE( "created buffer_storage %p\n", buffer ); return buffer; } @@ -2112,10 +2128,10 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G else funcs->p_glGetBufferParameteriv( target, GL_BUFFER_SIZE, &size ); if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; - buffer->name = name ? name : get_target_name( teb, target ); + if (!name) name = get_target_name( teb, target ); buffer->size = size; - rb_put( &buffers.map, &buffer->name, &buffer->entry ); - TRACE( "allocated buffer %p for %u\n", buffer, buffer->name ); + set_buffer_storage( name - 1, buffer ); + TRACE( "allocated buffer %p for %u\n", buffer, name ); } buffer->host_ptr = ptr; @@ -2229,7 +2245,7 @@ static BOOL wow64_gl_get_buffer_pointer_v( TEB *teb, GLenum target, GLuint name, if (pname != GL_BUFFER_MAP_POINTER) return FALSE; pthread_mutex_lock( &wgl_lock ); - buffer = name ? get_named_buffer( teb, name ) : get_target_buffer( teb, target ); + buffer = name ? get_named_buffer_storage( teb, name ) : get_target_buffer_storage( teb, target ); if (buffer) { *wow_ptr = PtrToUlong( buffer->map_ptr ); @@ -2263,7 +2279,7 @@ void *wow64_glMapBuffer( TEB *teb, GLenum target, GLenum access, PFN_glMapBuffer void *ptr = NULL; pthread_mutex_lock( &wgl_lock ); - buffer = get_target_buffer( teb, target ); + buffer = get_target_buffer_storage( teb, target ); if (use_driver_buffer_map( buffer )) ptr = p_glMapBuffer( target, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); @@ -2277,7 +2293,7 @@ void *wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeip void *ptr = NULL; pthread_mutex_lock( &wgl_lock ); - buffer = get_target_buffer( teb, target ); + buffer = get_target_buffer_storage( teb, target ); if (use_driver_buffer_map( buffer )) ptr = p_glMapBufferRange( target, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); @@ -2291,7 +2307,7 @@ void *wow64_glMapNamedBuffer( TEB *teb, GLuint name, GLenum access, PFN_glMapNam void *ptr = NULL; pthread_mutex_lock( &wgl_lock ); - buffer = get_named_buffer( teb, name ); + buffer = get_named_buffer_storage( teb, name ); if (use_driver_buffer_map( buffer )) ptr = p_glMapNamedBuffer( name, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, 0, 0, range_access, ptr ); pthread_mutex_unlock( &wgl_lock ); @@ -2305,7 +2321,7 @@ void *wow64_glMapNamedBufferRange( TEB *teb, GLuint name, GLintptr offset, GLsiz void *ptr = NULL; pthread_mutex_lock( &wgl_lock ); - buffer = get_named_buffer( teb, name ); + buffer = get_named_buffer_storage( teb, name ); if (use_driver_buffer_map( buffer )) ptr = p_glMapNamedBufferRange( name, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, offset, length, access, ptr ); pthread_mutex_unlock( &wgl_lock ); @@ -2342,7 +2358,7 @@ GLboolean wow64_glUnmapBuffer( TEB *teb, GLenum target, PFN_glUnmapBuffer p_glUn GLboolean ret; pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_target_buffer( teb, target ))) ret = wow64_unmap_buffer( teb, buffer ); + if ((buffer = get_target_buffer_storage( teb, target ))) ret = wow64_unmap_buffer( teb, buffer ); if (use_driver_buffer_map( buffer )) ret = p_glUnmapBuffer( target ); pthread_mutex_unlock( &wgl_lock ); return ret; @@ -2354,7 +2370,7 @@ GLboolean wow64_glUnmapNamedBuffer( TEB *teb, GLuint name, PFN_glUnmapBuffer p_g GLboolean ret; pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_named_buffer( teb, name ))) ret = wow64_unmap_buffer( teb, buffer ); + if ((buffer = get_named_buffer_storage( teb, name ))) ret = wow64_unmap_buffer( teb, buffer ); if (use_driver_buffer_map( buffer )) ret = p_glUnmapNamedBuffer( name ); pthread_mutex_unlock( &wgl_lock ); return ret; @@ -2366,7 +2382,7 @@ void wow64_glFlushMappedBufferRange( TEB *teb, GLenum target, GLintptr offset, G struct buffer *buffer; pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_target_buffer( teb, target ))) flush_buffer( teb, buffer, offset, length ); + if ((buffer = get_target_buffer_storage( teb, target ))) flush_buffer( teb, buffer, offset, length ); if (use_driver_buffer_map( buffer )) p_glFlushMappedBufferRange( target, offset, length ); pthread_mutex_unlock( &wgl_lock ); } @@ -2377,7 +2393,7 @@ void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset struct buffer *buffer; pthread_mutex_lock( &wgl_lock ); - if ((buffer = get_named_buffer( teb, name ))) flush_buffer( teb, buffer, offset, length ); + if ((buffer = get_named_buffer_storage( teb, name ))) flush_buffer( teb, buffer, offset, length ); if (use_driver_buffer_map( buffer )) p_glFlushMappedNamedBufferRange( name, offset, length ); pthread_mutex_unlock( &wgl_lock ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
From: Rémi Bernon <rbernon@codeweavers.com> Mapping, unmapping and flushing a given buffer is left unguarded, under the assumption that is is undefined to do such calls concurrently. --- dlls/opengl32/unix_wgl.c | 131 ++++++++++++++------------------------- 1 file changed, 46 insertions(+), 85 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 91ae50af2db..67e898699b7 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1849,6 +1849,12 @@ static GLuint get_target_name( TEB *teb, GLenum target ) return name; } +static struct buffer *get_buffer_storage( GLuint idx ) +{ + if (idx < buffers.size) return buffers.map[idx]; + return NULL; +} + static struct buffer *set_buffer_storage( GLuint idx, struct buffer *buffer ) { struct buffer *previous = buffer; @@ -1876,19 +1882,26 @@ static struct buffer *set_buffer_storage( GLuint idx, struct buffer *buffer ) static struct buffer *get_named_buffer_storage( TEB *teb, GLuint name ) { - if (!name || name > buffers.size) return NULL; - return buffers.map[name - 1]; + struct buffer *buffer; + pthread_mutex_lock( &wgl_lock ); + buffer = name ? get_buffer_storage( name - 1 ) : NULL; + pthread_mutex_unlock( &wgl_lock ); + return buffer; } -static struct buffer *invalidate_buffer_name( TEB *teb, GLuint name ) +static struct buffer *set_named_buffer_storage( TEB *teb, GLuint name, struct buffer *buffer ) { - return name ? set_buffer_storage( name - 1, NULL ) : NULL; + struct buffer *previous; + pthread_mutex_lock( &wgl_lock ); + previous = name ? set_buffer_storage( name - 1, buffer ) : NULL; + pthread_mutex_unlock( &wgl_lock ); + return previous; } -static struct buffer *invalidate_buffer_target( TEB *teb, GLenum target ) +static struct buffer *set_target_buffer_storage( TEB *teb, GLenum target, struct buffer *buffer ) { GLuint name = get_target_name( teb, target ); - return name ? invalidate_buffer_name( teb, name ) : NULL; + return name ? set_named_buffer_storage( teb, name, buffer ) : NULL; } static struct buffer *get_target_buffer_storage( TEB *teb, GLenum target ) @@ -1997,7 +2010,6 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam * to support it. */ funcs->p_glBindBuffer( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, buffer_name ); funcs->p_glBufferData( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, size, buffer->vm_ptr, GL_DYNAMIC_COPY ); - set_buffer_storage( buffer_name - 1, buffer ); TRACE( "created buffer %p with pinned memory %p\n", buffer, buffer->vm_ptr ); return buffer; } @@ -2064,7 +2076,6 @@ static struct buffer *create_buffer_storage( TEB *teb, GLenum target, GLuint nam funcs->p_glNamedBufferStorageMemEXT( buffer_name, size, buffer->gl_memory, 0 ); else funcs->p_glBufferStorageMemEXT( target, size, buffer->gl_memory, 0 ); - set_buffer_storage( buffer_name - 1, buffer ); TRACE( "created buffer_storage %p\n", buffer ); return buffer; } @@ -2122,15 +2133,19 @@ static void *wow64_map_buffer( TEB *teb, struct buffer *buffer, GLenum target, G if (!buffer) { + struct buffer *previous; GLint size; if (name) funcs->p_glGetNamedBufferParameteriv( name, GL_BUFFER_SIZE, &size ); else funcs->p_glGetBufferParameteriv( target, GL_BUFFER_SIZE, &size ); if (!(buffer = calloc( 1, sizeof(*buffer) ))) return NULL; - if (!name) name = get_target_name( teb, target ); buffer->size = size; - set_buffer_storage( name - 1, buffer ); + + if (name) previous = set_named_buffer_storage( teb, name, buffer ); + else previous = set_target_buffer_storage( teb, target, buffer ); + assert( !previous ); + TRACE( "allocated buffer %p for %u\n", buffer, name ); } @@ -2184,21 +2199,23 @@ static GLbitfield map_range_flags_from_map_flags( GLenum flags ) } } -void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers, PFN_glDeleteBuffers p_glDeleteBuffers ) +void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *names, PFN_glDeleteBuffers p_glDeleteBuffers ) { const struct opengl_funcs *funcs = teb->glTable; - struct buffer *buffer; + struct buffer **tmp; GLsizei i; - pthread_mutex_lock( &wgl_lock ); - - p_glDeleteBuffers( n, buffers ); - for (i = 0; i < n; i++) + if ((tmp = malloc( n * sizeof(*tmp) ))) { - if ((buffer = invalidate_buffer_name( teb, buffers[i] ))) free_buffer( funcs, buffer ); + pthread_mutex_lock( &wgl_lock ); + for (i = 0; i < n; i++) tmp[i] = names[i] ? set_buffer_storage( names[i] - 1, NULL ) : NULL; + pthread_mutex_unlock( &wgl_lock ); + + for (i = 0; i < n; i++) if (tmp[i]) free_buffer( funcs, tmp[i] ); + free( tmp ); } - pthread_mutex_unlock( &wgl_lock ); + p_glDeleteBuffers( n, names ); } void wow64_glBufferStorage( TEB *teb, GLenum target, GLsizeiptr size, const void *data, @@ -2207,15 +2224,9 @@ void wow64_glBufferStorage( TEB *teb, GLenum target, GLsizeiptr size, const void const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer = NULL, *previous; - pthread_mutex_lock( &wgl_lock ); - previous = invalidate_buffer_target( teb, target ); - - if (flags & GL_MAP_PERSISTENT_BIT) - buffer = create_buffer_storage( teb, target, 0, size, data, flags ); - + if (flags & GL_MAP_PERSISTENT_BIT) buffer = create_buffer_storage( teb, target, 0, size, data, flags ); + previous = set_target_buffer_storage( teb, target, buffer ); if (!buffer) p_glBufferStorage( target, size, data, flags ); - - pthread_mutex_unlock( &wgl_lock ); if (previous) free_buffer( funcs, previous ); } @@ -2225,15 +2236,9 @@ void wow64_glNamedBufferStorage( TEB *teb, GLuint name, GLsizeiptr size, const v const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer = NULL, *previous; - pthread_mutex_lock( &wgl_lock ); - previous = invalidate_buffer_name( teb, name ); - - if (flags & GL_MAP_PERSISTENT_BIT) - buffer = create_buffer_storage( teb, 0, name, size, data, flags ); - + if (flags & GL_MAP_PERSISTENT_BIT) buffer = create_buffer_storage( teb, 0, name, size, data, flags ); + previous = set_named_buffer_storage( teb, name, buffer ); if (!buffer) p_glNamedBufferStorage( name, size, data, flags ); - - pthread_mutex_unlock( &wgl_lock ); if (previous) free_buffer( funcs, previous ); } @@ -2243,15 +2248,11 @@ static BOOL wow64_gl_get_buffer_pointer_v( TEB *teb, GLenum target, GLuint name, BOOL ret = FALSE; if (pname != GL_BUFFER_MAP_POINTER) return FALSE; - - pthread_mutex_lock( &wgl_lock ); - buffer = name ? get_named_buffer_storage( teb, name ) : get_target_buffer_storage( teb, target ); - if (buffer) + if ((buffer = name ? get_named_buffer_storage( teb, name ) : get_target_buffer_storage( teb, target ))) { *wow_ptr = PtrToUlong( buffer->map_ptr ); ret = TRUE; } - pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2278,11 +2279,9 @@ void *wow64_glMapBuffer( TEB *teb, GLenum target, GLenum access, PFN_glMapBuffer struct buffer *buffer; void *ptr = NULL; - pthread_mutex_lock( &wgl_lock ); buffer = get_target_buffer_storage( teb, target ); if (use_driver_buffer_map( buffer )) ptr = p_glMapBuffer( target, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, 0, 0, range_access, ptr ); - pthread_mutex_unlock( &wgl_lock ); return ptr; } @@ -2292,11 +2291,9 @@ void *wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeip struct buffer *buffer; void *ptr = NULL; - pthread_mutex_lock( &wgl_lock ); buffer = get_target_buffer_storage( teb, target ); if (use_driver_buffer_map( buffer )) ptr = p_glMapBufferRange( target, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, target, 0, offset, length, access, ptr ); - pthread_mutex_unlock( &wgl_lock ); return ptr; } @@ -2306,11 +2303,9 @@ void *wow64_glMapNamedBuffer( TEB *teb, GLuint name, GLenum access, PFN_glMapNam struct buffer *buffer; void *ptr = NULL; - pthread_mutex_lock( &wgl_lock ); buffer = get_named_buffer_storage( teb, name ); if (use_driver_buffer_map( buffer )) ptr = p_glMapNamedBuffer( name, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, 0, 0, range_access, ptr ); - pthread_mutex_unlock( &wgl_lock ); return ptr; } @@ -2320,11 +2315,9 @@ void *wow64_glMapNamedBufferRange( TEB *teb, GLuint name, GLintptr offset, GLsiz struct buffer *buffer; void *ptr = NULL; - pthread_mutex_lock( &wgl_lock ); buffer = get_named_buffer_storage( teb, name ); if (use_driver_buffer_map( buffer )) ptr = p_glMapNamedBufferRange( name, offset, length, access ); ptr = wow64_map_buffer( teb, buffer, 0, name, offset, length, access, ptr ); - pthread_mutex_unlock( &wgl_lock ); return ptr; } @@ -2357,10 +2350,8 @@ GLboolean wow64_glUnmapBuffer( TEB *teb, GLenum target, PFN_glUnmapBuffer p_glUn struct buffer *buffer; GLboolean ret; - pthread_mutex_lock( &wgl_lock ); if ((buffer = get_target_buffer_storage( teb, target ))) ret = wow64_unmap_buffer( teb, buffer ); if (use_driver_buffer_map( buffer )) ret = p_glUnmapBuffer( target ); - pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2369,10 +2360,8 @@ GLboolean wow64_glUnmapNamedBuffer( TEB *teb, GLuint name, PFN_glUnmapBuffer p_g struct buffer *buffer; GLboolean ret; - pthread_mutex_lock( &wgl_lock ); if ((buffer = get_named_buffer_storage( teb, name ))) ret = wow64_unmap_buffer( teb, buffer ); if (use_driver_buffer_map( buffer )) ret = p_glUnmapNamedBuffer( name ); - pthread_mutex_unlock( &wgl_lock ); return ret; } @@ -2381,10 +2370,8 @@ void wow64_glFlushMappedBufferRange( TEB *teb, GLenum target, GLintptr offset, G { struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); if ((buffer = get_target_buffer_storage( teb, target ))) flush_buffer( teb, buffer, offset, length ); if (use_driver_buffer_map( buffer )) p_glFlushMappedBufferRange( target, offset, length ); - pthread_mutex_unlock( &wgl_lock ); } void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length, @@ -2392,10 +2379,8 @@ void wow64_glFlushMappedNamedBufferRange( TEB *teb, GLuint name, GLintptr offset { struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); if ((buffer = get_named_buffer_storage( teb, name ))) flush_buffer( teb, buffer, offset, length ); if (use_driver_buffer_map( buffer )) p_glFlushMappedNamedBufferRange( name, offset, length ); - pthread_mutex_unlock( &wgl_lock ); } void wow64_glBufferAttachMemoryNV( TEB *teb, GLenum target, GLuint memory, GLuint64 offset, PFN_glBufferAttachMemoryNV p_glBufferAttachMemoryNV ) @@ -2403,12 +2388,8 @@ void wow64_glBufferAttachMemoryNV( TEB *teb, GLenum target, GLuint memory, GLuin const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, target ); + if ((buffer = set_target_buffer_storage( teb, target, NULL ))) free_buffer( funcs, buffer ); p_glBufferAttachMemoryNV( target, memory, offset ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } void wow64_glBufferData( TEB *teb, GLenum target, GLsizeiptr size, const void *data, GLenum usage, PFN_glBufferData p_glBufferData ) @@ -2416,12 +2397,8 @@ void wow64_glBufferData( TEB *teb, GLenum target, GLsizeiptr size, const void *d const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, target ); + if ((buffer = set_target_buffer_storage( teb, target, NULL ))) free_buffer( funcs, buffer ); p_glBufferData( target, size, data, usage ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } void wow64_glBufferStorageMemEXT( TEB *teb, GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glBufferStorageMemEXT p_glBufferStorageMemEXT ) @@ -2429,12 +2406,8 @@ void wow64_glBufferStorageMemEXT( TEB *teb, GLenum target, GLsizeiptr size, GLui const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_target( teb, target ); + if ((buffer = set_target_buffer_storage( teb, target, NULL ))) free_buffer( funcs, buffer ); p_glBufferStorageMemEXT( target, size, memory, offset ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } void wow64_glNamedBufferAttachMemoryNV( TEB *teb, GLuint name, GLuint memory, GLuint64 offset, PFN_glNamedBufferAttachMemoryNV p_glNamedBufferAttachMemoryNV ) @@ -2442,12 +2415,8 @@ void wow64_glNamedBufferAttachMemoryNV( TEB *teb, GLuint name, GLuint memory, GL const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, name ); + if ((buffer = set_named_buffer_storage( teb, name, NULL ))) free_buffer( funcs, buffer ); p_glNamedBufferAttachMemoryNV( name, memory, offset ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } void wow64_glNamedBufferData( TEB *teb, GLuint name, GLsizeiptr size, const void *data, GLenum usage, PFN_glNamedBufferData p_glNamedBufferData ) @@ -2455,12 +2424,8 @@ void wow64_glNamedBufferData( TEB *teb, GLuint name, GLsizeiptr size, const void const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, name ); + if ((buffer = set_named_buffer_storage( teb, name, NULL ))) free_buffer( funcs, buffer ); p_glNamedBufferData( name, size, data, usage ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } void wow64_glNamedBufferStorageMemEXT( TEB *teb, GLuint name, GLsizeiptr size, GLuint memory, GLuint64 offset, PFN_glNamedBufferStorageMemEXT p_glNamedBufferStorageMemEXT ) @@ -2468,12 +2433,8 @@ void wow64_glNamedBufferStorageMemEXT( TEB *teb, GLuint name, GLsizeiptr size, G const struct opengl_funcs *funcs = teb->glTable; struct buffer *buffer; - pthread_mutex_lock( &wgl_lock ); - buffer = invalidate_buffer_name( teb, name ); + if ((buffer = set_named_buffer_storage( teb, name, NULL ))) free_buffer( funcs, buffer ); p_glNamedBufferStorageMemEXT( name, size, memory, offset ); - pthread_mutex_unlock( &wgl_lock ); - - if (buffer) free_buffer( funcs, buffer ); } NTSTATUS wow64_thread_attach( void *args ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11226
Mapping, unmapping and flushing a given buffer is left unguarded, under the assumption that is is undefined to do such calls concurrently.
This assumption seems questionable, where does it come from? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144454
On Mon Jun 29 18:26:01 2026 +0000, Jacek Caban wrote:
Mapping, unmapping and flushing a given buffer is left unguarded, under the assumption that is is undefined to do such calls concurrently. This assumption seems questionable, where does it come from? The only situation where this could be an issue is with shared contexts used in two different threads, and one thread doing glMapBuffer / glUnmapBuffer while the other does for instance glFlushMappedBufferRange, glBufferData, glMapBuffer, or glUnmapBuffer on the same shared buffer. Each of these is correct to call only in a specific mapped or unmapped buffer state, and I don't see any reasonable scenario where it does anything useful unless guarded externally and the call sequence is correct.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144515
On Tue Jun 30 06:03:12 2026 +0000, Rémi Bernon wrote:
The only situation where this could be an issue is with shared contexts used in two different threads, and one thread doing glMapBuffer / glUnmapBuffer while the other does for instance glFlushMappedBufferRange, glBufferData, glMapBuffer, or glUnmapBuffer on the same shared buffer. Each of these is correct to call only in a specific mapped or unmapped buffer state, and I don't see any reasonable scenario where it does anything useful unless guarded externally and the call sequence is correct. My reading of the spec is that concurrent `glMapBuffer` calls will get you the buffer mapped in one thread and a well specified error in the other. I could imagine handling the error as part of a valid app logic. With this MR, it could crash or corrupt internal data instead.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144538
On Tue Jun 30 12:37:36 2026 +0000, Jacek Caban wrote:
My reading of the spec is that concurrent `glMapBuffer` calls will get you the buffer mapped in one thread and a well specified error in the other. I could imagine handling the error as part of a valid app logic. With this MR, it could crash or corrupt internal data instead. Well, I don't know. Reading the spec Chapter 5 "Shared Objects and Multiple Contexts" it just seems to me that everything is UB when accessing an object across shared context, unless client uses glFlush / glFinish / glFenceSync + glWaitSync to synchronize the changes externally, which makes sense to me.
I don't really mind about this code and my goal is mostly to get as much as possible out of the context, and I would be fine fine leaving the lock as it is, especially since it doesn't even seem to cause contention, but it also doesn't seem necessary to have such wide critical sections. Fwiw Mesa doesn't do any kind of locking in its MapBuffer / UnmapBuffer / BufferData / FlushMappedBufferRange implementation, and reads / writes multiple buffer object fields in a non atomic fashion. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144539
On Tue Jun 30 13:14:57 2026 +0000, Rémi Bernon wrote:
Well, I don't know. Reading the spec Chapter 5 "Shared Objects and Multiple Contexts" it just seems to me that everything is UB when accessing an object across shared context, unless client uses glFlush / glFinish / glFenceSync + glWaitSync to synchronize the changes externally, which makes sense to me. I don't really mind about this code and my goal is mostly to get as much as possible out of the context, and I would be fine fine leaving the lock as it is, especially since it doesn't even seem to cause contention, but it also doesn't seem necessary to have such wide critical sections. Fwiw Mesa doesn't do any kind of locking in its MapBuffer / UnmapBuffer / BufferData / FlushMappedBufferRange implementation, and reads / writes multiple buffer object fields in a non atomic fashion. Right, looking closer, we can probably indeed treat it as undefined.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144639
As we now implement implicit buffer names on the PE side, names are now always explicitly, and therefore sequentially, allocated.
But here we're dealing with Unix names, not PE names. Do you mean that `glGenBuffers` gives those guarantees? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144640
On Fri Jul 3 09:48:13 2026 +0000, Jacek Caban wrote:
As we now implement implicit buffer names on the PE side, names are now always explicitly, and therefore sequentially, allocated. But here we're dealing with Unix names, not PE names. Do you mean that `glGenBuffers` gives those guarantees? It's not specified, but I believe it does in practice. The wglShareLists tests pretty much rely on that behavior and it passes on both AMD/NV on Windows. That doesn't mean that it will be the case on Linux or other platforms, but I believe it's the case nonetheless. Mesa also implements name allocation in a way that has the same characteristic.
We can keep the rb_tree if you think it's better not to assume that, it was mostly an optimization to avoid looking up the entry twice when trying to replace a previous value. It would be nice to have rb_put able to swap values instead of failing if it's already there. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144790
On Fri Jul 3 09:48:12 2026 +0000, Rémi Bernon wrote:
It's not specified, but I believe it does in practice. The wglShareLists tests pretty much rely on that behavior and it passes on both AMD/NV on Windows. That doesn't mean that it will be the case on Linux or other platforms, but I believe it's the case nonetheless. Mesa also implements name allocation in a way that has the same characteristic. We can keep the rb_tree if you think it's better not to assume that, it was mostly an optimization to avoid looking up the entry twice when trying to replace a previous value. It would be nice to have rb_put able to swap values instead of failing if it's already there. Yes, that doesn't seem like something we should depend on, those kinds of dependencies tend to cause hard to reproduce issues. We could introduce a replacing variant of rb_put, though I wouldn't expect it to make a measurable performance difference in this case.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11226#note_144902
participants (3)
-
Jacek Caban (@jacek) -
Rémi Bernon -
Rémi Bernon (@rbernon)