From: Jacek Caban jacek@codeweavers.com
And use it to store the client pointer instead of storing it in the buffer data. --- dlls/opengl32/make_opengl | 30 ++- dlls/opengl32/unix_private.h | 2 + dlls/opengl32/unix_thunks.c | 42 +++- dlls/opengl32/unix_thunks.h | 4 +- dlls/opengl32/unix_wgl.c | 362 +++++++++++++++++++++++++---------- 5 files changed, 333 insertions(+), 107 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 60ba6e2d5b1..97a3a1fb950 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -289,6 +289,7 @@ my %map_default_fbo_thunks = my %manual_wow64_wrappers = ( "glClientWaitSync" => 0, + "glDeleteBuffers" => 0, "glDeleteSync" => 0, "glFenceSync" => 0, "glGetBufferPointerv" => 0, @@ -310,6 +311,22 @@ my %manual_wow64_wrappers = "glUnmapNamedBufferEXT" => 1, "glWaitSync" => 0, ); +my %wow64_invalidate_buffer = + ( + "glBufferAttachMemoryNV" => 1, + "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 = ( "glCompileShaderIncludeARB" => "count", @@ -431,6 +448,7 @@ sub generate_unix_thunk($$$$) my $need_lock = $func_ret =~ /HGLRC|HPBUFFERARB/; my $teb = $is_wow64 ? "teb" : "params->teb"; my $ret_stat = "return STATUS_SUCCESS;"; + my $invalidation = ""; my $input_conv = ""; my $output_conv = ""; my $call_args = ""; @@ -531,6 +549,13 @@ sub generate_unix_thunk($$$$) $ret .= "}\n\n"; return $ret; } + if (defined $wow64_invalidate_buffer{$name}) + { + $need_lock = 1; + $invalidation .= $name =~ /NamedBuffer/ + ? " invalidate_buffer_name( $teb, params->buffer );\n" + : " invalidate_buffer_target( $teb, params->target );\n"; + } $ret .= " TEB *teb = get_teb64( params->teb );\n" if $need_wrap || !$use_dc; } else @@ -571,7 +596,7 @@ sub generate_unix_thunk($$$$) } $ret .= " resolve_default_fbo( $teb, TRUE );\n" if defined $resolve_default_fbo_thunks{$name}; $ret .= " push_default_fbo( $teb );\n" if defined $hide_default_fbo_thunks{$name}; - $ret .= " pthread_mutex_lock( &wgl_lock );\n" if $need_lock; + $ret .= " pthread_mutex_lock( &wgl_lock );\n$invalidation" if $need_lock; $ret .= " $ret_expr"; $call_args =~ s/,$/ /; if ($manual_wow64_wrapper) @@ -1392,6 +1417,8 @@ close OUT; open OUT, ">unix_thunks.h" or die "cannot create unix_thunks.h"; print OUT "/* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */\n\n";
+print OUT "typedef ULONG PTR32;\n\n"; + foreach (sort keys %wgl_functions) { next if !needs_wrapper( $_, $wgl_functions{$_} ); @@ -1410,7 +1437,6 @@ foreach (sort keys %ext_functions) }
print OUT "\n#ifdef _WIN64\n"; -print OUT "typedef ULONG PTR32;\n";
foreach (sort keys %wgl_functions) { diff --git a/dlls/opengl32/unix_private.h b/dlls/opengl32/unix_private.h index 4b05a98cccf..9ced126e3ab 100644 --- a/dlls/opengl32/unix_private.h +++ b/dlls/opengl32/unix_private.h @@ -71,6 +71,8 @@ static inline TEB *get_teb64( ULONG teb32 ) return (TEB *)((char *)teb32_ptr + teb32_ptr->WowTebOffset); }
+extern void invalidate_buffer_name( TEB *teb, GLuint name ); +extern void invalidate_buffer_target( TEB *teb, GLenum target ); extern NTSTATUS return_wow64_string( const void *str, PTR32 *wow64_str );
#endif diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 820bd47929f..abec508aafb 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -37327,7 +37327,10 @@ static NTSTATUS wow64_ext_glBufferAttachMemoryNV( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_target( teb, params->target ); funcs->p_glBufferAttachMemoryNV( params->target, params->memory, params->offset ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -37344,7 +37347,10 @@ static NTSTATUS wow64_ext_glBufferData( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -37361,7 +37367,10 @@ static NTSTATUS wow64_ext_glBufferDataARB( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -37425,7 +37434,10 @@ static NTSTATUS wow64_ext_glBufferStorage( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_target( teb, params->target ); funcs->p_glBufferStorage( params->target, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -37443,7 +37455,10 @@ static NTSTATUS wow64_ext_glBufferStorageExternalEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); return STATUS_SUCCESS; } @@ -37460,7 +37475,10 @@ static NTSTATUS wow64_ext_glBufferStorageMemEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_target( teb, params->target ); funcs->p_glBufferStorageMemEXT( params->target, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -41248,8 +41266,7 @@ static NTSTATUS wow64_ext_glDeleteBuffers( void *args ) PTR32 buffers; } *params = args; TEB *teb = get_teb64( params->teb ); - const struct opengl_funcs *funcs = teb->glTable; - funcs->p_glDeleteBuffers( params->n, ULongToPtr(params->buffers) ); + wow64_glDeleteBuffers( teb, params->n, ULongToPtr(params->buffers) ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58106,7 +58123,10 @@ static NTSTATUS wow64_ext_glNamedBufferAttachMemoryNV( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferAttachMemoryNV( params->buffer, params->memory, params->offset ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58123,7 +58143,10 @@ static NTSTATUS wow64_ext_glNamedBufferData( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58140,7 +58163,10 @@ static NTSTATUS wow64_ext_glNamedBufferDataEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58191,7 +58217,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorage( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferStorage( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58208,7 +58237,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorageEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferStorageEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), ULongToPtr(params->data), params->flags ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } @@ -58226,7 +58258,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorageExternalEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + 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 ); return STATUS_SUCCESS; } @@ -58243,7 +58278,10 @@ static NTSTATUS wow64_ext_glNamedBufferStorageMemEXT( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + pthread_mutex_lock( &wgl_lock ); + invalidate_buffer_name( teb, params->buffer ); funcs->p_glNamedBufferStorageMemEXT( params->buffer, (GLsizeiptr)ULongToPtr(params->size), params->memory, params->offset ); + pthread_mutex_unlock( &wgl_lock ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; } diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index 4cb48b7aa7b..8b73b95da33 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -1,5 +1,7 @@ /* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */
+typedef ULONG PTR32; + extern BOOL wrap_wglCopyContext( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ); extern HGLRC wrap_wglCreateContext( TEB *teb, HDC hDc ); extern BOOL wrap_wglDeleteContext( TEB *teb, HGLRC oldContext ); @@ -45,8 +47,8 @@ extern BOOL wrap_wglReleaseTexImageARB( TEB *teb, HPBUFFERARB hPbuffer, int iBuf extern BOOL wrap_wglSetPbufferAttribARB( TEB *teb, HPBUFFERARB hPbuffer, const int *piAttribList );
#ifdef _WIN64 -typedef ULONG PTR32; extern GLenum wow64_glClientWaitSync( TEB *teb, GLsync sync, GLbitfield flags, GLuint64 timeout ); +extern void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers ); extern void wow64_glDeleteSync( TEB *teb, GLsync sync ); extern GLsync wow64_glFenceSync( TEB *teb, GLenum condition, GLbitfield flags ); extern void wow64_glGetBufferPointerv( TEB *teb, GLenum target, GLenum pname, PTR32 *params ); diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 7aa3d20bc7e..d7420a8ca6d 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -40,6 +40,7 @@ #include "unix_private.h"
#include "wine/debug.h" +#include "wine/rbtree.h"
WINE_DEFAULT_DEBUG_CHANNEL(opengl);
@@ -118,6 +119,12 @@ struct hint_state GLenum perspective_correction; };
+struct buffers +{ + unsigned int ref; + struct rb_tree map; +}; + struct context { struct wgl_context base; @@ -131,6 +138,7 @@ struct context GLubyte *extensions; /* extension string */ GLuint *disabled_exts; /* indices of disabled extensions */ GLubyte *wow64_version; /* wow64 GL version override */ + struct buffers *buffers; /* wow64 buffers map */
/* semi-stub state tracker for wglCopyContext */ GLbitfield used; /* context state used bits */ @@ -146,6 +154,16 @@ struct context GLboolean has_viewport; /* whether viewport has been initialized */ };
+struct buffer +{ + struct rb_entry entry; + GLuint name; + size_t size; + void *host_ptr; + void *map_ptr; + size_t copy_length; +}; + struct wgl_handle { UINT handle; @@ -315,6 +333,23 @@ static BOOL copy_context_attributes( TEB *teb, const struct opengl_funcs *funcs, return dst->used != -1 && src->used != -1; }
+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 void release_buffers( struct buffers *buffers ) +{ + struct buffer *buffer, *next; + + if (--buffers->ref) return; + + RB_FOR_EACH_ENTRY_DESTRUCTOR( buffer, next, &buffers->map, struct buffer, entry ) + free( buffer ); + free( buffers ); +} + static struct context *opengl_context_from_handle( TEB *teb, HGLRC handle, const struct opengl_funcs **funcs );
/* update handle context if it has been re-shared with another one */ @@ -332,6 +367,12 @@ static void update_handle_context( TEB *teb, HGLRC handle, struct wgl_handle *pt WARN( "Failed to re-create context for wglShareLists\n" ); return; } + if (shared && shared->buffers) + { + release_buffers( ctx->buffers ); + ctx->buffers = shared->buffers; + ctx->buffers->ref++; + } ctx->share = (HGLRC)-1; /* initial shared context */ copy_context_attributes( teb, funcs, handle, ctx, handle, ctx, ctx->used ); } @@ -1251,6 +1292,24 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC share, const int context->hdc = hdc; context->share = (HGLRC)-1; /* initial shared context */ context->attribs = memdup_attribs( attribs ); + if (is_win64 && is_wow64()) + { + if (share_ctx) + { + context->buffers = share_ctx->buffers; + context->buffers->ref++; + } + else if (!(context->buffers = malloc( sizeof(*context->buffers )))) + { + free_context( context ); + return 0; + } + else + { + context->buffers->ref = 1; + rb_init( &context->buffers->map, compare_buffer_name ); + } + } if (!(funcs->p_wgl_context_reset( &context->base, hdc, share_ctx ? &share_ctx->base : NULL, attribs ))) free_context( context ); else if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) { @@ -2016,16 +2075,6 @@ static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param ) return size; }
-static void *get_buffer_pointer( TEB *teb, GLenum target ) -{ - const struct opengl_funcs *funcs = teb->glTable; - typeof(*funcs->p_glGetBufferPointerv) *func; - void *ptr = NULL; - if (!(func = funcs->p_glGetBufferPointerv)) func = (void *)funcs->p_wglGetProcAddress( "glGetBufferPointerv" ); - if (func) func( target, GL_BUFFER_MAP_POINTER, &ptr ); - return ptr; -} - static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param ) { const struct opengl_funcs *funcs = teb->glTable; @@ -2036,16 +2085,6 @@ static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param ) return size; }
-static void *get_named_buffer_pointer( TEB *teb, GLint buffer ) -{ - const struct opengl_funcs *funcs = teb->glTable; - typeof(*funcs->p_glGetNamedBufferPointerv) *func; - void *ptr = NULL; - if (!(func = funcs->p_glGetNamedBufferPointerv)) func = (void *)funcs->p_wglGetProcAddress( "glGetNamedBufferPointerv" ); - if (func) func( buffer, GL_BUFFER_MAP_POINTER, &ptr ); - return ptr; -} - static void unmap_buffer( TEB *teb, GLenum target ) { const struct opengl_funcs *funcs = teb->glTable; @@ -2062,45 +2101,127 @@ static void unmap_named_buffer( TEB *teb, GLint buffer ) if (func) func( buffer ); }
-static PTR32 wow64_map_buffer( TEB *teb, GLuint name, GLenum target, void *ptr, SIZE_T size, - GLbitfield access, PTR32 *client_ptr ) +static GLuint get_target_name( TEB *teb, GLenum target ) +{ + const struct opengl_funcs *funcs = teb->glTable; + GLenum binding_name; + GLint name = 0; + + switch (target) + { + case GL_ARRAY_BUFFER: binding_name = GL_ARRAY_BUFFER_BINDING; break; + case GL_ATOMIC_COUNTER_BUFFER: binding_name = GL_ATOMIC_COUNTER_BUFFER_BINDING; break; + case GL_COPY_READ_BUFFER: binding_name = GL_COPY_READ_BUFFER_BINDING; break; + case GL_COPY_WRITE_BUFFER: binding_name = GL_COPY_WRITE_BUFFER_BINDING; break; + case GL_DISPATCH_INDIRECT_BUFFER: binding_name = GL_DISPATCH_INDIRECT_BUFFER_BINDING; break; + case GL_DRAW_INDIRECT_BUFFER: binding_name = GL_DRAW_INDIRECT_BUFFER_BINDING; break; + case GL_ELEMENT_ARRAY_BUFFER: binding_name = GL_ELEMENT_ARRAY_BUFFER_BINDING; break; + case GL_PIXEL_PACK_BUFFER: binding_name = GL_PIXEL_PACK_BUFFER_BINDING; break; + case GL_PIXEL_UNPACK_BUFFER: binding_name = GL_PIXEL_UNPACK_BUFFER_BINDING; break; + case GL_QUERY_BUFFER: binding_name = GL_QUERY_BUFFER_BINDING; break; + case GL_SHADER_STORAGE_BUFFER: binding_name = GL_SHADER_STORAGE_BUFFER_BINDING; break; + case GL_TEXTURE_BUFFER: binding_name = GL_TEXTURE_BUFFER_BINDING; break; + case GL_TRANSFORM_FEEDBACK_BUFFER: binding_name = GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; break; + case GL_UNIFORM_BUFFER: binding_name = GL_UNIFORM_BUFFER_BINDING; break; + default: + FIXME( "unknown target %x\n", target ); + return 0; + }; + + funcs->p_glGetIntegerv( binding_name, &name ); + return name; +} + +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; +} + +void invalidate_buffer_name( TEB *teb, GLuint name ) { - static unsigned int once; + struct buffer *buffer = get_named_buffer( teb, name ); + struct context *ctx; + + if (!buffer || !(ctx = get_current_context( teb, NULL, NULL ))) return; + rb_remove( &ctx->buffers->map, &buffer->entry ); + free( buffer ); +} + +void invalidate_buffer_target( TEB *teb, GLenum target ) +{ + GLuint name = get_target_name( teb, target ); + if (name) invalidate_buffer_name( teb, name ); +} + +static struct buffer *get_target_buffer( TEB *teb, GLenum target ) +{ + GLuint name = get_target_name( teb, target ); + return name ? get_named_buffer( teb, name ) : NULL; +} + +static PTR32 wow64_map_buffer( TEB *teb, GLenum target, GLuint name, GLintptr offset, + size_t length, GLbitfield access, void *ptr, PTR32 *client_ptr ) +{ + struct buffer *buffer = get_target_buffer( teb, target ); + + if (!ptr && (!*client_ptr || !buffer)) return 0; + + if (!buffer) + { + struct context *ctx = get_current_context( teb, NULL, NULL ); + + if (!(buffer = calloc( 1, sizeof(*buffer) ))) return 0; + buffer->name = name ? name : get_target_name( teb, target ); + buffer->size = name ? get_named_buffer_param( teb, name, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE ); + rb_put( &ctx->buffers->map, &buffer->name, &buffer->entry ); + TRACE( "allocated buffer %p for %u\n", buffer, buffer->name ); + } + + if (ptr) + { + buffer->host_ptr = ptr; + if (ULongToPtr(PtrToUlong(ptr)) == ptr) /* we're lucky */ + { + buffer->map_ptr = ptr; + TRACE( "returning %p\n", buffer->map_ptr ); + return PtrToUlong( buffer->map_ptr ); + } + } + + if (!offset && !length) length = buffer->size;
if (*client_ptr) /* wow64 pointer provided, map buffer to it */ { - PTR32 ret = *client_ptr; + buffer->map_ptr = UlongToPtr( *client_ptr ); + *client_ptr = 0; + buffer->copy_length = (access & GL_MAP_WRITE_BIT) ? length : 0; if (!(access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT))) { + static int once; if (!once++) FIXME( "Doing a copy of a mapped buffer (expect performance issues)\n" );
- TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*client_ptr) ); - memcpy( UlongToPtr(*client_ptr), ptr, size ); + TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", length, buffer->host_ptr, + buffer->map_ptr ); + memcpy( buffer->map_ptr, buffer->host_ptr, length ); } - - /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */ - *(PTR32 *)ptr = ret; + TRACE( "returning client buffer %p\n", buffer->map_ptr ); *client_ptr = 0; - return ret; + return PtrToUlong( buffer->map_ptr ); }
- if (ULongToPtr(PtrToUlong(ptr)) == ptr) return PtrToUlong(ptr); /* we're lucky */ if (access & GL_MAP_PERSISTENT_BIT) { FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" ); goto unmap; }
- if (!size) size = name ? get_named_buffer_param( teb, name, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE ); - if ((PTR32)size != size) goto unmap; /* overflow */ - if (size < sizeof(PTR32)) - { - FIXME( "Buffer too small for metadata!\n" ); - goto unmap; - } - - *client_ptr = size; + *client_ptr = length; return 0;
unmap: @@ -2124,71 +2245,85 @@ static GLbitfield map_range_flags_from_map_flags( GLenum flags ) } }
-static PTR32 wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access ) +void wow64_glDeleteBuffers( TEB *teb, GLsizei n, const GLuint *buffers ) { - void *wow_ptr; + const struct opengl_funcs *funcs = teb->glTable; + GLsizei i;
- if (ULongToPtr(PtrToUlong(ptr)) == ptr) return 0; /* we're lucky */ + pthread_mutex_lock( &wgl_lock );
- wow_ptr = UlongToPtr(*(PTR32 *)ptr); - if (access & GL_MAP_WRITE_BIT) - { - TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr ); - memcpy( ptr, wow_ptr, size ); - } + funcs->p_glDeleteBuffers( n, buffers ); + for (i = 0; i < n; i++) invalidate_buffer_name( teb, buffers[i] );
- return PtrToUlong( wow_ptr ); + pthread_mutex_unlock( &wgl_lock ); }
-static void wow64_gl_get_buffer_pointer_v( GLenum pname, PTR32 *ptr, PTR32 *wow_ptr ) +static BOOL wow64_gl_get_buffer_pointer_v( TEB *teb, GLenum target, GLuint name, GLenum pname, PTR32 *wow_ptr ) { - if (pname != GL_BUFFER_MAP_POINTER) return; - if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return; /* we're lucky */ - *wow_ptr = ptr[0]; + struct buffer *buffer; + BOOL ret = FALSE; + + 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 ); + if (buffer) + { + *wow_ptr = PtrToUlong( buffer->map_ptr ); + ret = TRUE; + } + pthread_mutex_unlock( &wgl_lock ); + return ret; }
void wow64_glGetBufferPointerv( 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 ); - return wow64_gl_get_buffer_pointer_v( pname, ptr, params ); + *params = PtrToUlong(ptr); }
void wow64_glGetBufferPointervARB( TEB *teb, GLenum target, GLenum pname, PTR32 *params ) { const struct opengl_funcs *funcs = teb->glTable; void *ptr; - funcs->p_glGetBufferPointervARB( target, pname, &ptr ); - return wow64_gl_get_buffer_pointer_v( pname, ptr, params ); + 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 ) { 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_glGetNamedBufferPointerv( buffer, pname, &ptr ); - return wow64_gl_get_buffer_pointer_v( pname, ptr, params ); + *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 ); - return wow64_gl_get_buffer_pointer_v( pname, ptr, params ); + *params = PtrToUlong(ptr); }
static PTR32 wow64_gl_map_buffer( TEB *teb, GLenum target, GLenum access, PTR32 *client_ptr, PFN_glMapBuffer gl_map_buffer64 ) { GLbitfield range_access = map_range_flags_from_map_flags( access ); - void *ptr; - - /* if *ret, we're being called again with a wow64 pointer */ - ptr = *client_ptr ? get_buffer_pointer( teb, target ) : gl_map_buffer64( target, access ); + void *ptr = NULL; + PTR32 ret ;
- return wow64_map_buffer( teb, 0, target, ptr, 0, range_access, client_ptr ); + pthread_mutex_lock( &wgl_lock ); + if (!*client_ptr) ptr = gl_map_buffer64( target, access ); + ret = wow64_map_buffer( teb, target, 0, 0, 0, range_access, ptr, client_ptr ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
PTR32 wow64_glMapBuffer( TEB *teb, GLenum target, GLenum access, PTR32 *client_ptr ) @@ -2206,26 +2341,28 @@ PTR32 wow64_glMapBufferARB( TEB *teb, GLenum target, GLenum access, PTR32 *clien PTR32 wow64_glMapBufferRange( TEB *teb, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, PTR32 *client_ptr ) { const struct opengl_funcs *funcs = teb->glTable; - void *ptr; - - /* already mapped, we're being called again with a wow64 pointer */ - if (*client_ptr) ptr = (char *)get_buffer_pointer( teb, target ); - else ptr = funcs->p_glMapBufferRange( target, offset, length, access ); + void *ptr = NULL; + PTR32 ret;
- return wow64_map_buffer( teb, 0, target, ptr, length, access, client_ptr ); + pthread_mutex_lock( &wgl_lock ); + if (!*client_ptr) ptr = funcs->p_glMapBufferRange( target, offset, length, access ); + ret = wow64_map_buffer( teb, target, 0, offset, length, access, ptr, client_ptr ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
-static PTR32 wow64_gl_map_named_buffer( TEB *teb, GLuint buffer, GLenum access, PTR32 *client_ptr, +static PTR32 wow64_gl_map_named_buffer( TEB *teb, GLuint name, GLenum access, PTR32 *client_ptr, PFN_glMapNamedBuffer gl_map_named_buffer64 ) { GLbitfield range_access = map_range_flags_from_map_flags( access ); - void *ptr; - - /* already mapped, we're being called again with a wow64 pointer */ - if (*client_ptr) ptr = get_named_buffer_pointer( teb, buffer ); - else ptr = gl_map_named_buffer64( buffer, access ); + void *ptr = NULL; + PTR32 ret;
- return wow64_map_buffer( teb, buffer, 0, ptr, 0, range_access, client_ptr ); + pthread_mutex_lock( &wgl_lock ); + if (!*client_ptr) ptr = gl_map_named_buffer64( name, access ); + ret = wow64_map_buffer( teb, 0, name, 0, 0, range_access, ptr, client_ptr ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
PTR32 wow64_glMapNamedBuffer( TEB *teb, GLuint buffer, GLenum access, PTR32 *client_ptr ) @@ -2240,16 +2377,17 @@ PTR32 wow64_glMapNamedBufferEXT( TEB *teb, GLuint buffer, GLenum access, PTR32 * return wow64_gl_map_named_buffer( teb, buffer, access, client_ptr, funcs->p_glMapNamedBufferEXT ); }
-static NTSTATUS wow64_gl_map_named_buffer_range( TEB *teb, GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access, +static NTSTATUS wow64_gl_map_named_buffer_range( TEB *teb, GLuint name, GLintptr offset, GLsizeiptr length, GLbitfield access, PTR32 *client_ptr, PFN_glMapNamedBufferRange gl_map_named_buffer_range64 ) { - void *ptr; - - /* already mapped, we're being called again with a wow64 pointer */ - if (*client_ptr) ptr = get_named_buffer_pointer( teb, buffer ); - else ptr = gl_map_named_buffer_range64( buffer, offset, length, access ); + void *ptr = NULL; + PTR32 ret;
- return wow64_map_buffer( teb, buffer, 0, ptr, length, access, client_ptr ); + pthread_mutex_lock( &wgl_lock ); + if (!*client_ptr) ptr = gl_map_named_buffer_range64( name, offset, length, access ); + ret = wow64_map_buffer( teb, 0, name, offset, length, access, ptr, client_ptr ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
PTR32 wow64_glMapNamedBufferRange( TEB *teb, GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access, PTR32 *client_ptr ) @@ -2264,50 +2402,70 @@ PTR32 wow64_glMapNamedBufferRangeEXT( TEB *teb, GLuint buffer, GLintptr offset, return wow64_gl_map_named_buffer_range( teb, buffer, offset, length, access, client_ptr, funcs->p_glMapNamedBufferRangeEXT ); }
-static PTR32 wow64_unmap_client_buffer( TEB *teb, GLenum target ) +static void wow64_unmap_buffer( struct buffer *buffer, PTR32 *client_ptr ) +{ + if (!buffer->host_ptr) return; + + if (buffer->host_ptr != buffer->map_ptr) + { + if (buffer->copy_length) + { + TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", buffer->copy_length, + buffer->map_ptr, buffer->host_ptr ); + memcpy( buffer->host_ptr, buffer->map_ptr, buffer->copy_length ); + } + *client_ptr = PtrToUlong( buffer->map_ptr ); + } + + buffer->host_ptr = buffer->map_ptr = NULL; +} + +static GLboolean wow64_unmap_target_buffer( TEB *teb, GLenum target, PTR32 *client_ptr, PFN_glUnmapBuffer gl_unmap ) { - PTR32 *ptr; + struct buffer *buffer; + GLboolean ret;
- if (!(ptr = get_buffer_pointer( teb, target ))) return 0; - return wow64_unmap_buffer( ptr, get_buffer_param( teb, target, GL_BUFFER_MAP_LENGTH ), - get_buffer_param( teb, target, GL_BUFFER_ACCESS_FLAGS ) ); + pthread_mutex_lock( &wgl_lock ); + if ((buffer = get_target_buffer( teb, target ))) wow64_unmap_buffer( buffer, client_ptr ); + ret = gl_unmap( target ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
GLboolean wow64_glUnmapBuffer( TEB *teb, GLenum target, PTR32 *client_ptr ) { const struct opengl_funcs *funcs = teb->glTable; - *client_ptr = wow64_unmap_client_buffer( teb, target ); - return funcs->p_glUnmapBuffer( target ); + return wow64_unmap_target_buffer( teb, target, client_ptr, funcs->p_glUnmapBuffer ); }
GLboolean wow64_glUnmapBufferARB( TEB *teb, GLenum target, PTR32 *client_ptr ) { const struct opengl_funcs *funcs = teb->glTable; - *client_ptr = wow64_unmap_client_buffer( teb, target ); - return funcs->p_glUnmapBuffer( target ); + return wow64_unmap_target_buffer( teb, target, client_ptr, funcs->p_glUnmapBufferARB ); }
-static PTR32 wow64_gl_unmap_named_buffer( TEB *teb, GLuint buffer ) +static GLboolean wow64_gl_unmap_named_buffer( TEB *teb, GLuint name, PTR32 *client_ptr, PFN_glUnmapBuffer gl_unmap ) { - PTR32 *ptr; + struct buffer *buffer; + GLboolean ret;
- if (!(ptr = get_named_buffer_pointer( teb, buffer ))) return 0; - return wow64_unmap_buffer( ptr, get_named_buffer_param( teb, buffer, GL_BUFFER_MAP_LENGTH ), - get_named_buffer_param( teb, buffer, GL_BUFFER_ACCESS_FLAGS ) ); + pthread_mutex_lock( &wgl_lock ); + if ((buffer = get_named_buffer( teb, name ))) wow64_unmap_buffer( buffer, client_ptr ); + ret = gl_unmap( name ); + pthread_mutex_unlock( &wgl_lock ); + return ret; }
GLboolean wow64_glUnmapNamedBuffer( TEB *teb, GLuint buffer, PTR32 *client_ptr ) { const struct opengl_funcs *funcs = teb->glTable; - *client_ptr = wow64_gl_unmap_named_buffer( teb, buffer ); - return funcs->p_glUnmapNamedBuffer( buffer ); + return wow64_gl_unmap_named_buffer( teb, buffer, client_ptr, funcs->p_glUnmapNamedBuffer ); }
GLboolean wow64_glUnmapNamedBufferEXT( TEB *teb, GLuint buffer, PTR32 *client_ptr ) { const struct opengl_funcs *funcs = teb->glTable; - *client_ptr = wow64_gl_unmap_named_buffer( teb, buffer ); - return funcs->p_glUnmapNamedBufferEXT( buffer ); + return wow64_gl_unmap_named_buffer( teb, buffer, client_ptr, funcs->p_glUnmapNamedBufferEXT ); }
NTSTATUS wow64_thread_attach( void *args )