From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/make_opengl | 1 - dlls/opengl32/unix_thunks.c | 4 +- dlls/opengl32/unix_thunks.h | 1 - dlls/opengl32/unix_wgl.c | 108 ++++++++++------------------------- dlls/opengl32/wgl.c | 54 ++++++++++++++++++ include/wine/opengl_driver.h | 7 +++ 6 files changed, 92 insertions(+), 83 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index d799eb2a4d7..8704ec90b13 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -214,7 +214,6 @@ my %manual_unix_thunks = "glGetInteger64v" => 1, "glGetIntegerv" => 1, "glGetString" => 1, - "glGetStringi" => 1, "glGetUnsignedBytevEXT" => 1, "glImportSyncEXT" => 1, "glNamedFramebufferDrawBuffer" => 1, diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 3a93f2e61e0..73ecc42cffb 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -12301,7 +12301,7 @@ static NTSTATUS ext_glGetStringi( void *args ) struct glGetStringi_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; if (!funcs->p_glGetStringi) return STATUS_NOT_IMPLEMENTED; - params->ret = wrap_glGetStringi( params->teb, params->name, params->index ); + params->ret = funcs->p_glGetStringi( params->name, params->index ); return STATUS_SUCCESS; } @@ -55059,7 +55059,7 @@ static NTSTATUS wow64_ext_glGetStringi( void *args ) const GLubyte *ret; const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_glGetStringi) return STATUS_NOT_IMPLEMENTED; - ret = wrap_glGetStringi( teb, params->name, params->index ); + ret = funcs->p_glGetStringi( params->name, params->index ); return return_wow64_string( ret, ¶ms->ret ); } diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index 2c0824e0268..a86626520f4 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -34,7 +34,6 @@ extern void wrap_glFramebufferDrawBuffersEXT( TEB *teb, GLuint framebuffer, GLsi extern void wrap_glFramebufferReadBufferEXT( TEB *teb, GLuint framebuffer, GLenum mode ); extern void wrap_glGetFramebufferParameterivEXT( TEB *teb, GLuint framebuffer, GLenum pname, GLint *params ); extern void wrap_glGetInteger64v( TEB *teb, GLenum pname, GLint64 *data ); -extern const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index ); extern void wrap_glGetUnsignedBytevEXT( TEB *teb, GLenum pname, GLubyte *data ); extern GLsync wrap_glImportSyncEXT( TEB *teb, GLenum external_sync_type, GLintptr external_sync, GLbitfield flags, GLsync handle ); extern void wrap_glNamedFramebufferDrawBuffer( TEB *teb, GLuint framebuffer, GLenum buf ); diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 72c5850c844..98c1d7fc68c 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -653,61 +653,6 @@ static BOOL is_extension_supported( struct context *ctx, const char *extension ) sizeof(ctx->extension_array[0]), string_array_cmp ) != NULL; } -static char *append_extension( char *ptr, const char *name ) -{ - size_t size = strlen( name ); - memcpy( ptr, name, size ); - ptr += size; - *ptr++ = ' '; - return ptr; -} - -/* build the extension string by filtering out the disabled extensions */ -static GLubyte *filter_extensions( struct context *ctx, const char *extensions, const struct opengl_funcs *funcs ) -{ - const char *end, **extra; - size_t size; - char *p, *str; - - size = strlen( extensions ) + 2; - if (funcs->p_glImportMemoryWin32HandleEXT) size += strlen( "GL_EXT_memory_object_win32" ) + 1; - if (funcs->p_glImportSemaphoreWin32HandleEXT) size += strlen( "GL_EXT_semaphore_win32" ) + 1; - for (extra = legacy_extensions; *extra; extra++) size += strlen( *extra ) + 1; - if (!(p = str = malloc( size ))) return NULL; - - TRACE( "GL_EXTENSIONS:\n" ); - - for (;;) - { - while (*extensions == ' ') extensions++; - if (!*extensions) break; - - if (!(end = strchr( extensions, ' ' ))) end = extensions + strlen( extensions ); - memcpy( p, extensions, end - extensions ); - p[end - extensions] = 0; - - if (is_extension_supported( ctx, p )) - { - TRACE( "++ %s\n", p ); - p += end - extensions; - *p++ = ' '; - } - else - { - TRACE( "-- %s (disabled in context)\n", p ); - } - extensions = end; - } - - if (funcs->p_glImportMemoryWin32HandleEXT) p = append_extension( p, "GL_EXT_memory_object_win32" ); - if (funcs->p_glImportSemaphoreWin32HandleEXT) p = append_extension( p, "GL_EXT_semaphore_win32" ); - for (extra = legacy_extensions; *extra; extra++) p = append_extension( p, *extra ); - - if (p != str) --p; - *p = 0; - return (GLubyte *)str; -} - /* Check if any GL extension from the list is supported */ static BOOL is_any_extension_supported( struct context *ctx, const char *extension ) { @@ -809,9 +754,6 @@ static BOOL get_integer( TEB *teb, GLenum pname, GLint *data ) switch (pname) { - case GL_NUM_EXTENSIONS: - *data = ctx->extension_count; - return TRUE; case GL_DRAW_FRAMEBUFFER_BINDING: if (!draw->draw_fbo) break; *data = ctx->draw_fbo; @@ -860,12 +802,6 @@ const GLubyte *wrap_glGetString( TEB *teb, GLenum name ) const char *renderer = funcs->p_wglQueryCurrentRendererStringWINE( WGL_RENDERER_DEVICE_ID_WINE ); return renderer ? (const GLubyte *)renderer : ret; } - if (name == GL_EXTENSIONS) - { - struct context *ctx = get_current_context( teb, NULL, NULL ); - GLubyte **extensions = &ctx->extensions; - if (*extensions || (*extensions = filter_extensions( ctx, (const char *)ret, funcs ))) return *extensions; - } else if (name == GL_VERSION) { struct context *ctx = get_current_context( teb, NULL, NULL ); @@ -876,20 +812,6 @@ const GLubyte *wrap_glGetString( TEB *teb, GLenum name ) return ret; } -const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index ) -{ - const struct opengl_funcs *funcs = teb->glTable; - - if (name == GL_EXTENSIONS) - { - struct context *ctx = get_current_context( teb, NULL, NULL ); - if (index < ctx->extension_count) return (const GLubyte *)ctx->extension_array[index]; - index = -1; - } - - return funcs->p_glGetStringi( name, index ); -} - static int registry_entry_cmp( const void *a, const void *b ) { const struct registry_entry *entry_a = a, *entry_b = b; @@ -1141,6 +1063,20 @@ static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) return FALSE; } +static USHORT *add_extension_index( struct opengl_extensions *extensions, const char *ext, size_t len, USHORT *ptr ) +{ + UINT index = 0; +#define USE_GL_EXT(x) \ + if (++index && !strncmp( #x, ext, len )) \ + { \ + if (extensions->has_ ## x) *ptr++ = index; \ + return ptr; \ + } + ALL_GL_CLIENT_EXTS +#undef USE_GL_EXT + return ptr; +} + static void add_extension( struct opengl_extensions *extensions, const char *ext, size_t len, BOOL set ) { #define USE_GL_EXT(x) if (!strncmp( #x, ext, len )) extensions->has_ ## x = set; else @@ -1339,7 +1275,21 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD ctx->extension_count = j; } - if (TRACE_ON(opengl)) for (i = 0; i < count; i++) TRACE( "++ %s\n", extensions[i] ); + dump_extensions( "Client", &client->extensions ); + + if ((ext = (const char *)funcs->p_glGetString( GL_EXTENSIONS ))) + { + USHORT *ptr = client->compat_indexes; + const char *end; + + for (end = ext; *end; end++) + { + if (*end != ' ') continue; + ptr = add_extension_index( &client->extensions, ext, end - ext, ptr ); + ext = end + 1; + } + if (end > ext) ptr = add_extension_index( &client->extensions, ext, end - ext, ptr ); + } } BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC client_context ) diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 312cc38c263..a959bc17e1c 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -259,6 +259,7 @@ struct context { struct opengl_client_context base; struct handle_table syncs; + char *extensions; }; static struct context *context_from_opengl_client_context( struct opengl_client_context *base ) @@ -304,6 +305,7 @@ static void free_client_context( struct handle_entry *ptr ) { struct context *context = context_from_opengl_client_context( ptr->context ); free_handle( &contexts, ptr ); + free( context->extensions ); free( context ); } @@ -2036,6 +2038,11 @@ void WINAPI glGetIntegerv( GLenum name, GLint *data ) case GL_MINOR_VERSION: *data = ctx->base.minor_version; return; + case GL_NUM_EXTENSIONS: +#define USE_GL_EXT(x) + ctx->base.extensions.has_ ## x + *data = 0 ALL_GL_CLIENT_EXTS + ctx->base.extensions.has_WGL_EXT_extensions_string + ctx->base.extensions.has_WGL_EXT_swap_control; +#undef USE_GL_EXT + return; } if ((status = UNIX_CALL( glGetIntegerv, &args ))) WARN( "glGetIntegerv returned %#lx\n", status ); @@ -2053,9 +2060,23 @@ const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ) #ifndef _WIN64 GLubyte *wow64_str = NULL; #endif + struct context *ctx; TRACE( "name %d, index %d\n", name, index ); + if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + + switch (name) + { + case GL_EXTENSIONS: +#define USE_GL_EXT(x) if (ctx->base.extensions.has_ ## x && !index--) return (const GLubyte *)#x; + ALL_GL_CLIENT_EXTS +#undef USE_GL_EXT + if (ctx->base.extensions.has_WGL_EXT_extensions_string && !index--) return (const GLubyte *)"WGL_EXT_extensions_string"; + if (ctx->base.extensions.has_WGL_EXT_swap_control && !index--) return (const GLubyte *)"WGL_EXT_swap_control"; + return NULL; + } + #ifndef _WIN64 if (UNIX_CALL( glGetStringi, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret ); #endif @@ -2073,6 +2094,7 @@ const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ) const GLubyte * WINAPI glGetString( GLenum name ) { struct glGetString_params args = { .teb = NtCurrentTeb(), .name = name }; + struct context *ctx; NTSTATUS status; #ifndef _WIN64 GLubyte *wow64_str = NULL; @@ -2080,6 +2102,38 @@ const GLubyte * WINAPI glGetString( GLenum name ) TRACE( "name %d\n", name ); + if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + + switch (name) + { + case GL_EXTENSIONS: + if (!ctx->extensions && *ctx->base.compat_indexes) + { + #define USE_GL_EXT(x) #x, + static const char *names[] = { ALL_GL_CLIENT_EXTS }; + #undef USE_GL_EXT + const USHORT *indexes = ctx->base.compat_indexes; + UINT size = 0; + char *ptr; + + for (UINT i = 0; indexes[i]; i++) size += strlen( names[indexes[i] - 1] ) + 1; + if (ctx->base.extensions.has_GL_EXT_memory_object_win32) size += strlen( "GL_EXT_memory_object_win32 " ); + if (ctx->base.extensions.has_GL_EXT_semaphore_win32) size += strlen( "GL_EXT_semaphore_win32 " ); + if (ctx->base.extensions.has_WGL_EXT_extensions_string) size += strlen( "WGL_EXT_extensions_string " ); + if (ctx->base.extensions.has_WGL_EXT_swap_control) size += strlen( "WGL_EXT_swap_control " ); + if (!(ptr = ctx->extensions = malloc( size ))) return NULL; + + for (UINT i = 0; indexes[i]; i++) ptr += sprintf( ptr, "%s ", names[indexes[i] - 1] ); + if (ctx->base.extensions.has_GL_EXT_memory_object_win32) ptr += sprintf( ptr, "GL_EXT_memory_object_win32 " ); + if (ctx->base.extensions.has_GL_EXT_semaphore_win32) ptr += sprintf( ptr, "GL_EXT_semaphore_win32 " ); + if (ctx->base.extensions.has_WGL_EXT_extensions_string) ptr += sprintf( ptr, "WGL_EXT_extensions_string " ); + if (ctx->base.extensions.has_WGL_EXT_swap_control) ptr += sprintf( ptr, "WGL_EXT_swap_control " ); + if (ptr != ctx->extensions) ptr[-1] = 0; + } + + return (const GLubyte *)ctx->extensions; + } + #ifndef _WIN64 if (UNIX_CALL( glGetString, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret ); #endif diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 402e2997869..0141596867f 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -78,8 +78,15 @@ struct opengl_client_context int major_version; int minor_version; struct opengl_extensions extensions; /* exposed client extensions */ +#define USE_GL_EXT(x) +1 + USHORT compat_indexes[1 ALL_GL_CLIENT_EXTS]; /* compat extension indexes */ +#undef USE_GL_EXT }; +/* make sure client context size stays small */ +C_ASSERT( ARRAY_SIZE(((struct opengl_client_context *)0)->compat_indexes) <= 0x10000 ); +C_ASSERT( sizeof(struct opengl_client_context) <= 0x800 ); + static inline struct opengl_client_context *opengl_client_context_from_client( HGLRC client_context ) { return CONTAINING_RECORD( client_context, struct opengl_client_context, obj ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10019