Performance hit measured on a few games (with esync and wined3d), CPU% is the time spent in the syscall dispatcher as measured with `perf top -K` while the game is running, the measured scene is usually right after starting a new game:
* Brink (32-bit, GL, id Tech 4): 550 fps, 3% CPU -> 480 fps, 12% CPU
* Shadow Warrior 2 (64-bit, d3d11): 75 fps, 2% CPU -> 50 fps, 20% CPU
* Hat in Time (64-bit, d3d9, UE3): 220 fps, 5% CPU -> 215 fps, 10% CPU
* Control (64-bit, d3d11): 25 fps, 0% CPU -> 25 fps, 3% CPU
* Obduction (64-bit, d3d11, UE4): 85 fps, 30% CPU -> 80 fps, 30% CPU
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/Makefile.in | 4 +- dlls/opengl32/make_opengl | 16 +++-- dlls/opengl32/unix_thunks.c | 8 ++- dlls/opengl32/unix_wgl.c | 130 +++++++++++++++++------------------- dlls/opengl32/unixlib.h | 6 +- dlls/opengl32/wgl.c | 22 ++++-- 6 files changed, 101 insertions(+), 85 deletions(-)
diff --git a/dlls/opengl32/Makefile.in b/dlls/opengl32/Makefile.in index 16f5ab17120..bd7ddd8d56f 100644 --- a/dlls/opengl32/Makefile.in +++ b/dlls/opengl32/Makefile.in @@ -1,10 +1,12 @@ MODULE = opengl32.dll +UNIXLIB = opengl32.so EXTRADEFS = -DWINE_NO_LONG_TYPES -D_OPENGL32_ IMPORTLIB = opengl32 IMPORTS = user32 gdi32 advapi32 win32u DELAYIMPORTS = glu32 +UNIX_LIBS = -lwin32u
-EXTRADLLFLAGS = -Wl,--image-base,0x7a800000 -mcygwin +EXTRADLLFLAGS = -Wl,--image-base,0x7a800000
C_SRCS = \ thunks.c \ diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 3b67d3d9f61..ad9def8dcec 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -815,6 +815,7 @@ foreach (sort keys %ext_functions)
print OUT "enum unix_funcs\n"; print OUT "{\n"; +print OUT " unix_thread_attach,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -846,11 +847,10 @@ print OUT " GLsizei length;\n"; print OUT " const GLchar *message;\n"; print OUT "};\n\n";
-print OUT "typedef NTSTATUS (*unixlib_function_t)( void *args );\n"; -print OUT "extern const unixlib_function_t __wine_unix_call_funcs[] DECLSPEC_HIDDEN;\n"; -print OUT "#define UNIX_CALL( func, params ) __wine_unix_call_funcs[unix_ ## func]( params )\n"; +print OUT "extern unixlib_handle_t unixlib_handle DECLSPEC_HIDDEN;\n"; +print OUT "#define UNIX_CALL( func, params ) __wine_unix_call( unixlib_handle, unix_ ## func, params )\n\n";
-print OUT "\n#endif /* __WINE_OPENGL32_UNIXLIB_H */\n"; +print OUT "#endif /* __WINE_OPENGL32_UNIXLIB_H */\n"; close OUT;
# @@ -917,6 +917,10 @@ close OUT; open OUT, ">unix_thunks.c" or die "cannot create unix_thunks.c"; print OUT "/* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */\n\n";
+print OUT "#if 0\n"; +print OUT "#pragma makedep unix\n"; +print OUT "#endif\n\n"; + print OUT "#include <stdarg.h>\n"; print OUT "#include <stddef.h>\n\n";
@@ -929,6 +933,7 @@ print OUT "#include "wingdi.h"\n\n"; print OUT "#include "unixlib.h"\n"; print OUT "#include "unix_private.h"\n\n";
+print OUT "extern NTSTATUS thread_attach( void *args ) DECLSPEC_HIDDEN;\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; @@ -968,8 +973,9 @@ foreach (sort keys %ext_functions) print OUT generate_unix_thunk($_, $ext_functions{$_}, "ext"); }
-print OUT "const unixlib_function_t __wine_unix_call_funcs[] =\n"; +print OUT "const unixlib_entry_t __wine_unix_call_funcs[] =\n"; print OUT "{\n"; +print OUT " &thread_attach,\n"; foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 1be25db9a5f..7511621cf67 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -1,5 +1,9 @@ /* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */
+#if 0 +#pragma makedep unix +#endif + #include <stdarg.h> #include <stddef.h>
@@ -12,6 +16,7 @@ #include "unixlib.h" #include "unix_private.h"
+extern NTSTATUS thread_attach( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglCopyContext( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglCreateContext( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglDeleteContext( void *args ) DECLSPEC_HIDDEN; @@ -24141,8 +24146,9 @@ static NTSTATUS ext_wglSwapIntervalEXT( void *args ) return STATUS_SUCCESS; }
-const unixlib_function_t __wine_unix_call_funcs[] = +const unixlib_entry_t __wine_unix_call_funcs[] = { + &thread_attach, &wgl_wglCopyContext, &wgl_wglCreateContext, &wgl_wglDeleteContext, diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index db025734b8c..7c6204d966d 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -18,11 +18,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#if 0 +#pragma makedep unix +#endif + #include "config.h"
#include <stdarg.h> #include <stdlib.h>
+#include <pthread.h> + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -37,14 +43,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(wgl);
-static CRITICAL_SECTION wgl_section; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &wgl_section, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": wgl_section") } -}; -static CRITICAL_SECTION wgl_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER;
/* handle management */
@@ -154,7 +153,7 @@ static GLubyte *filter_extensions_list( const char *extensions, const char *disa const char *end; char *p, *str;
- p = str = HeapAlloc( GetProcessHeap(), 0, strlen( extensions ) + 2 ); + p = str = malloc( strlen( extensions ) + 2 ); if (!str) return NULL;
TRACE( "GL_EXTENSIONS:\n" ); @@ -200,7 +199,7 @@ static GLuint *filter_extensions_index( const char *disabled ) }
funcs->gl.p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count ); - disabled_index = HeapAlloc( GetProcessHeap(), 0, extensions_count * sizeof(*disabled_index) ); + disabled_index = malloc( extensions_count * sizeof(*disabled_index) ); if (!disabled_index) return NULL;
TRACE( "GL_EXTENSIONS:\n" ); @@ -294,14 +293,6 @@ static ULONG query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_IN return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); }
-static char *heap_strdup( const char *str ) -{ - int len = strlen( str ) + 1; - char *ret = HeapAlloc( GetProcessHeap(), 0, len ); - memcpy( ret, str, len ); - return ret; -} - /* build the extension string by filtering out the disabled extensions */ static BOOL filter_extensions( const char *extensions, GLubyte **exts_list, GLuint **disabled_exts ) { @@ -319,13 +310,12 @@ static BOOL filter_extensions( const char *extensions, GLubyte **exts_list, GLui KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer; static WCHAR disabled_extensionsW[] = {'D','i','s','a','b','l','e','d','E','x','t','e','n','s','i','o','n','s',0};
- if (query_reg_value( hkey, disabled_extensionsW, value, sizeof(buffer) )) str = heap_strdup( buffer ); + if (query_reg_value( hkey, disabled_extensionsW, value, sizeof(buffer) )) str = strdup( buffer ); NtClose( hkey ); } if (str) { - if (InterlockedCompareExchangePointer( (void **)&disabled, str, NULL )) - HeapFree( GetProcessHeap(), 0, str ); + if (InterlockedCompareExchangePointer( (void **)&disabled, str, NULL )) free( str ); } else disabled = ""; } @@ -445,12 +435,12 @@ static char *build_extension_list(void) wrap_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count ); capacity = 128 * extensions_count;
- if (!(available_extensions = HeapAlloc( GetProcessHeap(), 0, capacity ))) return NULL; + if (!(available_extensions = malloc( capacity ))) return NULL; for (i = 0; i < extensions_count; ++i) { extension = (char *)wrap_glGetStringi( GL_EXTENSIONS, i ); capacity = max( capacity, len + strlen( extension ) + 2 ); - if (!(tmp = HeapReAlloc( GetProcessHeap(), 0, available_extensions, capacity ))) break; + if (!(tmp = realloc( available_extensions, capacity ))) break; available_extensions = tmp; len += sprintf( available_extensions + len, "%s ", extension ); } @@ -472,13 +462,13 @@ static BOOL is_extension_supported( const char *extension ) char *available_extensions = NULL; BOOL ret = FALSE;
- if (type == HANDLE_CONTEXT) available_extensions = heap_strdup( (const char *)wrap_glGetString( GL_EXTENSIONS ) ); + if (type == HANDLE_CONTEXT) available_extensions = strdup( (const char *)wrap_glGetString( GL_EXTENSIONS ) ); if (!available_extensions) available_extensions = build_extension_list();
if (!available_extensions) ERR( "No OpenGL extensions found, check if your OpenGL setup is correct!\n" ); else ret = check_extension_support( extension, available_extensions );
- HeapFree( GetProcessHeap(), 0, available_extensions ); + free( available_extensions ); return ret; }
@@ -570,11 +560,10 @@ static HGLRC wrap_wglCreateContext( HDC hdc )
if (!funcs) return 0; if (!(drv_ctx = funcs->wgl.p_wglCreateContext( hdc ))) return 0; - if ((context = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context) ))) + if ((context = calloc( 1, sizeof(*context) ))) { context->drv_ctx = drv_ctx; - if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) - HeapFree( GetProcessHeap(), 0, context ); + if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context ); } if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx ); return ret; @@ -634,9 +623,9 @@ static BOOL wrap_wglDeleteContext( HGLRC hglrc ) } if (hglrc == NtCurrentTeb()->glCurrentRC) wrap_wglMakeCurrent( 0, 0 ); ptr->funcs->wgl.p_wglDeleteContext( ptr->u.context->drv_ctx ); - HeapFree( GetProcessHeap(), 0, ptr->u.context->disabled_exts ); - HeapFree( GetProcessHeap(), 0, ptr->u.context->extensions ); - HeapFree( GetProcessHeap(), 0, ptr->u.context ); + free( ptr->u.context->disabled_exts ); + free( ptr->u.context->extensions ); + free( ptr->u.context ); free_handle_ptr( ptr ); return TRUE; } @@ -683,7 +672,7 @@ static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *a } if ((drv_ctx = funcs->ext.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->u.context->drv_ctx : NULL, attribs ))) { - if ((context = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context) ))) + if ((context = calloc( 1, sizeof(*context) ))) { enum wgl_handle_type type = HANDLE_CONTEXT;
@@ -701,7 +690,7 @@ static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *a }
context->drv_ctx = drv_ctx; - if (!(ret = alloc_handle( type, funcs, context ))) HeapFree( GetProcessHeap(), 0, context ); + if (!(ret = alloc_handle( type, funcs, context ))) free( context ); } if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx ); } @@ -817,16 +806,15 @@ static void gl_debug_message_callback( GLenum source, GLenum type, GLuint id, GL .length = length, .message = message, }; - BOOL (WINAPI *callback)( struct wine_gl_debug_message_params *params, ULONG size ); - void **kernel_callback_table; + void *ret_ptr; + ULONG ret_len;
struct wgl_handle *ptr = (struct wgl_handle *)userParam; if (!(params.user_callback = ptr->u.context->debug_callback)) return; params.user_data = ptr->u.context->debug_user;
- kernel_callback_table = NtCurrentTeb()->Peb->KernelCallbackTable; - callback = kernel_callback_table[NtUserCallOpenGLDebugMessageCallback]; - callback( ¶ms, sizeof(params) ); + KeUserModeCallback( NtUserCallOpenGLDebugMessageCallback, ¶ms, sizeof(params), + &ret_ptr, &ret_len ); }
static void WINAPI wrap_glDebugMessageCallback( GLDEBUGPROC callback, const void *userParam ) @@ -868,27 +856,27 @@ static void WINAPI wrap_glDebugMessageCallbackARB( GLDEBUGPROCARB callback, cons NTSTATUS wgl_wglCopyContext( void *args ) { struct wglCopyContext_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglCopyContext( params->hglrcSrc, params->hglrcDst, params->mask ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS wgl_wglCreateContext( void *args ) { struct wglCreateContext_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglCreateContext( params->hDc ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS wgl_wglDeleteContext( void *args ) { struct wglDeleteContext_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglDeleteContext( params->oldContext ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
@@ -902,18 +890,18 @@ NTSTATUS wgl_wglGetProcAddress( void *args ) NTSTATUS wgl_wglMakeCurrent( void *args ) { struct wglMakeCurrent_params *params = args; - if (params->newContext) EnterCriticalSection( &wgl_section ); + if (params->newContext) pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeCurrent( params->hDc, params->newContext ); - if (params->newContext) LeaveCriticalSection( &wgl_section ); + if (params->newContext) pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS wgl_wglShareLists( void *args ) { struct wglShareLists_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglShareLists( params->hrcSrvShare, params->hrcSrvSource ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
@@ -962,89 +950,95 @@ NTSTATUS ext_glGetStringi( void *args ) NTSTATUS ext_wglBindTexImageARB( void *args ) { struct wglBindTexImageARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglBindTexImageARB( params->hPbuffer, params->iBuffer ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglCreateContextAttribsARB( void *args ) { struct wglCreateContextAttribsARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglCreateContextAttribsARB( params->hDC, params->hShareContext, params->attribList ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglCreatePbufferARB( void *args ) { struct wglCreatePbufferARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglCreatePbufferARB( params->hDC, params->iPixelFormat, params->iWidth, params->iHeight, params->piAttribList ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglDestroyPbufferARB( void *args ) { struct wglDestroyPbufferARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglDestroyPbufferARB( params->hPbuffer ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglGetPbufferDCARB( void *args ) { struct wglGetPbufferDCARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglGetPbufferDCARB( params->hPbuffer ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglMakeContextCurrentARB( void *args ) { struct wglMakeContextCurrentARB_params *params = args; - if (params->hglrc) EnterCriticalSection( &wgl_section ); + if (params->hglrc) pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeContextCurrentARB( params->hDrawDC, params->hReadDC, params->hglrc ); - if (params->hglrc) LeaveCriticalSection( &wgl_section ); + if (params->hglrc) pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglQueryPbufferARB( void *args ) { struct wglQueryPbufferARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglQueryPbufferARB( params->hPbuffer, params->iAttribute, params->piValue ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglReleasePbufferDCARB( void *args ) { struct wglReleasePbufferDCARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglReleasePbufferDCARB( params->hPbuffer, params->hDC ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglReleaseTexImageARB( void *args ) { struct wglReleaseTexImageARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglReleaseTexImageARB( params->hPbuffer, params->iBuffer ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; }
NTSTATUS ext_wglSetPbufferAttribARB( void *args ) { struct wglSetPbufferAttribARB_params *params = args; - EnterCriticalSection( &wgl_section ); + pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglSetPbufferAttribARB( params->hPbuffer, params->piAttribList ); - LeaveCriticalSection( &wgl_section ); + pthread_mutex_unlock( &wgl_lock ); + return STATUS_SUCCESS; +} + +NTSTATUS WINAPI thread_attach( void *args ) +{ + NtCurrentTeb()->glTable = &null_opengl_funcs; return STATUS_SUCCESS; } diff --git a/dlls/opengl32/unixlib.h b/dlls/opengl32/unixlib.h index 68e66b47a3a..b76858a2e13 100644 --- a/dlls/opengl32/unixlib.h +++ b/dlls/opengl32/unixlib.h @@ -22293,6 +22293,7 @@ struct wglSwapIntervalEXT_params
enum unix_funcs { + unix_thread_attach, unix_wglCopyContext, unix_wglCreateContext, unix_wglDeleteContext, @@ -25349,8 +25350,7 @@ struct wine_gl_debug_message_params const GLchar *message; };
-typedef NTSTATUS (*unixlib_function_t)( void *args ); -extern const unixlib_function_t __wine_unix_call_funcs[] DECLSPEC_HIDDEN; -#define UNIX_CALL( func, params ) __wine_unix_call_funcs[unix_ ## func]( params ) +extern unixlib_handle_t unixlib_handle DECLSPEC_HIDDEN; +#define UNIX_CALL( func, params ) __wine_unix_call( unixlib_handle, unix_ ## func, params )
#endif /* __WINE_OPENGL32_UNIXLIB_H */ diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 76ce3437a97..3d547783f31 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "config.h" - #include <stdarg.h> #include <stdlib.h> #include <math.h> @@ -40,6 +38,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wgl); WINE_DECLARE_DEBUG_CHANNEL(fps);
+unixlib_handle_t unixlib_handle; + static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
/*********************************************************************** @@ -865,25 +865,33 @@ static BOOL WINAPI call_opengl_debug_message_callback( struct wine_gl_debug_mess return TRUE; }
-extern struct opengl_funcs null_opengl_funcs DECLSPEC_HIDDEN; - /*********************************************************************** * OpenGL initialisation routine */ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { void **kernel_callback_table; + NTSTATUS status;
switch(reason) { case DLL_PROCESS_ATTACH: - NtCurrentTeb()->glTable = &null_opengl_funcs; + if ((status = NtQueryVirtualMemory( GetCurrentProcess(), hinst, MemoryWineUnixFuncs, + &unixlib_handle, sizeof(unixlib_handle), NULL ))) + { + ERR( "Failed to load unixlib, status %#x\n", status ); + return FALSE; + }
kernel_callback_table = NtCurrentTeb()->Peb->KernelCallbackTable; kernel_callback_table[NtUserCallOpenGLDebugMessageCallback] = call_opengl_debug_message_callback; - break; + /* fallthrough */ case DLL_THREAD_ATTACH: - NtCurrentTeb()->glTable = &null_opengl_funcs; + if ((status = UNIX_CALL( thread_attach, NULL ))) + { + WARN( "Failed to initialize thread, status %#x\n", status ); + return FALSE; + } break; } return TRUE;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/wgl.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 3d547783f31..274fd7d5333 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -429,10 +429,10 @@ static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD l
if (needed_size > size) { size = needed_size; - HeapFree(GetProcessHeap(), 0, bitmap); - HeapFree(GetProcessHeap(), 0, gl_bitmap); - bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); - gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + free( bitmap ); + free( gl_bitmap ); + bitmap = calloc( 1, size ); + gl_bitmap = calloc( 1, size ); } if (needed_size != 0) { if (unicode) @@ -496,8 +496,8 @@ static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD l }
glPixelStorei( GL_UNPACK_ALIGNMENT, org_alignment ); - HeapFree(GetProcessHeap(), 0, bitmap); - HeapFree(GetProcessHeap(), 0, gl_bitmap); + free( bitmap ); + free( gl_bitmap ); return ret; }
@@ -658,7 +658,7 @@ static BOOL wglUseFontOutlines_common(HDC hdc, if(needed == GDI_ERROR) goto error;
- buf = HeapAlloc(GetProcessHeap(), 0, needed); + buf = malloc( needed );
if(unicode) GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity); @@ -692,8 +692,7 @@ static BOOL wglUseFontOutlines_common(HDC hdc,
while(!vertices) { - if(vertex_total != -1) - vertices = HeapAlloc(GetProcessHeap(), 0, vertex_total * 3 * sizeof(GLdouble)); + if (vertex_total != -1) vertices = malloc( vertex_total * 3 * sizeof(GLdouble) ); vertex_total = 0;
pph = (TTPOLYGONHEADER*)buf; @@ -767,7 +766,7 @@ static BOOL wglUseFontOutlines_common(HDC hdc, curve[2].y = (curve[1].y + curve[2].y)/2; } num = bezier_approximate(curve, NULL, deviation); - points = HeapAlloc(GetProcessHeap(), 0, num*sizeof(bezier_vector)); + points = malloc( num * sizeof(bezier_vector) ); num = bezier_approximate(curve, points, deviation); vertex_total += num; if(vertices) @@ -783,7 +782,7 @@ static BOOL wglUseFontOutlines_common(HDC hdc, vertices += 3; } } - HeapFree(GetProcessHeap(), 0, points); + free( points ); previous[0] = curve[2].x; previous[1] = curve[2].y; } @@ -808,8 +807,8 @@ error_in_list: if (format == WGL_FONT_POLYGONS) gluTessEndPolygon( tess ); glTranslated( (GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0 ); glEndList(); - HeapFree(GetProcessHeap(), 0, buf); - HeapFree(GetProcessHeap(), 0, vertices); + free( buf ); + free( vertices ); }
error:
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 7c6204d966d..7a6b3bb0ca4 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -104,7 +104,7 @@ static struct wgl_handle *get_handle_ptr( HANDLE handle, enum wgl_handle_type ty if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle) return &wgl_handles[index];
- SetLastError( ERROR_INVALID_HANDLE ); + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return NULL; }
@@ -124,7 +124,7 @@ static HANDLE alloc_handle( enum wgl_handle_type type, struct opengl_funcs *func ptr->u.context = user_ptr; handle = next_handle( ptr, type ); } - else SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); return handle; }
@@ -545,7 +545,7 @@ static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE; if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT ))) { - if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE ); + if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); else ret = src->funcs->wgl.p_wglCopyContext( src->u.context->drv_ctx, dst->u.context->drv_ctx, mask ); } return ret; @@ -592,7 +592,7 @@ static BOOL wrap_wglMakeCurrent( HDC hdc, HGLRC hglrc ) } else { - SetLastError( ERROR_BUSY ); + RtlSetLastWin32Error( ERROR_BUSY ); ret = FALSE; } } @@ -605,7 +605,7 @@ static BOOL wrap_wglMakeCurrent( HDC hdc, HGLRC hglrc ) } else if (!hdc) { - SetLastError( ERROR_INVALID_HANDLE ); + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); ret = FALSE; } return ret; @@ -618,7 +618,7 @@ static BOOL wrap_wglDeleteContext( HGLRC hglrc ) if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE; if (ptr->u.context->tid && ptr->u.context->tid != GetCurrentThreadId()) { - SetLastError( ERROR_BUSY ); + RtlSetLastWin32Error( ERROR_BUSY ); return FALSE; } if (hglrc == NtCurrentTeb()->glCurrentRC) wrap_wglMakeCurrent( 0, 0 ); @@ -638,7 +638,7 @@ static BOOL wrap_wglShareLists( HGLRC hglrcSrc, HGLRC hglrcDst ) if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE; if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT ))) { - if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE ); + if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); else ret = src->funcs->wgl.p_wglShareLists( src->u.context->drv_ctx, dst->u.context->drv_ctx ); } return ret; @@ -661,13 +661,13 @@ static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *a
if (!funcs) { - SetLastError( ERROR_DC_NOT_FOUND ); + RtlSetLastWin32Error( ERROR_DC_NOT_FOUND ); return 0; } if (!funcs->ext.p_wglCreateContextAttribsARB) return 0; if (share && !(share_ptr = get_handle_ptr( share, HANDLE_CONTEXT ))) { - SetLastError( ERROR_INVALID_OPERATION ); + RtlSetLastWin32Error( ERROR_INVALID_OPERATION ); return 0; } if ((drv_ctx = funcs->ext.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->u.context->drv_ctx : NULL, attribs ))) @@ -752,7 +752,7 @@ static BOOL wrap_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC hgl } else { - SetLastError( ERROR_BUSY ); + RtlSetLastWin32Error( ERROR_BUSY ); ret = FALSE; } }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126040
Your paranoid android.
=== debian11 (32 bit report) ===
wmvcore: wmvcore.c:2997: Test failed: Wait timed out.
FWIW more than 75% of the CPU time spent in the syscall dispatcher is reported in xsavec. Forcing xsave / fxsave didn't change much.
This, as well as the measurements above are also probably dependent on the hardware, they were measured with an AMD Ryzen 9 5900X CPU and RX 580 GPU, all graphics settings to lowest.
With something like https://gitlab.winehq.org/wine/wine/-/merge_requests/1324 (though it is just a proof of concept and I have no idea what impact it may have except that it works), I can improve performance almost up to the non-PE version:
* Brink (32-bit, GL, id Tech 4): 550 fps, 3% CPU -> 480 fps, 12% CPU **-> 540 fps, 4% CPU**
* Shadow Warrior 2 (64-bit, d3d11): 75 fps, 2% CPU -> 50 fps, 20% CPU **-> 65 fps, 9% CPU**
* Hat in Time (64-bit, d3d9, UE3): 220 fps, 5% CPU -> 215 fps, 10% CPU **-> 220 fps, 7% CPU**
* Obduction (64-bit, d3d11, UE4): 85 fps, 30% CPU -> 80 fps, 30% CPU **-> 85 fps, 30% CPU**
(I dropped Control because it didn't have any effect and its rendering was broken in all cases)
The Shadow Warrior 2 numbers seem a bit concerning, even after !1324; do we know what's going on there?
There's a lot of calls to glBindBufferBase I believe, I don't have much more details.