Commit b892720a authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

opengl32: Move wglGetProcAddress extension filtering to unix_wgl.c.

parent 8a6987af
......@@ -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/ $//;
......
......@@ -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 */
......@@ -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;
......@@ -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;
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment