From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/make_opengl | 1 - dlls/opengl32/tests/opengl.c | 34 ++++++++++---- dlls/opengl32/unix_thunks.c | 4 +- dlls/opengl32/unix_thunks.h | 1 - dlls/opengl32/unix_wgl.c | 86 +++--------------------------------- dlls/opengl32/wgl.c | 75 +++++++++++++++++++++++++++++++ include/wine/opengl_driver.h | 2 + 7 files changed, 111 insertions(+), 92 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 9fc362f9ebe..d9a1228256a 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -218,7 +218,6 @@ my %manual_unix_thunks = "glGetInteger64v" => 1, "glGetIntegerv" => 1, "glGetString" => 1, - "glGetStringi" => 1, "glGetUnsignedBytevEXT" => 1, "glImportSyncEXT" => 1, "glNamedFramebufferDrawBuffer" => 1, diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 107dfc3f9ff..9fb9f90e389 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -58,6 +58,13 @@ static const char *debugstr_ok( const char *cond ) } while (0) #define ok_ret( e, r ) ok_ex( r, ==, e, UINT, "%#x" ) +#define check_gl_error(exp) check_gl_error_(__LINE__, exp) +static void check_gl_error_( unsigned int line, GLenum exp ) +{ + GLenum err = glGetError(); + ok_(__FILE__,line)( err == exp, "glGetError returned %x, expected %x\n", err, exp ); +} + static NTSTATUS (WINAPI *pD3DKMTCreateDCFromMemory)( D3DKMT_CREATEDCFROMMEMORY *desc ); static NTSTATUS (WINAPI *pD3DKMTDestroyDCFromMemory)( const D3DKMT_DESTROYDCFROMMEMORY *desc ); @@ -109,11 +116,12 @@ static PFN_glCopyNamedBufferSubData pglCopyNamedBufferSubData; static PFN_glCreateBuffers pglCreateBuffers; static PFN_glDeleteBuffers pglDeleteBuffers; static PFN_glDeleteSync pglDeleteSync; +static PFN_glFenceSync pglFenceSync; static PFN_glFlushMappedBufferRange pglFlushMappedBufferRange; static PFN_glFlushMappedNamedBufferRange pglFlushMappedNamedBufferRange; static PFN_glGenBuffers pglGenBuffers; +static PFN_glGetStringi pglGetStringi; static PFN_glIsSync pglIsSync; -static PFN_glFenceSync pglFenceSync; static PFN_glMapBuffer pglMapBuffer; static PFN_glMapBufferRange pglMapBufferRange; static PFN_glMapNamedBuffer pglMapNamedBuffer; @@ -197,11 +205,12 @@ static void init_functions(void) GET_PROC(glCreateBuffers) GET_PROC(glDeleteBuffers) GET_PROC(glDeleteSync) + GET_PROC(glFenceSync) GET_PROC(glFlushMappedBufferRange) GET_PROC(glFlushMappedNamedBufferRange) GET_PROC(glGenBuffers) + GET_PROC(glGetStringi) GET_PROC(glIsSync) - GET_PROC(glFenceSync) GET_PROC(glMapBuffer) GET_PROC(glMapBufferRange) GET_PROC(glMapNamedBuffer) @@ -2388,6 +2397,8 @@ static void test_opengl3(HDC hdc) { int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0}; HGLRC gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs); + const GLubyte *ext; + GLint num; if(gl3Ctx == NULL) { @@ -2395,6 +2406,18 @@ static void test_opengl3(HDC hdc) return; } + wglMakeCurrent(hdc, gl3Ctx); + + glGetIntegerv(GL_NUM_EXTENSIONS, &num); + ok(num > 0, "got %u\n", num); + check_gl_error(0); + ext = pglGetStringi(GL_EXTENSIONS, 0); + ok(!!ext, "got %p\n", ext); + check_gl_error(0); + ext = pglGetStringi(GL_EXTENSIONS, num); + ok(!ext, "got %p\n", ext); + check_gl_error(GL_INVALID_VALUE); + wglDeleteContext(gl3Ctx); } @@ -3535,13 +3558,6 @@ static void test_child_window(HWND hwnd, PIXELFORMATDESCRIPTOR *pfd) DestroyWindow(child); } -#define check_gl_error(exp) check_gl_error_(__LINE__, exp) -static void check_gl_error_( unsigned int line, GLenum exp ) -{ - GLenum err = glGetError(); - ok_(__FILE__,line)( err == exp, "glGetError returned %x, expected %x\n", err, exp ); -} - static void test_gl_error( HDC hdc ) { HGLRC rc, old_rc; diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index ae6dd237e75..f7656b811d4 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -12316,7 +12316,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; } @@ -55047,7 +55047,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 ae809c3d353..4cef3c9e99e 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; @@ -1237,6 +1159,7 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD size_t size = ARRAYSIZE(legacy_extensions) - 1, count = 0; const char *version, *rest = "", **extensions, *compat; GLint num = 0; + USHORT *ptr; int i, j; static const char *disabled, *enabled; @@ -1384,7 +1307,12 @@ 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 ); + + ptr = client->compat_extensions; + for (enum opengl_extension *ext = parsed_extensions; *ext != GL_EXTENSION_COUNT; ext++) + if (client->extensions[*ext]) *ptr++ = *ext; + *ptr = GL_EXTENSION_COUNT; } BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC client_context ) diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 40ee985aa93..423edc4e99d 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -277,6 +277,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 ) @@ -322,6 +323,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 ); } @@ -1992,6 +1994,29 @@ GLsync WINAPI glImportSyncEXT( GLenum external_sync_type, GLintptr external_sync return NULL; } +static const enum opengl_extension legacy_extensions[] = +{ + WGL_EXT_extensions_string, + WGL_EXT_swap_control, +}; + +static const char *enum_gl_extensions( struct context *ctx, UINT index, GLint *ret ) +{ + UINT count = 0; + for (enum opengl_extension ext = 0; ext < ARRAY_SIZE(all_extensions); ext++) + { + if (strncmp( all_extensions[ext].name, "GL_", 3 )) continue; + if (ctx->base.extensions[ext] && count++ == index) return all_extensions[ext].name; + } + for (UINT i = 0; i < ARRAY_SIZE(legacy_extensions); i++) + { + enum opengl_extension ext = legacy_extensions[i]; + if (ctx->base.extensions[ext] && count++ == index) return all_extensions[ext].name; + } + if (ret) *ret = count; + return NULL; +} + static BOOL get_integer( struct context *ctx, GLenum name, GLint *data ) { switch (name) @@ -2002,6 +2027,9 @@ static BOOL get_integer( struct context *ctx, GLenum name, GLint *data ) case GL_MINOR_VERSION: *data = ctx->base.minor_version; return TRUE; + case GL_NUM_EXTENSIONS: + enum_gl_extensions( ctx, -1, data ); + return TRUE; } return FALSE; @@ -2019,9 +2047,21 @@ const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ) #ifndef _WIN64 GLubyte *wow64_str = NULL; #endif + struct context *ctx; + const char *str; TRACE( "name %d, index %d\n", name, index ); + if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return NULL; + + switch (name) + { + case GL_EXTENSIONS: + if ((str = enum_gl_extensions( ctx, index, NULL ))) return (const GLubyte *)str; + set_gl_error( GL_INVALID_VALUE ); + return NULL; + } + #ifndef _WIN64 if (UNIX_CALL( glGetStringi, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret ); #endif @@ -2039,6 +2079,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; @@ -2046,6 +2087,40 @@ 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->base.compat_extensions == GL_EXTENSION_COUNT) + { + set_gl_error( GL_INVALID_ENUM ); + return NULL; + } + if (!ctx->extensions) + { + const USHORT *indexes = ctx->base.compat_extensions; + UINT size = 0; + char *ptr; + + for (UINT i = 0; indexes[i] != GL_EXTENSION_COUNT; i++) size += all_extensions[indexes[i]].len + 1; + if (ctx->base.extensions[GL_EXT_memory_object_win32]) size += strlen( "GL_EXT_memory_object_win32 " ); + if (ctx->base.extensions[GL_EXT_semaphore_win32]) size += strlen( "GL_EXT_semaphore_win32 " ); + if (ctx->base.extensions[WGL_EXT_extensions_string]) size += strlen( "WGL_EXT_extensions_string " ); + if (ctx->base.extensions[WGL_EXT_swap_control]) size += strlen( "WGL_EXT_swap_control " ); + if (!(ptr = ctx->extensions = malloc( size ))) return NULL; + + for (UINT i = 0; indexes[i] != GL_EXTENSION_COUNT; i++) ptr += sprintf( ptr, "%s ", all_extensions[indexes[i]].name ); + if (ctx->base.extensions[GL_EXT_memory_object_win32]) ptr += sprintf( ptr, "GL_EXT_memory_object_win32 " ); + if (ctx->base.extensions[GL_EXT_semaphore_win32]) ptr += sprintf( ptr, "GL_EXT_semaphore_win32 " ); + if (ctx->base.extensions[WGL_EXT_extensions_string]) ptr += sprintf( ptr, "WGL_EXT_extensions_string " ); + if (ctx->base.extensions[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 e6616c47224..7702268e2cf 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -77,9 +77,11 @@ struct opengl_client_context int major_version; int minor_version; BOOLEAN extensions[GL_EXTENSION_COUNT]; /* exposed client extensions */ + UINT16 compat_extensions[GL_EXTENSION_COUNT]; /* compat extension indexes */ }; /* make sure client context size stays small */ +C_ASSERT( ARRAY_SIZE(((struct opengl_client_context *)0)->compat_extensions) <= 0x10000 ); C_ASSERT( sizeof(struct opengl_client_context) <= 0x1000 ); static inline struct opengl_client_context *opengl_client_context_from_client( HGLRC client_context ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10019