From: Jacek Caban <jacek(a)codeweavers.com> --- dlls/opengl32/unix_wgl.c | 188 +++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 88 deletions(-) diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 35600e79e02..9081c9ff615 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -26,6 +26,7 @@ #include <stdarg.h> #include <stdlib.h> +#include <assert.h> #include <pthread.h> @@ -138,10 +139,11 @@ struct context UINT64 debug_callback; /* client pointer */ UINT64 debug_user; /* client pointer */ GLubyte *extensions; /* extension string */ - GLuint *disabled_exts; /* indices of disabled extensions */ char *wow64_version; /* wow64 GL version override */ struct buffers *buffers; /* wow64 buffers map */ GLenum gl_error; /* wrapped GL error */ + const char **exts; /* array of supported extensions */ + size_t exts_count; /* size of supported extensions */ /* semi-stub state tracker for wglCopyContext */ GLbitfield used; /* context state used bits */ @@ -555,60 +557,6 @@ static const char *parse_gl_version( const char *gl_version, int *major, int *mi return ptr; } -static GLuint *filter_extensions_index( TEB *teb, const char *disabled, const char *enabled ) -{ - const struct opengl_funcs *funcs = teb->glTable; - const char *ext, *version; - GLuint *disabled_index; - GLint extensions_count; - unsigned int i = 0, j, len; - int major, minor; - - if (!funcs->p_glGetStringi) - { - void **func_ptr = (void **)&funcs->p_glGetStringi; - *func_ptr = funcs->p_wglGetProcAddress( "glGetStringi" ); - if (!funcs->p_glGetStringi) return NULL; - } - - version = (const char *)funcs->p_glGetString( GL_VERSION ); - parse_gl_version( version, &major, &minor ); - if (major < 3) - return NULL; - - funcs->p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count ); - disabled_index = malloc( extensions_count * sizeof(*disabled_index) ); - if (!disabled_index) return NULL; - - TRACE( "GL_EXTENSIONS:\n" ); - - for (j = 0; j < extensions_count; ++j) - { - ext = (const char *)funcs->p_glGetStringi( GL_EXTENSIONS, j ); - len = strlen( ext ); - - /* We do not support GL_MAP_PERSISTENT_BIT, and hence - * ARB_buffer_storage, on wow64. */ - if (is_win64 && is_wow64() && (!strcmp( ext, "GL_ARB_buffer_storage" ) || !strcmp( ext, "GL_EXT_buffer_storage" ))) - { - TRACE( "-- %s (disabled due to wow64)\n", ext ); - disabled_index[i++] = j; - } - else if (!has_extension( disabled, ext, len ) && (!*enabled || has_extension( enabled, ext, len ))) - { - TRACE( "++ %s\n", ext ); - } - else - { - TRACE( "-- %s (disabled by config)\n", ext ); - disabled_index[i++] = j; - } - } - - disabled_index[i] = ~0u; - return disabled_index; -} - static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) { while (len--) *dst++ = (unsigned char)*src++; @@ -762,7 +710,7 @@ static char *query_opengl_option( const char *name ) } /* build the extension string by filtering out the disabled extensions */ -static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts_list, GLuint **disabled_exts ) +static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts_list ) { static const char *disabled, *enabled; char *str; @@ -779,16 +727,20 @@ static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts } if (extensions && !*exts_list) *exts_list = filter_extensions_list( extensions, disabled, enabled ); - if (!*disabled_exts) *disabled_exts = filter_extensions_index( teb, disabled, enabled ); - return (exts_list && *exts_list) || *disabled_exts; + return exts_list && *exts_list; } -static const GLuint *disabled_extensions_index( TEB *teb ) +static int extensions_entry_cmp( const void *p1, const void *p2 ) { - struct context *ctx = get_current_context( teb, NULL, NULL ); - GLuint **disabled = &ctx->disabled_exts; - if (*disabled || filter_extensions( teb, NULL, NULL, disabled )) return *disabled; - return NULL; + const char *s1 = *(const char **)p1; + const char *s2 = *(const char **)p2; + while (*s1 && *s1 != ' ') + { + if (*s1 != *s2) return (int)*s1 - (int)*s2; + s1++; + s2++; + } + return (!*s2 || *s2 == ' ') ? 0 : -1; } /* Check if a GL extension is supported */ @@ -869,20 +821,9 @@ static BOOL get_default_fbo_integer( struct context *ctx, struct opengl_drawable static BOOL get_integer( TEB *teb, GLenum pname, GLint *data ) { - const struct opengl_funcs *funcs = teb->glTable; struct opengl_drawable *draw, *read; - const GLuint *disabled; struct context *ctx; - if (pname == GL_NUM_EXTENSIONS) - { - funcs->p_glGetIntegerv( pname, data ); - if ((disabled = disabled_extensions_index( teb ))) - while (*disabled++ != ~0u) (*data)--; - *data += ARRAY_SIZE(legacy_extensions) - 1; - return TRUE; - } - if (!(ctx = get_current_context( teb, &draw, &read ))) return FALSE; switch (pname) @@ -893,6 +834,9 @@ static BOOL get_integer( TEB *teb, GLenum pname, GLint *data ) case GL_MINOR_VERSION: *data = ctx->minor_version; return TRUE; + case GL_NUM_EXTENSIONS: + *data = ctx->exts_count; + return TRUE; case GL_DRAW_FRAMEBUFFER_BINDING: if (!draw->draw_fbo) break; *data = ctx->draw_fbo; @@ -917,8 +861,7 @@ const GLubyte *wrap_glGetString( TEB *teb, GLenum name ) { struct context *ctx = get_current_context( teb, NULL, NULL ); GLubyte **extensions = &ctx->extensions; - GLuint **disabled = &ctx->disabled_exts; - if (*extensions || filter_extensions( teb, (const char *)ret, extensions, disabled )) return *extensions; + if (*extensions || filter_extensions( teb, (const char *)ret, extensions )) return *extensions; } else if (name == GL_VERSION) { @@ -933,8 +876,6 @@ const GLubyte *wrap_glGetString( TEB *teb, GLenum name ) const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index ) { const struct opengl_funcs *funcs = teb->glTable; - const GLuint *disabled; - GLint count; if (!funcs->p_glGetStringi) { @@ -944,13 +885,9 @@ const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index ) if (name == GL_EXTENSIONS) { - funcs->p_glGetIntegerv( GL_NUM_EXTENSIONS, &count ); - - if ((disabled = disabled_extensions_index( teb ))) - while (index >= *disabled++) index++; - - if (index >= count && index - count < ARRAY_SIZE(legacy_extensions)) - return (const GLubyte *)legacy_extensions[index - count]; + struct context *ctx = get_current_context( teb, NULL, NULL ); + if (index < ctx->exts_count) return (const GLubyte *)ctx->exts[index]; + index = -1; } return funcs->p_glGetStringi( name, index ); @@ -958,7 +895,7 @@ const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index ) static char *build_extension_list( TEB *teb ) { - GLint len = 0, capacity, i, extensions_count; + GLint len = 0, capacity, i, extensions_count = 0; char *extension, *tmp, *available_extensions; get_integer( teb, GL_NUM_EXTENSIONS, &extensions_count ); @@ -1081,7 +1018,12 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD HGLRC hglrc, struct context *ctx ) { DWORD tid = HandleToULong(teb->ClientId.UniqueThread); + size_t size = ARRAYSIZE(legacy_extensions) - 1, count = 0; const char *version, *rest = ""; + const char **extensions; + int i, j; + + static const char *disabled, *enabled; ctx->tid = tid; teb->glReserved1[0] = draw_hdc; @@ -1093,10 +1035,70 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD if (ctx->major_version) return; /* already synced */ version = (const char *)funcs->p_glGetString( GL_VERSION ); - if (version) parse_gl_version( version, &ctx->major_version, &ctx->minor_version ); + if (version) rest = parse_gl_version( version, &ctx->major_version, &ctx->minor_version ); if (!ctx->major_version) ctx->major_version = 1; TRACE( "context %p version %d.%d\n", ctx, ctx->major_version, ctx->minor_version ); + if (ctx->major_version >= 3) + { + GLint extensions_count; + + if (!funcs->p_glGetStringi) + { + void **func_ptr = (void **)&funcs->p_glGetStringi; + *func_ptr = funcs->p_wglGetProcAddress( "glGetStringi" ); + } + + funcs->p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count ); + size += extensions_count; + if (!(extensions = malloc( size * sizeof(*extensions) ))) return; + for (i = 0; i < extensions_count; i++) extensions[count++] = (const char *)funcs->p_glGetStringi( GL_EXTENSIONS, i ); + } + else + { + const char *str = (const char *)funcs->p_glGetString( GL_EXTENSIONS ); + size_t len = strlen( str ); + const char *p; + char *out; + if (!str) str = ""; + if ((len = strlen( str )) && str[len - 1] == ' ') len--; + if (*str) size++; + for (p = str; p < str + len; p++) if (*p == ' ') size++; + if (!(extensions = malloc( size * sizeof(*extensions) + len + 1 ))) return; + out = (char *)&extensions[size]; + memcpy( out, str, len ); + out[len] = 0; + if (*out) extensions[count++] = out; + while (*out) + { + if (*out == ' ') + { + *out = 0; + extensions[count++] = out + 1; + } + out++; + } + assert( count + ARRAYSIZE(legacy_extensions) - 1 == size ); + } + + if (!disabled && !(disabled = query_opengl_option( "DisabledExtensions" ))) disabled = ""; + if (!enabled && !(enabled = query_opengl_option( "EnabledExtensions" ))) enabled = ""; + if (*enabled || *disabled) + { + for (i = 0, j = 0; i < count; i++) + { + size_t len = strlen( extensions[i] ); + if (!has_extension( disabled, extensions[i], len ) && (!*enabled || has_extension( enabled, extensions[i], len ))) + extensions[j++] = extensions[i]; + else + TRACE( "-- %s (disabled by config)\n", extensions[i] ); + } + count = j; + } + + for (i = 0; legacy_extensions[i]; i++) extensions[count++] = legacy_extensions[i]; + qsort( extensions, count, sizeof(*extensions), extensions_entry_cmp ); + if (is_win64 && is_wow64()) { if (ctx->major_version > 4 || (ctx->major_version == 4 && ctx->minor_version > 3)) @@ -1106,7 +1108,17 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD ctx->minor_version = 3; asprintf( &ctx->wow64_version, "4.3%s", rest ); } + for (i = 0; i < count; i++) + { + if (strcmp( extensions[i], "GL_ARB_buffer_storage" ) && strcmp( extensions[i], "GL_ARB_buffer_storage" )) continue; + FIXME( "Disabling %s extension on wow64\n", extensions[i] ); + if (i != --count) memmove( &extensions[i], &extensions[i + 1], (count - i) * sizeof(extensions[0]) ); + } } + + ctx->exts = extensions; + ctx->exts_count = count; + if (TRACE_ON(opengl)) for (i = 0; i < count; i++) TRACE( "++ %s\n", extensions[i] ); } BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) @@ -1147,7 +1159,7 @@ BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) static void free_context( struct context *ctx ) { free( ctx->wow64_version ); - free( ctx->disabled_exts ); + free( ctx->exts ); free( ctx->extensions ); free( ctx->attribs ); free( ctx ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9263