From: Matteo Bruni Subject: [PATCH 2/2] opengl32: Fix extension checks on OpenGL core profile contexts. (v3) Message-Id: <1421433535-16017-2-git-send-email-mbruni@codeweavers.com> Date: Fri, 16 Jan 2015 19:38:55 +0100 v2: Also filter the extensions reported by glGetStringi() and the GL functions depending on the disabled extensions. v3: Adapt to the removal of the separate enum in the previous patch. --- dlls/opengl32/make_opengl | 1 + dlls/opengl32/opengl_norm.c | 9 -- dlls/opengl32/wgl.c | 246 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 208 insertions(+), 48 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 9ca5ebd..82c9919 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -237,6 +237,7 @@ sub GenerateThunk($$$$) return "" if $name eq "glDebugEntry"; return "" if $name eq "glGetString"; + return "" if $name eq "glGetIntegerv"; return "" if $func_ref->[2] && $func_ref->[2]->[0] =~ /WGL_/; # If for opengl_norm.c, generate a nice heading otherwise Patrik won't be happy :-) diff --git a/dlls/opengl32/opengl_norm.c b/dlls/opengl32/opengl_norm.c index 52fb00b..34a4892 100644 --- a/dlls/opengl32/opengl_norm.c +++ b/dlls/opengl32/opengl_norm.c @@ -948,15 +948,6 @@ void WINAPI glGetFloatv( GLenum pname, GLfloat* data ) { } /*********************************************************************** - * glGetIntegerv (OPENGL32.@) - */ -void WINAPI glGetIntegerv( GLenum pname, GLint* data ) { - const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; - TRACE("(%d, %p)\n", pname, data ); - funcs->gl.p_glGetIntegerv( pname, data ); -} - -/*********************************************************************** * glGetLightfv (OPENGL32.@) */ void WINAPI glGetLightfv( GLenum light, GLenum pname, GLfloat* params ) { diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 32d241c..1b4c968 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -59,11 +59,12 @@ enum wgl_handle_type struct opengl_context { - DWORD tid; /* thread that the context is current in */ - HDC draw_dc; /* current drawing DC */ - HDC read_dc; /* current reading DC */ - GLubyte *extensions; /* extension string */ - struct wgl_context *drv_ctx; /* driver context */ + DWORD tid; /* thread that the context is current in */ + HDC draw_dc; /* current drawing DC */ + HDC read_dc; /* current reading DC */ + GLubyte *extensions; /* extension string */ + GLuint *disabled_exts; /* indices of disabled extensions */ + struct wgl_context *drv_ctx; /* driver context */ }; struct wgl_handle @@ -162,6 +163,12 @@ static void free_handle_ptr( struct wgl_handle *ptr ) LeaveCriticalSection( &wgl_section ); } +static inline enum wgl_handle_type get_current_context_type(void) +{ + if (!NtCurrentTeb()->glCurrentRC) return HANDLE_CONTEXT; + return (LOWORD(NtCurrentTeb()->glCurrentRC) & HANDLE_TYPE_MASK) >> 12; +} + /*********************************************************************** * wglCopyContext (OPENGL32.@) */ @@ -199,6 +206,7 @@ BOOL WINAPI wglDeleteContext(HGLRC hglrc) } if (hglrc == NtCurrentTeb()->glCurrentRC) 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_handle_ptr( ptr ); @@ -681,9 +689,82 @@ int WINAPI wglGetLayerPaletteEntries(HDC hdc, return 0; } +static BOOL filter_extensions(const char *extensions, GLubyte **exts_list, GLuint **disabled_exts); + +void WINAPI glGetIntegerv(GLenum pname, GLint *data) +{ + const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; + + TRACE("(%d, %p)\n", pname, data); + if (pname == GL_NUM_EXTENSIONS) + { + struct wgl_handle *ptr = get_current_context_ptr(); + if (ptr->u.context->disabled_exts || + filter_extensions(NULL, NULL, &ptr->u.context->disabled_exts)) + { + unsigned int disabled_count = 0; + GLuint *disabled_exts = ptr->u.context->disabled_exts; + GLint count; + + funcs->gl.p_glGetIntegerv(pname, &count); + while (*(disabled_exts++) != ~0u) + disabled_count++; + *data = count - disabled_count; + return; + } + } + return funcs->gl.p_glGetIntegerv(pname, data); +} + +static const GLubyte * WINAPI glGetStringi(GLenum name, GLuint index) +{ + const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; + + TRACE("(%d, %d)\n", name, index); + if (!funcs->ext.p_glGetStringi) + { + void **func_ptr = (void **)&funcs->ext.p_glGetStringi; + *func_ptr = funcs->wgl.p_wglGetProcAddress("glGetStringi"); + if (!funcs->ext.p_glGetStringi) + return NULL; + } + + if (name == GL_EXTENSIONS) + { + struct wgl_handle *ptr = get_current_context_ptr(); + if (ptr->u.context->disabled_exts || + filter_extensions(NULL, NULL, &ptr->u.context->disabled_exts)) + { + unsigned int disabled_count = 0; + GLuint *disabled_exts = ptr->u.context->disabled_exts; + + while (index + disabled_count >= *(disabled_exts++)) + disabled_count++; + return funcs->ext.p_glGetStringi(name, index + disabled_count); + } + } + return funcs->ext.p_glGetStringi(name, index); +} + /* check if the extension is present in the list */ -static BOOL has_extension( const char *list, const char *ext, size_t len ) +static BOOL has_extension(const char *list, const char *ext, size_t len) { + if (!list) + { + const char *gl_ext; + unsigned int i; + GLint extensions_count; + + glGetIntegerv(GL_NUM_EXTENSIONS, &extensions_count); + for (i = 0; i < extensions_count; ++i) + { + gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i); + if (!strcmp(gl_ext, ext)) + return TRUE; + } + return FALSE; + } + while (list) { while (*list == ' ') list++; @@ -701,15 +782,21 @@ static int compar(const void *elt_a, const void *elt_b) { /* Check if a GL extension is supported */ static BOOL is_extension_supported(const char* extension) { + enum wgl_handle_type type = get_current_context_type(); const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; - const char *gl_ext_string = (const char*)glGetString(GL_EXTENSIONS); + const char *gl_ext_string = NULL; size_t len; TRACE("Checking for extension '%s'\n", extension); - if(!gl_ext_string) { - ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n"); - return FALSE; + if (type == HANDLE_CONTEXT) + { + gl_ext_string = (const char*)glGetString(GL_EXTENSIONS); + if (!gl_ext_string) + { + ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n"); + return FALSE; + } } /* We use the GetProcAddress function from the display driver to retrieve function pointers @@ -798,6 +885,11 @@ PROC WINAPI wglGetProcAddress( LPCSTR name ) *func_ptr = driver_func; } + if (!strcmp(name, "glGetIntegerv")) + return (void *)glGetIntegerv; + else if (!strcmp(name, "glGetStringi")) + return (void *)glGetStringi; + TRACE("returning %s -> %p\n", name, ext_ret->func); return ext_ret->func; } @@ -1657,17 +1749,106 @@ GLint WINAPI glDebugEntry( GLint unknown1, GLint unknown2 ) return 0; } +static GLubyte *filter_extensions_list(const char *extensions, const char *disabled) +{ + char *p, *str = NULL; + const char *end; + + p = str = HeapAlloc(GetProcessHeap(), 0, strlen(extensions) + 2); + if (!str) + return NULL; + 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 (!has_extension(disabled, p, strlen(p))) + { + TRACE("++ %s\n", p); + p += end - extensions; + *p++ = ' '; + } + else + { + TRACE("-- %s (disabled by config)\n", p); + } + extensions = end; + } + *p = 0; + return (GLubyte *)str; +} + +static GLuint *filter_extensions_index(const char *disabled) +{ + const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; + const char *ext, *end, *gl_ext; + GLuint *disabled_exts = NULL, *new_disabled_exts; + unsigned int i = 0, j, disabled_size; + GLint extensions_count; + + if (!funcs->ext.p_glGetStringi) + { + void **func_ptr = (void **)&funcs->ext.p_glGetStringi; + *func_ptr = funcs->wgl.p_wglGetProcAddress("glGetStringi"); + if (!funcs->ext.p_glGetStringi) + return NULL; + } + + funcs->gl.p_glGetIntegerv(GL_NUM_EXTENSIONS, &extensions_count); + disabled_size = 2; + disabled_exts = HeapAlloc(GetProcessHeap(), 0, disabled_size * sizeof(*disabled_exts)); + if (!disabled_exts) + return disabled_exts; + for (j = 0; j < extensions_count; ++j) + { + gl_ext = (const char *)funcs->ext.p_glGetStringi(GL_EXTENSIONS, j); + ext = disabled; + for (;;) + { + while (*ext == ' ') + ext++; + if (!*ext) + break; + if (!(end = strchr(ext, ' '))) + end = ext + strlen(ext); + + if (!strncmp(gl_ext, ext, end - ext) && !gl_ext[end - ext]) + { + TRACE("-- %s (disabled by config)\n", gl_ext); + if (i + 1 == disabled_size) + { + disabled_size *= 2; + new_disabled_exts = HeapReAlloc(GetProcessHeap(), 0, disabled_exts, disabled_size * sizeof(*disabled_exts)); + if (!new_disabled_exts) + { + disabled_exts[i] = ~0u; + return disabled_exts; + } + disabled_exts = new_disabled_exts; + } + disabled_exts[i++] = j; + break; + } + ext = end; + } + } + disabled_exts[i] = ~0u; + return disabled_exts; +} + /* build the extension string by filtering out the disabled extensions */ -static GLubyte *filter_extensions( const char *extensions ) +static BOOL filter_extensions(const char *extensions, GLubyte **exts_list, GLuint **disabled_exts) { static const char *disabled; - char *p, *str; - const char *end; + char *str = NULL; TRACE( "GL_EXTENSIONS:\n" ); - if (!extensions) extensions = ""; - if (!disabled) { HKEY hkey; @@ -1692,29 +1873,16 @@ static GLubyte *filter_extensions( const char *extensions ) else disabled = ""; } - if (!disabled[0]) return NULL; - if ((str = HeapAlloc( GetProcessHeap(), 0, strlen(extensions) + 2 ))) - { - p = str; - 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 (!has_extension( disabled, p , strlen( p ))) - { - TRACE("++ %s\n", p ); - p += end - extensions; - *p++ = ' '; - } - else TRACE("-- %s (disabled by config)\n", p ); - extensions = end; - } - *p = 0; - } - return (GLubyte *)str; + if (!disabled[0]) + return FALSE; + + if (extensions && !*exts_list) + *exts_list = filter_extensions_list(extensions, disabled); + + if (!*disabled_exts) + *disabled_exts = filter_extensions_index(disabled); + + return (exts_list && *exts_list) || *disabled_exts; } /*********************************************************************** @@ -1729,7 +1897,7 @@ const GLubyte * WINAPI glGetString( GLenum name ) { struct wgl_handle *ptr = get_current_context_ptr(); if (ptr->u.context->extensions || - ((ptr->u.context->extensions = filter_extensions( (const char *)ret )))) + filter_extensions((const char *)ret, &ptr->u.context->extensions, &ptr->u.context->disabled_exts)) ret = ptr->u.context->extensions; } return ret; -- 2.0.5