From: Derek Lesho dlesho@codeweavers.com
--- dlls/opengl32/make_opengl | 6 ++ dlls/opengl32/unix_wgl.c | 166 ++++++++++++++++++++++++++++++++++++++ dlls/opengl32/unixlib.h | 9 +++ dlls/opengl32/wgl.c | 9 +++ 4 files changed, 190 insertions(+)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 501121da317..f619645d10b 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -96,6 +96,8 @@ my %arg_types = "GLint64EXT" => [ "int64", "wine_dbgstr_longlong(%s)" ], "GLintptr" => [ "long", "%Id" ], "GLintptrARB" => [ "long", "%Id" ], + "GLplacedMapMESA" => [ "ptr", "%p" ], + "GLplacedUnmapMESA" => [ "ptr", "%p" ], "GLshort" => [ "long", "%d" ], "GLsizei" => [ "long", "%d" ], "GLsizeiptr" => [ "long", "%Id" ], @@ -1069,6 +1071,7 @@ print OUT " unix_process_attach,\n"; print OUT " unix_thread_attach,\n"; print OUT " unix_process_detach,\n"; print OUT " unix_get_pixel_formats,\n"; +print OUT " unix_mapping_thread,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1194,6 +1197,7 @@ print OUT "extern NTSTATUS process_attach( void *args );\n"; print OUT "extern NTSTATUS thread_attach( void *args );\n"; print OUT "extern NTSTATUS process_detach( void *args );\n"; print OUT "extern NTSTATUS get_pixel_formats( void *args );\n"; +print OUT "extern NTSTATUS mapping_thread( void *args );\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1242,6 +1246,7 @@ print OUT " process_attach,\n"; print OUT " thread_attach,\n"; print OUT " process_detach,\n"; print OUT " get_pixel_formats,\n"; +print OUT " mapping_thread,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -1310,6 +1315,7 @@ print OUT " process_attach,\n"; print OUT " wow64_thread_attach,\n"; print OUT " wow64_process_detach,\n"; print OUT " wow64_get_pixel_formats,\n"; +print OUT " mapping_thread,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 6e6fcdf7607..8f03d52ce29 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -159,6 +159,13 @@ static BOOL has_extension( const char *list, const char *ext, size_t len ) return FALSE; }
+static BOOL wow64_has_placed( const struct opengl_funcs *funcs ) +{ + const char *extensions = (const char *) funcs->gl.p_glGetString( GL_EXTENSIONS ); + + return !!strstr(extensions, "GL_MESA_placed_allocation"); +} + static GLubyte *filter_extensions_list( const char *extensions, const char *disabled ) { const char *end; @@ -650,6 +657,11 @@ static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) return ret; }
+static void wow64_setup_placed(const struct opengl_funcs *funcs); +static void * WINE_GLAPI wow64_placed_map(GLuint size); +static void WINE_GLAPI wow64_placed_unmap(void *addr, GLuint size); +static ULONG_PTR zero_bits = 0; + static HGLRC wrap_wglCreateContext( HDC hdc ) { HGLRC ret = 0; @@ -688,6 +700,8 @@ static BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) teb->glReserved1[1] = hdc; teb->glCurrentRC = hglrc; teb->glTable = (void *)ptr->funcs; + + wow64_setup_placed(ptr->funcs); } } else @@ -851,6 +865,8 @@ static BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, teb->glReserved1[1] = read_hdc; teb->glCurrentRC = hglrc; teb->glTable = (void *)ptr->funcs; + + wow64_setup_placed(ptr->funcs); } } else @@ -2243,6 +2259,154 @@ NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args ) return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT ); }
+ +static void wow64_setup_placed(const struct opengl_funcs *funcs) +{ + SYSTEM_BASIC_INFORMATION info; + typeof(*funcs->ext.p_glSetPlacedAllocatorMESA) *p_set_placed_allocator; + + NtQuerySystemInformation(SystemEmulationBasicInformation, &info, sizeof(info), NULL); + zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff; + + if (!(p_set_placed_allocator = funcs->ext.p_glSetPlacedAllocatorMESA)) + p_set_placed_allocator = (void *)funcs->wgl.p_wglGetProcAddress( "glSetPlacedAllocatorMESA" ); + if (p_set_placed_allocator) + p_set_placed_allocator( wow64_placed_map, wow64_placed_unmap ); +} + + +static int mapping_thread_stop; +static pthread_mutex_t mapping_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t mapping_cond = PTHREAD_COND_INITIALIZER; +static struct +{ + enum + { + MAPPING_CMD_NONE = 0, + MAPPING_CMD_MAP, + MAPPING_CMD_UNMAP, + } cmd; + + + BOOL done; + + union + { + struct + { + /* in */ + unsigned int size; + /* out */ + void *mapping; + } map; + struct + { + /* in */ + void *mapping; + GLuint size; + } unmap; + }; +} map_request; + +static void * WINE_GLAPI wow64_placed_map(GLuint size) +{ + void *mapping = NULL; + SIZE_T alloc_size = size; + + if (!NtCurrentTeb()) + { + /* offload to mapping_thread */ + pthread_mutex_lock( &mapping_lock ); + + while (map_request.cmd != MAPPING_CMD_NONE) + pthread_cond_wait( &mapping_cond, &mapping_lock ); + + map_request.cmd = MAPPING_CMD_MAP; + map_request.map.size = size; + + pthread_cond_broadcast( &mapping_cond ); + + while (!map_request.done) + pthread_cond_wait( &mapping_cond, &mapping_lock ); + + mapping = map_request.map.mapping; + map_request.cmd = MAPPING_CMD_NONE; + map_request.done = FALSE; + + pthread_mutex_unlock( &mapping_lock ); + pthread_cond_broadcast( &mapping_cond ); + return mapping; + } + + if (NtAllocateVirtualMemory(GetCurrentProcess(), &mapping, zero_bits, &alloc_size, + MEM_COMMIT, PAGE_READWRITE)) + { + ERR("NtAllocateVirtualMemory failed\n"); + return NULL; + } + + TRACE("returning placed mapping %p size %x.\n", mapping, size); + + return mapping; +} + +static void WINE_GLAPI wow64_placed_unmap(void *addr, GLuint size) +{ + SIZE_T alloc_size = 0; + + if(!NtCurrentTeb()) + { + /* offload to mapping_thread */ + pthread_mutex_lock( &mapping_lock ); + + while (map_request.cmd != MAPPING_CMD_NONE) + pthread_cond_wait( &mapping_cond, &mapping_lock ); + + map_request.cmd = MAPPING_CMD_UNMAP; + map_request.unmap.mapping = addr; + map_request.unmap.size = size; + + pthread_mutex_unlock( &mapping_lock ); + pthread_cond_broadcast( &mapping_cond ); + + return; + } + + TRACE("unmapping %p.\n", addr); + NtFreeVirtualMemory(GetCurrentProcess(), &addr, &alloc_size, MEM_RELEASE); +} + +NTSTATUS mapping_thread (void *args ) +{ + if (!is_wow64()) + return STATUS_SUCCESS; + + while (!mapping_thread_stop) + { + pthread_mutex_lock( &mapping_lock ); + + while (map_request.cmd == MAPPING_CMD_NONE || map_request.done) + pthread_cond_wait( &mapping_cond, &mapping_lock ); + + if (map_request.cmd == MAPPING_CMD_MAP) + { + map_request.map.mapping = wow64_placed_map(map_request.map.size); + map_request.done = TRUE; + } + else if (map_request.cmd == MAPPING_CMD_UNMAP) + { + wow64_placed_unmap(map_request.unmap.mapping, map_request.unmap.size); + map_request.cmd = MAPPING_CMD_NONE; + } + + pthread_cond_broadcast( &mapping_cond ); + + pthread_mutex_unlock( &mapping_lock ); + } + + return STATUS_SUCCESS; +} + NTSTATUS wow64_thread_attach( void *args ) { return thread_attach( get_teb64( (ULONG_PTR)args )); @@ -2252,6 +2416,8 @@ NTSTATUS wow64_process_detach( void *args ) { NTSTATUS status;
+ mapping_thread_stop = 1; + if ((status = process_detach( NULL ))) return status;
free( wow64_strings ); diff --git a/dlls/opengl32/unixlib.h b/dlls/opengl32/unixlib.h index 3eea4745aa1..def4ba7bae4 100644 --- a/dlls/opengl32/unixlib.h +++ b/dlls/opengl32/unixlib.h @@ -18658,6 +18658,13 @@ struct glSetMultisamplefvAMD_params const GLfloat *val; };
+struct glSetPlacedAllocatorMESA_params +{ + TEB *teb; + GLplacedMapMESA placedMap; + GLplacedUnmapMESA placedUnmap; +}; + struct glShaderBinary_params { TEB *teb; @@ -25343,6 +25350,7 @@ enum unix_funcs unix_thread_attach, unix_process_detach, unix_get_pixel_formats, + unix_mapping_thread, unix_wglCopyContext, unix_wglCreateContext, unix_wglDeleteContext, @@ -27578,6 +27586,7 @@ enum unix_funcs unix_glSetInvariantEXT, unix_glSetLocalConstantEXT, unix_glSetMultisamplefvAMD, + unix_glSetPlacedAllocatorMESA, unix_glShaderBinary, unix_glShaderOp1EXT, unix_glShaderOp2EXT, diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index c6414054ff5..4f4ac461185 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -1888,6 +1888,12 @@ static NTSTATUS WINAPI call_gl_debug_message_callback( void *args, ULONG size ) return STATUS_SUCCESS; }
+static DWORD WINAPI mapping_thread(LPVOID param) +{ + UNIX_CALL( mapping_thread, NULL ); + return 0; +} + /*********************************************************************** * OpenGL initialisation routine */ @@ -1909,6 +1915,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) return FALSE; }
+ if (NtCurrentTeb()->WowTebOffset) + CreateThread(NULL, 0, mapping_thread, NULL, 0, NULL); + /* fallthrough */ case DLL_THREAD_ATTACH: if ((status = UNIX_CALL( thread_attach, NtCurrentTeb() )))