From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/make_opengl | 2 +- dlls/opengl32/opengl_ext.h | 9 --- dlls/opengl32/unix_thunks.c | 9 +-- dlls/opengl32/unix_wgl.c | 107 +++++++++++++++++++++++++++++++++++- dlls/opengl32/wgl.c | 90 ++---------------------------- 5 files changed, 113 insertions(+), 104 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 1ebd6e01bb8..16f582a6f2a 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -508,7 +508,7 @@ sub needs_wrapper($$) { my ($name, $func) = @_;
- return 1 if $name =~ /^glDebugMessageCallback|^glGetString|^glGetIntegerv/; + return 1 if $name =~ /^glDebugMessageCallback|^glGetString|^glGetIntegerv|^wglGetProcAddress/;
# check if return value needs special handling (my $type = $func->[0]->textContent()) =~ s/ $//; diff --git a/dlls/opengl32/opengl_ext.h b/dlls/opengl32/opengl_ext.h index 7b19e302e82..c668e92fd9b 100644 --- a/dlls/opengl32/opengl_ext.h +++ b/dlls/opengl32/opengl_ext.h @@ -94,15 +94,6 @@ static inline struct wgl_handle *get_current_context_ptr(void) return &wgl_handles[LOWORD(NtCurrentTeb()->glCurrentRC) & ~HANDLE_TYPE_MASK]; }
-static inline enum wgl_handle_type get_current_context_type(void) -{ - if (!NtCurrentTeb()->glCurrentRC) return HANDLE_CONTEXT; - return LOWORD(NtCurrentTeb()->glCurrentRC) & HANDLE_TYPE_MASK; -} - extern int WINAPI wglDescribePixelFormat( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd );
-extern BOOL check_extension_support( const char *extension, const char *available_extensions ) DECLSPEC_HIDDEN; -extern char *build_extension_list(void) DECLSPEC_HIDDEN; - #endif /* __DLLS_OPENGL32_OPENGL_EXT_H */ diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 3306a446c7f..515a765f0a7 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -16,6 +16,7 @@ extern NTSTATUS wgl_wglCopyContext( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglCreateContext( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglDeleteContext( void *args ) DECLSPEC_HIDDEN; +extern NTSTATUS wgl_wglGetProcAddress( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglMakeCurrent( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS wgl_wglShareLists( void *args ) DECLSPEC_HIDDEN; extern NTSTATUS gl_glGetIntegerv( void *args ) DECLSPEC_HIDDEN; @@ -53,14 +54,6 @@ static NTSTATUS wgl_wglGetPixelFormat( void *args ) return STATUS_SUCCESS; }
-static NTSTATUS wgl_wglGetProcAddress( void *args ) -{ - struct wglGetProcAddress_params *params = args; - const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; - params->ret = funcs->wgl.p_wglGetProcAddress( params->lpszProc ); - return STATUS_SUCCESS; -} - static NTSTATUS wgl_wglSetPixelFormat( void *args ) { struct wglSetPixelFormat_params *params = args; diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 3213bfcb6bc..ada4dbe5498 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -194,6 +194,14 @@ static GLuint *filter_extensions_index( const char *disabled ) return disabled_index; }
+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 ) { @@ -238,7 +246,7 @@ static const GLuint *disabled_extensions_index(void) }
/* Check if a GL extension is supported */ -BOOL check_extension_support( const char *extension, const char *available_extensions ) +static BOOL check_extension_support( const char *extension, const char *available_extensions ) { const struct opengl_funcs *funcs = NtCurrentTeb()->glTable; size_t len; @@ -330,7 +338,7 @@ static const GLubyte * WINAPI wrap_glGetStringi( GLenum name, GLuint index ) return funcs->ext.p_glGetStringi( name, index ); }
-char *build_extension_list(void) +static char *build_extension_list(void) { GLint len = 0, capacity, i, extensions_count; char *extension, *tmp, *available_extensions; @@ -352,6 +360,94 @@ char *build_extension_list(void) return available_extensions; }
+static inline enum wgl_handle_type get_current_context_type(void) +{ + if (!NtCurrentTeb()->glCurrentRC) return HANDLE_CONTEXT; + return LOWORD(NtCurrentTeb()->glCurrentRC) & HANDLE_TYPE_MASK; +} + +/* Check if a GL extension is supported */ +static BOOL is_extension_supported( const char *extension ) +{ + enum wgl_handle_type type = get_current_context_type(); + char *available_extensions = NULL; + BOOL ret = FALSE; + + if (type == HANDLE_CONTEXT) available_extensions = heap_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 ); + return ret; +} + +static int registry_entry_cmp( const void *a, const void *b ) +{ + const struct registry_entry *entry_a = a, *entry_b = b; + return strcmp( entry_a->name, entry_b->name ); +} + +static PROC WINAPI wrap_wglGetProcAddress( LPCSTR name ) +{ + const struct registry_entry entry = {.name = name}, *found; + struct opengl_funcs *funcs = NtCurrentTeb()->glTable; + const void **func_ptr; + + /* Without an active context opengl32 doesn't know to what + * driver it has to dispatch wglGetProcAddress. + */ + if (!get_current_context_ptr()) + { + WARN( "No active WGL context found\n" ); + return (void *)-1; + } + + if (!(found = bsearch( &entry, extension_registry, extension_registry_size, sizeof(entry), registry_entry_cmp ))) + { + WARN( "Function %s unknown\n", name ); + return (void *)-1; + } + + func_ptr = (const void **)&funcs->ext + (found - extension_registry); + if (!*func_ptr) + { + void *driver_func = funcs->wgl.p_wglGetProcAddress( name ); + + if (!is_extension_supported( found->extension )) + { + unsigned int i; + static const struct { const char *name, *alt; } alternatives[] = + { + { "glCopyTexSubImage3DEXT", "glCopyTexSubImage3D" }, /* needed by RuneScape */ + { "glVertexAttribDivisor", "glVertexAttribDivisorARB"}, /* needed by Caffeine */ + }; + + for (i = 0; i < ARRAY_SIZE(alternatives); i++) + { + if (strcmp( name, alternatives[i].name )) continue; + WARN( "Extension %s required for %s not supported, trying %s\n", found->extension, + name, alternatives[i].alt ); + return wrap_wglGetProcAddress( alternatives[i].alt ); + } + + WARN( "Extension %s required for %s not supported\n", found->extension, name ); + return (void *)-1; + } + + if (driver_func == NULL) + { + WARN( "Function %s not supported by driver\n", name ); + return (void *)-1; + } + + *func_ptr = driver_func; + } + + return (void *)(UINT_PTR)(found - extension_registry); +} + static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) { struct wgl_handle *src, *dst; @@ -724,6 +820,13 @@ NTSTATUS wgl_wglDeleteContext( void *args ) return STATUS_SUCCESS; }
+NTSTATUS wgl_wglGetProcAddress( void *args ) +{ + struct wglGetProcAddress_params *params = args; + params->ret = wrap_wglGetProcAddress( params->lpszProc ); + return STATUS_SUCCESS; +} + NTSTATUS wgl_wglMakeCurrent( void *args ) { struct wglMakeCurrent_params *params = args; diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index f5a4b034196..1492f9b20b1 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -334,98 +334,20 @@ int WINAPI wglGetLayerPaletteEntries(HDC hdc, return 0; }
-static int registry_entry_cmp( const void *a, const void *b ) -{ - const struct registry_entry *entry_a = a, *entry_b = b; - return strcmp( entry_a->name, entry_b->name ); -} - -static char *heap_strdup( const char *str ) -{ - int len = strlen( str ) + 1; - char *ret = HeapAlloc( GetProcessHeap(), 0, len ); - memcpy( ret, str, len ); - return ret; -} - -/* Check if a GL extension is supported */ -static BOOL is_extension_supported( const char *extension ) -{ - enum wgl_handle_type type = get_current_context_type(); - char *available_extensions = NULL; - BOOL ret = FALSE; - - if (type == HANDLE_CONTEXT) available_extensions = heap_strdup( (const char *)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 ); - return ret; -} - /*********************************************************************** * wglGetProcAddress (OPENGL32.@) */ PROC WINAPI wglGetProcAddress( LPCSTR name ) { - const struct registry_entry entry = {.name = name}, *found; - struct opengl_funcs *funcs = NtCurrentTeb()->glTable; - const void **func_ptr, *proc; + struct wglGetProcAddress_params args = { .lpszProc = name, }; + const void *proc; + NTSTATUS status;
if (!name) return NULL; + if ((status = UNIX_CALL( wglGetProcAddress, &args ))) WARN( "wglGetProcAddress %s returned %#x\n", debugstr_a(name), status ); + if (args.ret == (void *)-1) return NULL;
- /* Without an active context opengl32 doesn't know to what - * driver it has to dispatch wglGetProcAddress. - */ - if (!get_current_context_ptr()) - { - WARN("No active WGL context found\n"); - return NULL; - } - - if (!(found = bsearch( &entry, extension_registry, extension_registry_size, - sizeof(entry), registry_entry_cmp ))) - { - WARN("Function %s unknown\n", name); - return NULL; - } - - func_ptr = (const void **)&funcs->ext + (found - extension_registry); - if (!*func_ptr) - { - void *driver_func = funcs->wgl.p_wglGetProcAddress( name ); - - if (!is_extension_supported(found->extension)) - { - unsigned int i; - static const struct { const char *name, *alt; } alternatives[] = - { - { "glCopyTexSubImage3DEXT", "glCopyTexSubImage3D" }, /* needed by RuneScape */ - { "glVertexAttribDivisor", "glVertexAttribDivisorARB"}, /* needed by Caffeine */ - }; - - for (i = 0; i < ARRAY_SIZE(alternatives); i++) - { - if (strcmp( name, alternatives[i].name )) continue; - WARN( "Extension %s required for %s not supported, trying %s\n", found->extension, - name, alternatives[i].alt ); - return wglGetProcAddress( alternatives[i].alt ); - } - WARN( "Extension %s required for %s not supported\n", found->extension, name ); - return NULL; - } - - if (driver_func == NULL) - { - WARN("Function %s not supported by driver\n", name); - return NULL; - } - *func_ptr = driver_func; - } - - proc = extension_procs[found - extension_registry]; + proc = extension_procs[(UINT_PTR)args.ret]; TRACE( "returning %s -> %p\n", name, proc ); return proc; }