include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / opengl32 / unix_wgl.c
blob093dab4efb86476511219f8406cda143caae67fd
1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
4 * Copyright (c) 2005 Raphael Junqueira
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <stdarg.h>
28 #include <stdlib.h>
30 #include <pthread.h>
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
37 #include "ntuser.h"
39 #include "unixlib.h"
40 #include "unix_private.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
46 static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
48 static BOOL is_wow64(void)
50 return !!NtCurrentTeb()->WowTebOffset;
53 static pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER;
55 /* handle management */
57 enum wgl_handle_type
59 HANDLE_PBUFFER = 0 << 12,
60 HANDLE_CONTEXT = 1 << 12,
61 HANDLE_CONTEXT_V3 = 3 << 12,
62 HANDLE_GLSYNC = 4 << 12,
63 HANDLE_TYPE_MASK = 15 << 12,
66 struct opengl_context
68 DWORD tid; /* thread that the context is current in */
69 void (CALLBACK *debug_callback)( GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *, const void * ); /* debug callback */
70 const void *debug_user; /* debug user parameter */
71 GLubyte *extensions; /* extension string */
72 GLuint *disabled_exts; /* indices of disabled extensions */
73 struct wgl_context *drv_ctx; /* driver context */
74 GLubyte *version_string;
77 struct wgl_handle
79 UINT handle;
80 const struct opengl_funcs *funcs;
81 union
83 struct opengl_context *context; /* for HANDLE_CONTEXT */
84 struct wgl_pbuffer *pbuffer; /* for HANDLE_PBUFFER */
85 struct wgl_handle *next; /* for free handles */
86 } u;
89 #define MAX_WGL_HANDLES 1024
90 static struct wgl_handle wgl_handles[MAX_WGL_HANDLES];
91 static struct wgl_handle *next_free;
92 static unsigned int handle_count;
94 /* the current context is assumed valid and doesn't need locking */
95 static inline struct wgl_handle *get_current_context_ptr( TEB *teb )
97 if (!teb->glCurrentRC) return NULL;
98 return &wgl_handles[LOWORD(teb->glCurrentRC) & ~HANDLE_TYPE_MASK];
101 static inline HANDLE next_handle( struct wgl_handle *ptr, enum wgl_handle_type type )
103 WORD generation = HIWORD( ptr->handle ) + 1;
104 if (!generation) generation++;
105 ptr->handle = MAKELONG( ptr - wgl_handles, generation ) | type;
106 return ULongToHandle( ptr->handle );
109 static struct wgl_handle *get_handle_ptr( HANDLE handle, enum wgl_handle_type type )
111 unsigned int index = LOWORD( handle ) & ~HANDLE_TYPE_MASK;
113 if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle)
114 return &wgl_handles[index];
116 RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
117 return NULL;
120 static HANDLE alloc_handle( enum wgl_handle_type type, const struct opengl_funcs *funcs, void *user_ptr )
122 HANDLE handle = 0;
123 struct wgl_handle *ptr = NULL;
125 if ((ptr = next_free))
126 next_free = next_free->u.next;
127 else if (handle_count < MAX_WGL_HANDLES)
128 ptr = &wgl_handles[handle_count++];
130 if (ptr)
132 ptr->funcs = funcs;
133 ptr->u.context = user_ptr;
134 handle = next_handle( ptr, type );
136 else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY );
137 return handle;
140 static void free_handle_ptr( struct wgl_handle *ptr )
142 ptr->handle |= 0xffff;
143 ptr->u.next = next_free;
144 ptr->funcs = NULL;
145 next_free = ptr;
148 /* check if the extension is present in the list */
149 static BOOL has_extension( const char *list, const char *ext, size_t len )
151 while (list)
153 while (*list == ' ') list++;
154 if (!strncmp( list, ext, len ) && (!list[len] || list[len] == ' ')) return TRUE;
155 list = strchr( list, ' ' );
157 return FALSE;
160 static GLubyte *filter_extensions_list( const char *extensions, const char *disabled )
162 const char *end;
163 char *p, *str;
165 p = str = malloc( strlen( extensions ) + 2 );
166 if (!str) return NULL;
168 TRACE( "GL_EXTENSIONS:\n" );
170 for (;;)
172 while (*extensions == ' ') extensions++;
173 if (!*extensions) break;
175 if (!(end = strchr( extensions, ' ' ))) end = extensions + strlen( extensions );
176 memcpy( p, extensions, end - extensions );
177 p[end - extensions] = 0;
179 /* We do not support GL_MAP_PERSISTENT_BIT, and hence
180 * ARB_buffer_storage, on wow64. */
181 if (is_win64 && is_wow64() && (!strcmp( p, "GL_ARB_buffer_storage" ) || !strcmp( p, "GL_EXT_buffer_storage" )))
183 TRACE( "-- %s (disabled due to wow64)\n", p );
185 else if (!has_extension( disabled, p, strlen( p ) ))
187 TRACE( "++ %s\n", p );
188 p += end - extensions;
189 *p++ = ' ';
191 else
193 TRACE( "-- %s (disabled by config)\n", p );
195 extensions = end;
197 *p = 0;
198 return (GLubyte *)str;
201 static const char *parse_gl_version( const char *gl_version, int *major, int *minor )
203 const char *ptr = gl_version;
205 *major = atoi( ptr );
206 if (*major <= 0)
207 ERR( "Invalid OpenGL major version %d.\n", *major );
209 while (isdigit( *ptr )) ++ptr;
210 if (*ptr++ != '.')
211 ERR( "Invalid OpenGL version string %s.\n", debugstr_a(gl_version) );
213 *minor = atoi( ptr );
215 while (isdigit( *ptr )) ++ptr;
216 return ptr;
219 static GLuint *filter_extensions_index( TEB *teb, const char *disabled )
221 const struct opengl_funcs *funcs = teb->glTable;
222 const char *ext, *version;
223 GLuint *disabled_index;
224 GLint extensions_count;
225 unsigned int i = 0, j;
226 int major, minor;
228 if (!funcs->ext.p_glGetStringi)
230 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
231 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
232 if (!funcs->ext.p_glGetStringi) return NULL;
235 version = (const char *)funcs->gl.p_glGetString( GL_VERSION );
236 parse_gl_version( version, &major, &minor );
237 if (major < 3)
238 return NULL;
240 funcs->gl.p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count );
241 disabled_index = malloc( extensions_count * sizeof(*disabled_index) );
242 if (!disabled_index) return NULL;
244 TRACE( "GL_EXTENSIONS:\n" );
246 for (j = 0; j < extensions_count; ++j)
248 ext = (const char *)funcs->ext.p_glGetStringi( GL_EXTENSIONS, j );
250 /* We do not support GL_MAP_PERSISTENT_BIT, and hence
251 * ARB_buffer_storage, on wow64. */
252 if (is_win64 && is_wow64() && (!strcmp( ext, "GL_ARB_buffer_storage" ) || !strcmp( ext, "GL_EXT_buffer_storage" )))
254 TRACE( "-- %s (disabled due to wow64)\n", ext );
255 disabled_index[i++] = j;
257 else if (!has_extension( disabled, ext, strlen( ext ) ))
259 TRACE( "++ %s\n", ext );
261 else
263 TRACE( "-- %s (disabled by config)\n", ext );
264 disabled_index[i++] = j;
268 disabled_index[i] = ~0u;
269 return disabled_index;
272 static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
274 while (len--) *dst++ = (unsigned char)*src++;
277 static inline UINT asciiz_to_unicode( WCHAR *dst, const char *src )
279 WCHAR *p = dst;
280 while ((*p++ = *src++));
281 return (p - dst) * sizeof(WCHAR);
284 static inline void unicode_to_ascii( char *dst, const WCHAR *src, size_t len )
286 while (len--) *dst++ = *src++;
289 static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
291 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
292 OBJECT_ATTRIBUTES attr;
293 HANDLE ret;
295 attr.Length = sizeof(attr);
296 attr.RootDirectory = root;
297 attr.ObjectName = &nameW;
298 attr.Attributes = 0;
299 attr.SecurityDescriptor = NULL;
300 attr.SecurityQualityOfService = NULL;
302 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
305 static HKEY open_hkcu_key( const char *name )
307 WCHAR bufferW[256];
308 static HKEY hkcu;
310 if (!hkcu)
312 char buffer[256];
313 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
314 DWORD i, len = sizeof(sid_data);
315 SID *sid;
317 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
318 return 0;
320 sid = ((TOKEN_USER *)sid_data)->User.Sid;
321 len = snprintf( buffer, sizeof(buffer), "\\Registry\\User\\S-%u-%u", sid->Revision,
322 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
323 sid->IdentifierAuthority.Value[4] ),
324 MAKEWORD( sid->IdentifierAuthority.Value[3],
325 sid->IdentifierAuthority.Value[2] )));
326 for (i = 0; i < sid->SubAuthorityCount; i++)
327 len += snprintf( buffer + len, sizeof(buffer) - len, "-%u", (int)sid->SubAuthority[i] );
329 ascii_to_unicode( bufferW, buffer, len );
330 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
333 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
336 static NTSTATUS query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
338 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
339 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
341 return NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size, &size );
344 /* build the extension string by filtering out the disabled extensions */
345 static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts_list, GLuint **disabled_exts )
347 static const char *disabled;
349 if (!disabled)
351 char *str = NULL;
352 HKEY hkey;
354 /* @@ Wine registry key: HKCU\Software\Wine\OpenGL */
355 if ((hkey = open_hkcu_key( "Software\\Wine\\OpenGL" )))
357 char buffer[4096];
358 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
359 static WCHAR disabled_extensionsW[] = {'D','i','s','a','b','l','e','d','E','x','t','e','n','s','i','o','n','s',0};
361 if (!query_reg_value( hkey, disabled_extensionsW, value, sizeof(buffer) ))
363 ULONG len = value->DataLength / sizeof(WCHAR);
365 unicode_to_ascii( buffer, (WCHAR *)value->Data, len );
366 buffer[len] = 0;
367 str = strdup( buffer );
369 NtClose( hkey );
371 if (str)
373 if (InterlockedCompareExchangePointer( (void **)&disabled, str, NULL )) free( str );
375 else disabled = "";
378 if (extensions && !*exts_list) *exts_list = filter_extensions_list( extensions, disabled );
379 if (!*disabled_exts) *disabled_exts = filter_extensions_index( teb, disabled );
380 return (exts_list && *exts_list) || *disabled_exts;
383 static const GLuint *disabled_extensions_index( TEB *teb )
385 struct wgl_handle *ptr = get_current_context_ptr( teb );
386 GLuint **disabled = &ptr->u.context->disabled_exts;
387 if (*disabled || filter_extensions( teb, NULL, NULL, disabled )) return *disabled;
388 return NULL;
391 /* Check if a GL extension is supported */
392 static BOOL check_extension_support( TEB *teb, const char *extension, const char *available_extensions )
394 const struct opengl_funcs *funcs = teb->glTable;
395 size_t len;
397 TRACE( "Checking for extension '%s'\n", extension );
399 /* We use the GetProcAddress function from the display driver to retrieve function pointers
400 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
401 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
402 * require the function to return NULL when an extension isn't found. For this reason we check
403 * if the OpenGL extension required for the function we are looking up is supported. */
405 while ((len = strcspn( extension, " " )))
407 /* Check if the extension is part of the GL extension string to see if it is supported. */
408 if (has_extension( available_extensions, extension, len )) return TRUE;
410 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
411 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
412 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
413 * Check if we are searching for a core GL function */
414 if (!strncmp( extension, "GL_VERSION_", 11 ))
416 const GLubyte *gl_version = funcs->gl.p_glGetString( GL_VERSION );
417 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
419 if (!gl_version)
421 ERR( "No OpenGL version found!\n" );
422 return FALSE;
425 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
426 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
427 if ((gl_version[0] > version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2]))) return TRUE;
429 WARN( "The function requires OpenGL version '%c.%c' while your drivers only provide '%c.%c'\n",
430 version[0], version[2], gl_version[0], gl_version[2] );
433 if (extension[len] == ' ') len++;
434 extension += len;
437 return FALSE;
440 static void wrap_glGetIntegerv( TEB *teb, GLenum pname, GLint *data )
442 const struct opengl_funcs *funcs = teb->glTable;
443 const GLuint *disabled;
445 funcs->gl.p_glGetIntegerv( pname, data );
447 if (pname == GL_NUM_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
448 while (*disabled++ != ~0u) (*data)--;
450 if (is_win64 && is_wow64())
452 /* 4.4 depends on ARB_buffer_storage, which we don't support on wow64. */
453 if (pname == GL_MAJOR_VERSION && *data > 4)
454 *data = 4;
455 else if (pname == GL_MINOR_VERSION)
457 GLint major;
459 funcs->gl.p_glGetIntegerv( GL_MAJOR_VERSION, &major );
460 if (major == 4 && *data > 3)
461 *data = 3;
466 static const GLubyte *wrap_glGetString( TEB *teb, GLenum name )
468 const struct opengl_funcs *funcs = teb->glTable;
469 const GLubyte *ret;
471 if ((ret = funcs->gl.p_glGetString( name )))
473 if (name == GL_EXTENSIONS)
475 struct wgl_handle *ptr = get_current_context_ptr( teb );
476 GLubyte **extensions = &ptr->u.context->extensions;
477 GLuint **disabled = &ptr->u.context->disabled_exts;
478 if (*extensions || filter_extensions( teb, (const char *)ret, extensions, disabled )) return *extensions;
480 else if (name == GL_VERSION && is_win64 && is_wow64())
482 struct wgl_handle *ptr = get_current_context_ptr( teb );
483 int major, minor;
484 const char *rest;
486 if (ptr->u.context->version_string)
487 return ptr->u.context->version_string;
489 rest = parse_gl_version( (const char *)ret, &major, &minor );
491 /* 4.4 depends on ARB_buffer_storage, which we don't support on wow64. */
492 if (major > 4 || (major == 4 && minor >= 4))
494 char *str = NULL;
496 asprintf( &str, "4.3%s", rest );
497 if (InterlockedCompareExchangePointer( (void **)&ptr->u.context->version_string, str, NULL ))
498 free( str );
499 return ptr->u.context->version_string;
504 return ret;
507 static const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index )
509 const struct opengl_funcs *funcs = teb->glTable;
510 const GLuint *disabled;
512 if (!funcs->ext.p_glGetStringi)
514 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
515 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
518 if (name == GL_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
519 while (index >= *disabled++) index++;
521 return funcs->ext.p_glGetStringi( name, index );
524 static char *build_extension_list( TEB *teb )
526 GLint len = 0, capacity, i, extensions_count;
527 char *extension, *tmp, *available_extensions;
529 wrap_glGetIntegerv( teb, GL_NUM_EXTENSIONS, &extensions_count );
530 capacity = 128 * extensions_count;
532 if (!(available_extensions = malloc( capacity ))) return NULL;
533 for (i = 0; i < extensions_count; ++i)
535 extension = (char *)wrap_glGetStringi( teb, GL_EXTENSIONS, i );
536 capacity = max( capacity, len + strlen( extension ) + 2 );
537 if (!(tmp = realloc( available_extensions, capacity ))) break;
538 available_extensions = tmp;
539 len += snprintf( available_extensions + len, capacity - len, "%s ", extension );
541 if (len) available_extensions[len - 1] = 0;
543 return available_extensions;
546 static inline enum wgl_handle_type get_current_context_type( TEB *teb )
548 if (!teb->glCurrentRC) return HANDLE_CONTEXT;
549 return LOWORD(teb->glCurrentRC) & HANDLE_TYPE_MASK;
552 /* Check if a GL extension is supported */
553 static BOOL is_extension_supported( TEB *teb, const char *extension )
555 enum wgl_handle_type type = get_current_context_type( teb );
556 char *available_extensions = NULL;
557 BOOL ret = FALSE;
559 if (type == HANDLE_CONTEXT) available_extensions = strdup( (const char *)wrap_glGetString( teb, GL_EXTENSIONS ) );
560 if (!available_extensions) available_extensions = build_extension_list( teb );
562 if (!available_extensions) ERR( "No OpenGL extensions found, check if your OpenGL setup is correct!\n" );
563 else ret = check_extension_support( teb, extension, available_extensions );
565 free( available_extensions );
566 return ret;
569 static int registry_entry_cmp( const void *a, const void *b )
571 const struct registry_entry *entry_a = a, *entry_b = b;
572 return strcmp( entry_a->name, entry_b->name );
575 static PROC wrap_wglGetProcAddress( TEB *teb, LPCSTR name )
577 const struct registry_entry entry = {.name = name}, *found;
578 struct opengl_funcs *funcs = teb->glTable;
579 const void **func_ptr;
581 /* Without an active context opengl32 doesn't know to what
582 * driver it has to dispatch wglGetProcAddress.
584 if (!get_current_context_ptr( teb ))
586 WARN( "No active WGL context found\n" );
587 return (void *)-1;
590 if (!(found = bsearch( &entry, extension_registry, extension_registry_size, sizeof(entry), registry_entry_cmp )))
592 WARN( "Function %s unknown\n", name );
593 return (void *)-1;
596 func_ptr = (const void **)&funcs->ext + (found - extension_registry);
597 if (!*func_ptr)
599 void *driver_func = funcs->wgl.p_wglGetProcAddress( name );
601 if (!is_extension_supported( teb, found->extension ))
603 unsigned int i;
604 static const struct { const char *name, *alt; } alternatives[] =
606 { "glCopyTexSubImage3DEXT", "glCopyTexSubImage3D" }, /* needed by RuneScape */
607 { "glVertexAttribDivisor", "glVertexAttribDivisorARB"}, /* needed by Caffeine */
610 for (i = 0; i < ARRAY_SIZE(alternatives); i++)
612 if (strcmp( name, alternatives[i].name )) continue;
613 WARN( "Extension %s required for %s not supported, trying %s\n", found->extension,
614 name, alternatives[i].alt );
615 return wrap_wglGetProcAddress( teb, alternatives[i].alt );
618 WARN( "Extension %s required for %s not supported\n", found->extension, name );
619 return (void *)-1;
622 if (driver_func == NULL)
624 WARN( "Function %s not supported by driver\n", name );
625 return (void *)-1;
628 *func_ptr = driver_func;
631 /* Return the index into the extension registry instead of a useless
632 * function pointer, PE side will returns its own function pointers.
634 return (void *)(UINT_PTR)(found - extension_registry);
637 static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
639 struct wgl_handle *src, *dst;
640 BOOL ret = FALSE;
642 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
643 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
645 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
646 else ret = src->funcs->wgl.p_wglCopyContext( src->u.context->drv_ctx, dst->u.context->drv_ctx, mask );
648 return ret;
651 static HGLRC wrap_wglCreateContext( HDC hdc )
653 HGLRC ret = 0;
654 struct wgl_context *drv_ctx;
655 struct opengl_context *context;
656 const struct opengl_funcs *funcs = get_dc_funcs( hdc );
658 if (!funcs) return 0;
659 if (!(drv_ctx = funcs->wgl.p_wglCreateContext( hdc ))) return 0;
660 if ((context = calloc( 1, sizeof(*context) )))
662 context->drv_ctx = drv_ctx;
663 if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context );
665 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
666 return ret;
669 static BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc )
671 BOOL ret = TRUE;
672 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
673 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
675 if (hglrc)
677 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
678 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
680 ret = ptr->funcs->wgl.p_wglMakeCurrent( hdc, ptr->u.context->drv_ctx );
681 if (ret)
683 if (prev) prev->u.context->tid = 0;
684 ptr->u.context->tid = tid;
685 teb->glReserved1[0] = hdc;
686 teb->glReserved1[1] = hdc;
687 teb->glCurrentRC = hglrc;
688 teb->glTable = (void *)ptr->funcs;
691 else
693 RtlSetLastWin32Error( ERROR_BUSY );
694 ret = FALSE;
697 else if (prev)
699 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
700 prev->u.context->tid = 0;
701 teb->glCurrentRC = 0;
702 teb->glTable = &null_opengl_funcs;
704 else if (!hdc)
706 RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
707 ret = FALSE;
709 return ret;
712 static BOOL wrap_wglDeleteContext( TEB *teb, HGLRC hglrc )
714 struct wgl_handle *ptr;
715 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
717 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
718 if (ptr->u.context->tid && ptr->u.context->tid != tid)
720 RtlSetLastWin32Error( ERROR_BUSY );
721 return FALSE;
723 if (hglrc == teb->glCurrentRC) wrap_wglMakeCurrent( teb, 0, 0 );
724 ptr->funcs->wgl.p_wglDeleteContext( ptr->u.context->drv_ctx );
725 free( ptr->u.context->version_string );
726 free( ptr->u.context->disabled_exts );
727 free( ptr->u.context->extensions );
728 free( ptr->u.context );
729 free_handle_ptr( ptr );
730 return TRUE;
733 static BOOL wrap_wglShareLists( HGLRC hglrcSrc, HGLRC hglrcDst )
735 BOOL ret = FALSE;
736 struct wgl_handle *src, *dst;
738 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
739 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
741 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
742 else ret = src->funcs->wgl.p_wglShareLists( src->u.context->drv_ctx, dst->u.context->drv_ctx );
744 return ret;
747 static BOOL wrap_wglBindTexImageARB( HPBUFFERARB handle, int buffer )
749 struct wgl_handle *ptr;
750 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
751 return ptr->funcs->ext.p_wglBindTexImageARB( ptr->u.pbuffer, buffer );
754 static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *attribs )
756 HGLRC ret = 0;
757 struct wgl_context *drv_ctx;
758 struct wgl_handle *share_ptr = NULL;
759 struct opengl_context *context;
760 const struct opengl_funcs *funcs = get_dc_funcs( hdc );
762 if (!funcs)
764 RtlSetLastWin32Error( ERROR_DC_NOT_FOUND );
765 return 0;
767 if (!funcs->ext.p_wglCreateContextAttribsARB) return 0;
768 if (share && !(share_ptr = get_handle_ptr( share, HANDLE_CONTEXT )))
770 RtlSetLastWin32Error( ERROR_INVALID_OPERATION );
771 return 0;
773 if ((drv_ctx = funcs->ext.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->u.context->drv_ctx : NULL, attribs )))
775 if ((context = calloc( 1, sizeof(*context) )))
777 enum wgl_handle_type type = HANDLE_CONTEXT;
779 if (attribs)
781 while (*attribs)
783 if (attribs[0] == WGL_CONTEXT_MAJOR_VERSION_ARB)
785 if (attribs[1] >= 3) type = HANDLE_CONTEXT_V3;
786 break;
788 attribs += 2;
792 context->drv_ctx = drv_ctx;
793 if (!(ret = alloc_handle( type, funcs, context ))) free( context );
795 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
798 return ret;
801 static HPBUFFERARB wrap_wglCreatePbufferARB( HDC hdc, int format, int width, int height, const int *attribs )
803 HPBUFFERARB ret;
804 struct wgl_pbuffer *pbuffer;
805 const struct opengl_funcs *funcs = get_dc_funcs( hdc );
807 if (!funcs || !funcs->ext.p_wglCreatePbufferARB) return 0;
808 if (!(pbuffer = funcs->ext.p_wglCreatePbufferARB( hdc, format, width, height, attribs ))) return 0;
809 ret = alloc_handle( HANDLE_PBUFFER, funcs, pbuffer );
810 if (!ret) funcs->ext.p_wglDestroyPbufferARB( pbuffer );
811 return ret;
814 static BOOL wrap_wglDestroyPbufferARB( HPBUFFERARB handle )
816 struct wgl_handle *ptr;
818 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
819 ptr->funcs->ext.p_wglDestroyPbufferARB( ptr->u.pbuffer );
820 free_handle_ptr( ptr );
821 return TRUE;
824 static HDC wrap_wglGetPbufferDCARB( HPBUFFERARB handle )
826 struct wgl_handle *ptr;
827 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return 0;
828 return ptr->funcs->ext.p_wglGetPbufferDCARB( ptr->u.pbuffer );
831 static BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC hglrc )
833 BOOL ret = TRUE;
834 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
835 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
837 if (hglrc)
839 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
840 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
842 ret = (ptr->funcs->ext.p_wglMakeContextCurrentARB &&
843 ptr->funcs->ext.p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->u.context->drv_ctx ));
844 if (ret)
846 if (prev) prev->u.context->tid = 0;
847 ptr->u.context->tid = tid;
848 teb->glReserved1[0] = draw_hdc;
849 teb->glReserved1[1] = read_hdc;
850 teb->glCurrentRC = hglrc;
851 teb->glTable = (void *)ptr->funcs;
854 else
856 RtlSetLastWin32Error( ERROR_BUSY );
857 ret = FALSE;
860 else if (prev)
862 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
863 prev->u.context->tid = 0;
864 teb->glCurrentRC = 0;
865 teb->glTable = &null_opengl_funcs;
867 return ret;
870 static BOOL wrap_wglQueryPbufferARB( HPBUFFERARB handle, int attrib, int *value )
872 struct wgl_handle *ptr;
873 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
874 return ptr->funcs->ext.p_wglQueryPbufferARB( ptr->u.pbuffer, attrib, value );
877 static int wrap_wglReleasePbufferDCARB( HPBUFFERARB handle, HDC hdc )
879 struct wgl_handle *ptr;
880 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
881 return ptr->funcs->ext.p_wglReleasePbufferDCARB( ptr->u.pbuffer, hdc );
884 static BOOL wrap_wglReleaseTexImageARB( HPBUFFERARB handle, int buffer )
886 struct wgl_handle *ptr;
887 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
888 return ptr->funcs->ext.p_wglReleaseTexImageARB( ptr->u.pbuffer, buffer );
891 static BOOL wrap_wglSetPbufferAttribARB( HPBUFFERARB handle, const int *attribs )
893 struct wgl_handle *ptr;
894 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
895 return ptr->funcs->ext.p_wglSetPbufferAttribARB( ptr->u.pbuffer, attribs );
898 static void gl_debug_message_callback( GLenum source, GLenum type, GLuint id, GLenum severity,
899 GLsizei length, const GLchar *message, const void *userParam )
901 struct wine_gl_debug_message_params params =
903 .source = source,
904 .type = type,
905 .id = id,
906 .severity = severity,
907 .length = length,
908 .message = message,
910 void *ret_ptr;
911 ULONG ret_len;
912 struct wgl_handle *ptr = (struct wgl_handle *)userParam;
914 if (!NtCurrentTeb())
916 fprintf( stderr, "msg:gl_debug_message_callback called from native thread, severity %#x, message \"%.*s\".\n",
917 severity, length, message );
918 return;
921 if (!(params.user_callback = ptr->u.context->debug_callback)) return;
922 params.user_data = ptr->u.context->debug_user;
924 KeUserModeCallback( NtUserCallOpenGLDebugMessageCallback, &params, sizeof(params),
925 &ret_ptr, &ret_len );
928 static void wrap_glDebugMessageCallback( TEB *teb, GLDEBUGPROC callback, const void *userParam )
930 struct wgl_handle *ptr = get_current_context_ptr( teb );
931 const struct opengl_funcs *funcs = teb->glTable;
933 if (!funcs->ext.p_glDebugMessageCallback) return;
935 ptr->u.context->debug_callback = callback;
936 ptr->u.context->debug_user = userParam;
937 funcs->ext.p_glDebugMessageCallback( gl_debug_message_callback, ptr );
940 static void wrap_glDebugMessageCallbackAMD( TEB *teb, GLDEBUGPROCAMD callback, void *userParam )
942 struct wgl_handle *ptr = get_current_context_ptr( teb );
943 const struct opengl_funcs *funcs = teb->glTable;
945 if (!funcs->ext.p_glDebugMessageCallbackAMD) return;
947 ptr->u.context->debug_callback = callback;
948 ptr->u.context->debug_user = userParam;
949 funcs->ext.p_glDebugMessageCallbackAMD( gl_debug_message_callback, ptr );
952 static void wrap_glDebugMessageCallbackARB( TEB *teb, GLDEBUGPROCARB callback, const void *userParam )
954 struct wgl_handle *ptr = get_current_context_ptr( teb );
955 const struct opengl_funcs *funcs = teb->glTable;
957 if (!funcs->ext.p_glDebugMessageCallbackARB) return;
959 ptr->u.context->debug_callback = callback;
960 ptr->u.context->debug_user = userParam;
961 funcs->ext.p_glDebugMessageCallbackARB( gl_debug_message_callback, ptr );
964 NTSTATUS wgl_wglCopyContext( void *args )
966 struct wglCopyContext_params *params = args;
967 pthread_mutex_lock( &wgl_lock );
968 params->ret = wrap_wglCopyContext( params->hglrcSrc, params->hglrcDst, params->mask );
969 pthread_mutex_unlock( &wgl_lock );
970 return STATUS_SUCCESS;
973 NTSTATUS wgl_wglCreateContext( void *args )
975 struct wglCreateContext_params *params = args;
976 pthread_mutex_lock( &wgl_lock );
977 params->ret = wrap_wglCreateContext( params->hDc );
978 pthread_mutex_unlock( &wgl_lock );
979 return STATUS_SUCCESS;
982 NTSTATUS wgl_wglDeleteContext( void *args )
984 struct wglDeleteContext_params *params = args;
985 pthread_mutex_lock( &wgl_lock );
986 params->ret = wrap_wglDeleteContext( params->teb, params->oldContext );
987 pthread_mutex_unlock( &wgl_lock );
988 return STATUS_SUCCESS;
991 NTSTATUS wgl_wglGetProcAddress( void *args )
993 struct wglGetProcAddress_params *params = args;
994 params->ret = wrap_wglGetProcAddress( params->teb, params->lpszProc );
995 return STATUS_SUCCESS;
998 NTSTATUS wgl_wglMakeCurrent( void *args )
1000 struct wglMakeCurrent_params *params = args;
1001 if (params->newContext) pthread_mutex_lock( &wgl_lock );
1002 params->ret = wrap_wglMakeCurrent( params->teb, params->hDc, params->newContext );
1003 if (params->newContext) pthread_mutex_unlock( &wgl_lock );
1004 return STATUS_SUCCESS;
1007 NTSTATUS wgl_wglShareLists( void *args )
1009 struct wglShareLists_params *params = args;
1010 pthread_mutex_lock( &wgl_lock );
1011 params->ret = wrap_wglShareLists( params->hrcSrvShare, params->hrcSrvSource );
1012 pthread_mutex_unlock( &wgl_lock );
1013 return STATUS_SUCCESS;
1016 NTSTATUS gl_glGetIntegerv( void *args )
1018 struct glGetIntegerv_params *params = args;
1019 wrap_glGetIntegerv( params->teb, params->pname, params->data );
1020 return STATUS_SUCCESS;
1023 NTSTATUS gl_glGetString( void *args )
1025 struct glGetString_params *params = args;
1026 params->ret = wrap_glGetString( params->teb, params->name );
1027 return STATUS_SUCCESS;
1030 NTSTATUS ext_glDebugMessageCallback( void *args )
1032 struct glDebugMessageCallback_params *params = args;
1033 wrap_glDebugMessageCallback( params->teb, params->callback, params->userParam );
1034 return STATUS_SUCCESS;
1037 NTSTATUS ext_glDebugMessageCallbackAMD( void *args )
1039 struct glDebugMessageCallbackAMD_params *params = args;
1040 wrap_glDebugMessageCallbackAMD( params->teb, params->callback, params->userParam );
1041 return STATUS_SUCCESS;
1044 NTSTATUS ext_glDebugMessageCallbackARB( void *args )
1046 struct glDebugMessageCallbackARB_params *params = args;
1047 wrap_glDebugMessageCallbackARB( params->teb, params->callback, params->userParam );
1048 return STATUS_SUCCESS;
1051 NTSTATUS ext_glGetStringi( void *args )
1053 struct glGetStringi_params *params = args;
1054 params->ret = wrap_glGetStringi( params->teb, params->name, params->index );
1055 return STATUS_SUCCESS;
1058 NTSTATUS ext_wglBindTexImageARB( void *args )
1060 struct wglBindTexImageARB_params *params = args;
1061 pthread_mutex_lock( &wgl_lock );
1062 params->ret = wrap_wglBindTexImageARB( params->hPbuffer, params->iBuffer );
1063 pthread_mutex_unlock( &wgl_lock );
1064 return STATUS_SUCCESS;
1067 NTSTATUS ext_wglCreateContextAttribsARB( void *args )
1069 struct wglCreateContextAttribsARB_params *params = args;
1070 pthread_mutex_lock( &wgl_lock );
1071 params->ret = wrap_wglCreateContextAttribsARB( params->hDC, params->hShareContext, params->attribList );
1072 pthread_mutex_unlock( &wgl_lock );
1073 return STATUS_SUCCESS;
1076 NTSTATUS ext_wglCreatePbufferARB( void *args )
1078 struct wglCreatePbufferARB_params *params = args;
1079 pthread_mutex_lock( &wgl_lock );
1080 params->ret = wrap_wglCreatePbufferARB( params->hDC, params->iPixelFormat, params->iWidth, params->iHeight, params->piAttribList );
1081 pthread_mutex_unlock( &wgl_lock );
1082 return STATUS_SUCCESS;
1085 NTSTATUS ext_wglDestroyPbufferARB( void *args )
1087 struct wglDestroyPbufferARB_params *params = args;
1088 pthread_mutex_lock( &wgl_lock );
1089 params->ret = wrap_wglDestroyPbufferARB( params->hPbuffer );
1090 pthread_mutex_unlock( &wgl_lock );
1091 return STATUS_SUCCESS;
1094 NTSTATUS ext_wglGetPbufferDCARB( void *args )
1096 struct wglGetPbufferDCARB_params *params = args;
1097 pthread_mutex_lock( &wgl_lock );
1098 params->ret = wrap_wglGetPbufferDCARB( params->hPbuffer );
1099 pthread_mutex_unlock( &wgl_lock );
1100 return STATUS_SUCCESS;
1103 NTSTATUS ext_wglMakeContextCurrentARB( void *args )
1105 struct wglMakeContextCurrentARB_params *params = args;
1106 if (params->hglrc) pthread_mutex_lock( &wgl_lock );
1107 params->ret = wrap_wglMakeContextCurrentARB( params->teb, params->hDrawDC, params->hReadDC, params->hglrc );
1108 if (params->hglrc) pthread_mutex_unlock( &wgl_lock );
1109 return STATUS_SUCCESS;
1112 NTSTATUS ext_wglQueryPbufferARB( void *args )
1114 struct wglQueryPbufferARB_params *params = args;
1115 pthread_mutex_lock( &wgl_lock );
1116 params->ret = wrap_wglQueryPbufferARB( params->hPbuffer, params->iAttribute, params->piValue );
1117 pthread_mutex_unlock( &wgl_lock );
1118 return STATUS_SUCCESS;
1121 NTSTATUS ext_wglReleasePbufferDCARB( void *args )
1123 struct wglReleasePbufferDCARB_params *params = args;
1124 pthread_mutex_lock( &wgl_lock );
1125 params->ret = wrap_wglReleasePbufferDCARB( params->hPbuffer, params->hDC );
1126 pthread_mutex_unlock( &wgl_lock );
1127 return STATUS_SUCCESS;
1130 NTSTATUS ext_wglReleaseTexImageARB( void *args )
1132 struct wglReleaseTexImageARB_params *params = args;
1133 pthread_mutex_lock( &wgl_lock );
1134 params->ret = wrap_wglReleaseTexImageARB( params->hPbuffer, params->iBuffer );
1135 pthread_mutex_unlock( &wgl_lock );
1136 return STATUS_SUCCESS;
1139 NTSTATUS ext_wglSetPbufferAttribARB( void *args )
1141 struct wglSetPbufferAttribARB_params *params = args;
1142 pthread_mutex_lock( &wgl_lock );
1143 params->ret = wrap_wglSetPbufferAttribARB( params->hPbuffer, params->piAttribList );
1144 pthread_mutex_unlock( &wgl_lock );
1145 return STATUS_SUCCESS;
1148 NTSTATUS thread_attach( void *args )
1150 TEB *teb = args;
1151 teb->glTable = &null_opengl_funcs;
1152 return STATUS_SUCCESS;
1155 NTSTATUS process_detach( void *args )
1157 return STATUS_SUCCESS;
1160 NTSTATUS get_pixel_formats( void *args )
1162 struct get_pixel_formats_params *params = args;
1163 const struct opengl_funcs *funcs = get_dc_funcs( params->hdc );
1164 if (!funcs || !funcs->wgl.p_get_pixel_formats) return STATUS_NOT_IMPLEMENTED;
1165 funcs->wgl.p_get_pixel_formats( params->formats, params->max_formats,
1166 &params->num_formats, &params->num_onscreen_formats );
1167 return STATUS_SUCCESS;
1170 #ifdef _WIN64
1172 typedef ULONG PTR32;
1174 extern NTSTATUS ext_glClientWaitSync( void *args );
1175 extern NTSTATUS ext_glDeleteSync( void *args );
1176 extern NTSTATUS ext_glFenceSync( void *args );
1177 extern NTSTATUS ext_glGetBufferPointerv( void *args );
1178 extern NTSTATUS ext_glGetBufferPointervARB( void *args );
1179 extern NTSTATUS ext_glGetNamedBufferPointerv( void *args );
1180 extern NTSTATUS ext_glGetNamedBufferPointervEXT( void *args );
1181 extern NTSTATUS ext_glGetSynciv( void *args );
1182 extern NTSTATUS ext_glIsSync( void *args );
1183 extern NTSTATUS ext_glMapBuffer( void *args );
1185 extern NTSTATUS ext_glUnmapBuffer( void *args );
1186 extern NTSTATUS ext_glUnmapBufferARB( void *args );
1187 extern NTSTATUS ext_glUnmapNamedBuffer( void *args );
1188 extern NTSTATUS ext_glUnmapNamedBufferEXT( void *args );
1190 extern NTSTATUS ext_glMapBufferARB( void *args );
1191 extern NTSTATUS ext_glMapBufferRange( void *args );
1192 extern NTSTATUS ext_glMapNamedBuffer( void *args );
1193 extern NTSTATUS ext_glMapNamedBufferEXT( void *args );
1194 extern NTSTATUS ext_glMapNamedBufferRange( void *args );
1195 extern NTSTATUS ext_glMapNamedBufferRangeEXT( void *args );
1196 extern NTSTATUS ext_glPathGlyphIndexRangeNV( void *args );
1197 extern NTSTATUS ext_glWaitSync( void *args );
1198 extern NTSTATUS ext_wglGetExtensionsStringARB( void *args );
1199 extern NTSTATUS ext_wglGetExtensionsStringEXT( void *args );
1200 extern NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args );
1201 extern NTSTATUS ext_wglQueryRendererStringWINE( void *args );
1203 struct wow64_string_entry
1205 const char *str;
1206 PTR32 wow64_str;
1208 static struct wow64_string_entry *wow64_strings;
1209 static SIZE_T wow64_strings_count;
1211 static PTR32 find_wow64_string( const char *str, PTR32 wow64_str )
1213 void *tmp;
1214 SIZE_T i;
1216 pthread_mutex_lock( &wgl_lock );
1218 for (i = 0; i < wow64_strings_count; i++) if (wow64_strings[i].str == str) break;
1219 if (i == wow64_strings_count && (tmp = realloc( wow64_strings, (i + 1) * sizeof(*wow64_strings) )))
1221 wow64_strings = tmp;
1222 wow64_strings[i].str = str;
1223 wow64_strings[i].wow64_str = 0;
1224 wow64_strings_count += 1;
1227 if (i == wow64_strings_count) ERR( "Failed to allocate memory for wow64 strings\n" );
1228 else if (wow64_strings[i].wow64_str) wow64_str = wow64_strings[i].wow64_str;
1229 else if (wow64_str)
1231 strcpy( UlongToPtr(wow64_str), (char *)str );
1232 wow64_strings[i].wow64_str = wow64_str;
1235 pthread_mutex_unlock( &wgl_lock );
1237 return wow64_str;
1240 static inline void update_teb32_context( TEB *teb )
1242 void *teb32;
1244 if (!teb->WowTebOffset) return;
1245 teb32 = (char *)teb + teb->WowTebOffset;
1247 ((TEB32 *)teb32)->glCurrentRC = (UINT_PTR)teb->glCurrentRC;
1248 ((TEB32 *)teb32)->glReserved1[0] = (UINT_PTR)teb->glReserved1[0];
1249 ((TEB32 *)teb32)->glReserved1[1] = (UINT_PTR)teb->glReserved1[1];
1252 NTSTATUS wow64_wgl_wglCreateContext( void *args )
1254 struct
1256 PTR32 teb;
1257 PTR32 hDc;
1258 PTR32 ret;
1259 } *params32 = args;
1260 struct wglCreateContext_params params =
1262 .teb = get_teb64(params32->teb),
1263 .hDc = ULongToPtr(params32->hDc),
1265 NTSTATUS status;
1266 if ((status = wgl_wglCreateContext( &params ))) return status;
1267 params32->ret = (UINT_PTR)params.ret;
1268 return STATUS_SUCCESS;
1271 NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args )
1273 struct
1275 PTR32 teb;
1276 PTR32 hDC;
1277 PTR32 hShareContext;
1278 PTR32 attribList;
1279 PTR32 ret;
1280 } *params32 = args;
1281 struct wglCreateContextAttribsARB_params params =
1283 .teb = get_teb64(params32->teb),
1284 .hDC = ULongToPtr(params32->hDC),
1285 .hShareContext = ULongToPtr(params32->hShareContext),
1286 .attribList = ULongToPtr(params32->attribList),
1288 NTSTATUS status;
1289 if ((status = ext_wglCreateContextAttribsARB( &params ))) return status;
1290 params32->ret = (UINT_PTR)params.ret;
1291 return STATUS_SUCCESS;
1294 NTSTATUS wow64_ext_wglCreatePbufferARB( void *args )
1296 struct
1298 PTR32 teb;
1299 PTR32 hDC;
1300 GLint iPixelFormat;
1301 GLint iWidth;
1302 GLint iHeight;
1303 PTR32 piAttribList;
1304 PTR32 ret;
1305 } *params32 = args;
1306 struct wglCreatePbufferARB_params params =
1308 .teb = get_teb64(params32->teb),
1309 .hDC = ULongToPtr(params32->hDC),
1310 .iPixelFormat = params32->iPixelFormat,
1311 .iWidth = params32->iWidth,
1312 .iHeight = params32->iHeight,
1313 .piAttribList = ULongToPtr(params32->piAttribList),
1315 NTSTATUS status;
1316 if ((status = ext_wglCreatePbufferARB( &params ))) return status;
1317 params32->ret = (UINT_PTR)params.ret;
1318 return STATUS_SUCCESS;
1321 NTSTATUS wow64_wgl_wglDeleteContext( void *args )
1323 struct
1325 PTR32 teb;
1326 PTR32 oldContext;
1327 BOOL ret;
1328 } *params32 = args;
1329 struct wglDeleteContext_params params =
1331 .teb = get_teb64(params32->teb),
1332 .oldContext = ULongToPtr(params32->oldContext),
1334 NTSTATUS status;
1335 if (!(status = wgl_wglDeleteContext( &params ))) update_teb32_context( params.teb );
1336 params32->ret = params.ret;
1337 return status;
1340 NTSTATUS wow64_wgl_wglMakeCurrent( void *args )
1342 struct
1344 PTR32 teb;
1345 PTR32 hDc;
1346 PTR32 newContext;
1347 BOOL ret;
1348 } *params32 = args;
1349 struct wglMakeCurrent_params params =
1351 .teb = get_teb64(params32->teb),
1352 .hDc = ULongToPtr(params32->hDc),
1353 .newContext = ULongToPtr(params32->newContext),
1355 NTSTATUS status;
1356 if (!(status = wgl_wglMakeCurrent( &params ))) update_teb32_context( params.teb );
1357 params32->ret = params.ret;
1358 return status;
1361 NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args )
1363 struct
1365 PTR32 teb;
1366 PTR32 hDrawDC;
1367 PTR32 hReadDC;
1368 PTR32 hglrc;
1369 BOOL ret;
1370 } *params32 = args;
1371 struct wglMakeContextCurrentARB_params params =
1373 .teb = get_teb64(params32->teb),
1374 .hDrawDC = ULongToPtr(params32->hDrawDC),
1375 .hReadDC = ULongToPtr(params32->hReadDC),
1376 .hglrc = ULongToPtr(params32->hglrc),
1378 NTSTATUS status;
1379 if (!(status = ext_wglMakeContextCurrentARB( &params ))) update_teb32_context( params.teb );
1380 params32->ret = params.ret;
1381 return status;
1384 NTSTATUS wow64_ext_wglGetPbufferDCARB( void *args )
1386 struct
1388 PTR32 teb;
1389 PTR32 hPbuffer;
1390 PTR32 ret;
1391 } *params32 = args;
1392 struct wglGetPbufferDCARB_params params =
1394 .teb = get_teb64(params32->teb),
1395 .hPbuffer = (HPBUFFERARB)ULongToPtr(params32->hPbuffer),
1397 NTSTATUS status;
1398 if ((status = ext_wglGetPbufferDCARB( &params ))) return status;
1399 params32->ret = (UINT_PTR)params.ret;
1400 return STATUS_SUCCESS;
1403 NTSTATUS wow64_wgl_wglGetProcAddress( void *args )
1405 struct
1407 PTR32 teb;
1408 PTR32 lpszProc;
1409 PTR32 ret;
1410 } *params32 = args;
1411 struct wglGetProcAddress_params params =
1413 .teb = get_teb64(params32->teb),
1414 .lpszProc = ULongToPtr(params32->lpszProc),
1416 NTSTATUS status;
1417 if ((status = wgl_wglGetProcAddress( &params ))) return status;
1418 params32->ret = (UINT_PTR)params.ret;
1419 return STATUS_SUCCESS;
1422 NTSTATUS wow64_gl_glGetString( void *args )
1424 struct
1426 PTR32 teb;
1427 GLenum name;
1428 PTR32 ret;
1429 } *params32 = args;
1430 struct glGetString_params params =
1432 .teb = get_teb64(params32->teb),
1433 .name = params32->name,
1435 NTSTATUS status;
1437 if ((status = gl_glGetString( &params ))) return status;
1439 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1441 params32->ret = strlen( (char *)params.ret ) + 1;
1442 return STATUS_BUFFER_TOO_SMALL;
1445 return STATUS_SUCCESS;
1448 NTSTATUS wow64_ext_glGetStringi( void *args )
1450 struct
1452 PTR32 teb;
1453 GLenum name;
1454 GLuint index;
1455 PTR32 ret;
1456 } *params32 = args;
1457 struct glGetStringi_params params =
1459 .teb = get_teb64(params32->teb),
1460 .name = params32->name,
1461 .index = params32->index,
1463 NTSTATUS status;
1465 if ((status = ext_glGetStringi( &params ))) return status;
1467 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1469 params32->ret = strlen( (char *)params.ret ) + 1;
1470 return STATUS_BUFFER_TOO_SMALL;
1473 return STATUS_SUCCESS;
1476 NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
1478 struct
1480 PTR32 teb;
1481 GLenum fontTarget;
1482 PTR32 fontName;
1483 GLbitfield fontStyle;
1484 GLuint pathParameterTemplate;
1485 GLfloat emScale;
1486 GLuint baseAndCount[2];
1487 GLenum ret;
1488 } *params32 = args;
1489 struct glPathGlyphIndexRangeNV_params params =
1491 .teb = get_teb64(params32->teb),
1492 .fontTarget = params32->fontTarget,
1493 .fontName = ULongToPtr(params32->fontName),
1494 .fontStyle = params32->fontStyle,
1495 .pathParameterTemplate = params32->pathParameterTemplate,
1496 .emScale = params32->emScale,
1497 .baseAndCount = {params32->baseAndCount[0], params32->baseAndCount[1]},
1499 NTSTATUS status;
1500 if ((status = ext_glPathGlyphIndexRangeNV( &params ))) return status;
1501 params32->ret = params.ret;
1502 return status;
1505 NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
1507 struct
1509 PTR32 teb;
1510 PTR32 hdc;
1511 PTR32 ret;
1512 } *params32 = args;
1513 struct wglGetExtensionsStringARB_params params =
1515 .teb = get_teb64(params32->teb),
1516 .hdc = ULongToPtr(params32->hdc),
1518 NTSTATUS status;
1520 if ((status = ext_wglGetExtensionsStringARB( &params ))) return status;
1522 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1524 params32->ret = strlen( params.ret ) + 1;
1525 return STATUS_BUFFER_TOO_SMALL;
1528 return STATUS_SUCCESS;
1531 NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
1533 struct
1535 PTR32 teb;
1536 PTR32 ret;
1537 } *params32 = args;
1538 struct wglGetExtensionsStringEXT_params params =
1540 .teb = get_teb64(params32->teb),
1542 NTSTATUS status;
1544 if ((status = ext_wglGetExtensionsStringEXT( &params ))) return status;
1546 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1548 params32->ret = strlen( params.ret ) + 1;
1549 return STATUS_BUFFER_TOO_SMALL;
1552 return STATUS_SUCCESS;
1555 NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
1557 struct
1559 PTR32 teb;
1560 GLenum attribute;
1561 PTR32 ret;
1562 } *params32 = args;
1563 struct wglQueryCurrentRendererStringWINE_params params =
1565 .teb = get_teb64(params32->teb),
1566 .attribute = params32->attribute,
1568 NTSTATUS status;
1570 if ((status = ext_wglQueryCurrentRendererStringWINE( &params ))) return status;
1572 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1574 params32->ret = strlen( params.ret ) + 1;
1575 return STATUS_BUFFER_TOO_SMALL;
1578 return STATUS_SUCCESS;
1581 NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
1583 struct
1585 PTR32 teb;
1586 PTR32 dc;
1587 GLint renderer;
1588 GLenum attribute;
1589 PTR32 ret;
1590 } *params32 = args;
1591 struct wglQueryRendererStringWINE_params params =
1593 .teb = get_teb64(params32->teb),
1594 .dc = ULongToPtr(params32->dc),
1595 .renderer = params32->renderer,
1596 .attribute = params32->attribute,
1598 NTSTATUS status;
1600 if ((status = ext_wglQueryRendererStringWINE( &params ))) return status;
1602 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1604 params32->ret = strlen( params.ret ) + 1;
1605 return STATUS_BUFFER_TOO_SMALL;
1608 return STATUS_SUCCESS;
1611 NTSTATUS wow64_ext_glClientWaitSync( void *args )
1613 struct wgl_handle *handle;
1614 struct
1616 PTR32 teb;
1617 PTR32 sync;
1618 GLbitfield flags;
1619 GLuint64 timeout;
1620 GLenum ret;
1621 } *params32 = args;
1622 NTSTATUS status;
1624 pthread_mutex_lock( &wgl_lock );
1626 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1627 status = STATUS_INVALID_HANDLE;
1628 else
1630 struct glClientWaitSync_params params =
1632 .teb = get_teb64(params32->teb),
1633 .sync = (GLsync)handle->u.context,
1634 .flags = params32->flags,
1635 .timeout = params32->timeout,
1637 status = ext_glClientWaitSync( &params );
1638 params32->ret = params.ret;
1641 pthread_mutex_unlock( &wgl_lock );
1642 return status;
1645 NTSTATUS wow64_ext_glDeleteSync( void *args )
1647 struct wgl_handle *handle;
1648 struct
1650 PTR32 teb;
1651 PTR32 sync;
1652 } *params32 = args;
1653 NTSTATUS status;
1655 pthread_mutex_lock( &wgl_lock );
1657 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1658 status = STATUS_INVALID_HANDLE;
1659 else
1661 struct glDeleteSync_params params =
1663 .teb = get_teb64(params32->teb),
1664 .sync = (GLsync)handle->u.context,
1666 status = ext_glDeleteSync( &params );
1667 free_handle_ptr( handle );
1670 pthread_mutex_unlock( &wgl_lock );
1671 return status;
1674 NTSTATUS wow64_ext_glFenceSync( void *args )
1676 struct
1678 PTR32 teb;
1679 GLenum condition;
1680 GLbitfield flags;
1681 PTR32 ret;
1682 } *params32 = args;
1683 struct glFenceSync_params params =
1685 .teb = get_teb64(params32->teb),
1686 .condition = params32->condition,
1687 .flags = params32->flags,
1689 NTSTATUS status;
1691 if ((status = ext_glFenceSync( &params ))) return status;
1693 pthread_mutex_lock( &wgl_lock );
1695 if (!(params32->ret = (UINT_PTR)alloc_handle( HANDLE_GLSYNC, NULL, params.ret )))
1697 struct glDeleteSync_params delete_params =
1699 .teb = params.teb,
1700 .sync = params.ret,
1703 ext_glDeleteSync( &delete_params );
1704 status = STATUS_NO_MEMORY;
1707 pthread_mutex_unlock( &wgl_lock );
1708 return status;
1711 NTSTATUS wow64_ext_glGetSynciv( void *args )
1713 struct wgl_handle *handle;
1714 struct
1716 PTR32 teb;
1717 PTR32 sync;
1718 GLenum pname;
1719 GLsizei count;
1720 PTR32 length;
1721 PTR32 values;
1722 } *params32 = args;
1723 NTSTATUS status;
1725 pthread_mutex_lock( &wgl_lock );
1727 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1728 status = STATUS_INVALID_HANDLE;
1729 else
1731 struct glGetSynciv_params params =
1733 .teb = get_teb64(params32->teb),
1734 .sync = (GLsync)handle->u.context,
1735 .pname = params32->pname,
1736 .count = params32->count,
1737 .length = ULongToPtr(params32->length),
1738 .values = ULongToPtr(params32->values),
1740 status = ext_glGetSynciv( &params );
1743 pthread_mutex_unlock( &wgl_lock );
1744 return status;
1747 NTSTATUS wow64_ext_glIsSync( void *args )
1749 struct wgl_handle *handle;
1750 struct
1752 PTR32 teb;
1753 PTR32 sync;
1754 GLboolean ret;
1755 } *params32 = args;
1756 NTSTATUS status;
1758 pthread_mutex_lock( &wgl_lock );
1760 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1761 status = STATUS_INVALID_HANDLE;
1762 else
1764 struct glIsSync_params params =
1766 .teb = get_teb64(params32->teb),
1767 .sync = (GLsync)handle->u.context,
1769 status = ext_glIsSync( &params );
1770 params32->ret = params.ret;
1773 pthread_mutex_unlock( &wgl_lock );
1774 return status;
1777 NTSTATUS wow64_ext_glWaitSync( void *args )
1779 struct wgl_handle *handle;
1780 struct
1782 PTR32 teb;
1783 PTR32 sync;
1784 GLbitfield flags;
1785 GLuint64 timeout;
1786 } *params32 = args;
1787 NTSTATUS status;
1789 pthread_mutex_lock( &wgl_lock );
1791 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1792 status = STATUS_INVALID_HANDLE;
1793 else
1795 struct glWaitSync_params params =
1797 .teb = get_teb64(params32->teb),
1798 .sync = (GLsync)handle->u.context,
1799 .flags = params32->flags,
1800 .timeout = params32->timeout,
1802 status = ext_glWaitSync( &params );
1805 pthread_mutex_unlock( &wgl_lock );
1806 return status;
1809 static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param )
1811 const struct opengl_funcs *funcs = teb->glTable;
1812 typeof(*funcs->ext.p_glGetBufferParameteriv) *func;
1813 GLint size = 0;
1814 if (!(func = funcs->ext.p_glGetBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferParameteriv" );
1815 if (func) func( target, param, &size );
1816 return size;
1819 static void *get_buffer_pointer( TEB *teb, GLenum target )
1821 const struct opengl_funcs *funcs = teb->glTable;
1822 typeof(*funcs->ext.p_glGetBufferPointerv) *func;
1823 void *ptr = NULL;
1824 if (!(func = funcs->ext.p_glGetBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferPointerv" );
1825 if (func) func( target, GL_BUFFER_MAP_POINTER, &ptr );
1826 return ptr;
1829 static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param )
1831 const struct opengl_funcs *funcs = teb->glTable;
1832 typeof(*funcs->ext.p_glGetNamedBufferParameteriv) *func;
1833 GLint size = 0;
1834 if (!(func = funcs->ext.p_glGetNamedBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferParameteriv" );
1835 if (func) func( buffer, param, &size );
1836 return size;
1839 static void *get_named_buffer_pointer( TEB *teb, GLint buffer )
1841 const struct opengl_funcs *funcs = teb->glTable;
1842 typeof(*funcs->ext.p_glGetNamedBufferPointerv) *func;
1843 void *ptr = NULL;
1844 if (!(func = funcs->ext.p_glGetNamedBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferPointerv" );
1845 if (func) func( buffer, GL_BUFFER_MAP_POINTER, &ptr );
1846 return ptr;
1849 static void unmap_buffer( TEB *teb, GLenum target )
1851 const struct opengl_funcs *funcs = teb->glTable;
1852 typeof(*funcs->ext.p_glUnmapBuffer) *func;
1853 if (!(func = funcs->ext.p_glUnmapBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapBuffer" );
1854 if (func) func( target );
1857 static void unmap_named_buffer( TEB *teb, GLint buffer )
1859 const struct opengl_funcs *funcs = teb->glTable;
1860 typeof(*funcs->ext.p_glUnmapNamedBuffer) *func;
1861 if (!(func = funcs->ext.p_glUnmapNamedBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapNamedBuffer" );
1862 if (func) func( buffer );
1865 static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *ptr, SIZE_T size,
1866 GLbitfield access, PTR32 *ret )
1868 static unsigned int once;
1870 if (*ret) /* wow64 pointer provided, map buffer to it */
1872 if (!(access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)))
1874 if (!once++)
1875 FIXME( "Doing a copy of a mapped buffer (expect performance issues)\n" );
1877 TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*ret) );
1878 memcpy( UlongToPtr(*ret), ptr, size );
1881 /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */
1882 *(PTR32 *)ptr = (UINT_PTR)*ret;
1883 return STATUS_SUCCESS;
1886 if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1887 if (access & GL_MAP_PERSISTENT_BIT)
1889 FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" );
1890 return STATUS_NOT_SUPPORTED;
1893 if (!size) size = buffer ? get_named_buffer_param( teb, buffer, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE );
1894 if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */
1895 if (size < sizeof(PTR32))
1897 FIXME( "Buffer too small for metadata!\n" );
1898 return STATUS_BUFFER_TOO_SMALL;
1901 *ret = size;
1902 return STATUS_INVALID_ADDRESS;
1905 static GLbitfield map_range_flags_from_map_flags( GLenum flags )
1907 switch (flags)
1909 case GL_READ_ONLY: return GL_MAP_READ_BIT;
1910 case GL_WRITE_ONLY: return GL_MAP_WRITE_BIT;
1911 case GL_READ_WRITE: return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1912 default:
1913 ERR( "invalid map flags %#x\n", flags );
1914 return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1918 static NTSTATUS wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access )
1920 void *wow_ptr;
1922 if (ULongToPtr(PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1924 wow_ptr = UlongToPtr(*(PTR32 *)ptr);
1925 if (access & GL_MAP_WRITE_BIT)
1927 TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr );
1928 memcpy( ptr, wow_ptr, size );
1931 return STATUS_INVALID_ADDRESS;
1934 static NTSTATUS wow64_gl_get_buffer_pointer_v( void *args, NTSTATUS (*get_buffer_pointer_v64)(void *) )
1936 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1937 struct
1939 PTR32 teb;
1940 GLenum target;
1941 GLenum pname;
1942 PTR32 params;
1943 } *params32 = args;
1944 struct glGetBufferPointerv_params params =
1946 .teb = get_teb64(params32->teb),
1947 .target = params32->target,
1948 .pname = params32->pname,
1949 .params = (void **)&ptr,
1951 PTR32 *wow_ptr = UlongToPtr(params32->params);
1952 NTSTATUS status;
1954 if ((status = get_buffer_pointer_v64( &params ))) return status;
1955 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1956 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1957 *wow_ptr = ptr[0];
1958 return STATUS_SUCCESS;
1961 NTSTATUS wow64_ext_glGetBufferPointerv( void *args )
1963 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointerv );
1966 NTSTATUS wow64_ext_glGetBufferPointervARB( void *args )
1968 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointervARB );
1971 static NTSTATUS wow64_gl_get_named_buffer_pointer_v( void *args, NTSTATUS (*gl_get_named_buffer_pointer_v64)(void *) )
1973 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1974 struct
1976 PTR32 teb;
1977 GLuint buffer;
1978 GLenum pname;
1979 PTR32 params;
1980 } *params32 = args;
1981 struct glGetNamedBufferPointerv_params params =
1983 .teb = get_teb64(params32->teb),
1984 .buffer = params32->buffer,
1985 .pname = params32->pname,
1986 .params = (void **)&ptr,
1988 PTR32 *wow_ptr = UlongToPtr(params32->params);
1989 NTSTATUS status;
1991 if ((status = gl_get_named_buffer_pointer_v64( &params ))) return status;
1992 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1993 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1994 *wow_ptr = ptr[0];
1995 return STATUS_SUCCESS;
1998 NTSTATUS wow64_ext_glGetNamedBufferPointerv( void *args )
2000 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointerv );
2003 NTSTATUS wow64_ext_glGetNamedBufferPointervEXT( void *args )
2005 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointervEXT );
2008 static NTSTATUS wow64_gl_map_buffer( void *args, NTSTATUS (*gl_map_buffer64)(void *) )
2010 struct
2012 PTR32 teb;
2013 GLenum target;
2014 GLenum access;
2015 PTR32 ret;
2016 } *params32 = args;
2017 struct glMapBuffer_params params =
2019 .teb = get_teb64(params32->teb),
2020 .target = params32->target,
2021 .access = params32->access,
2023 NTSTATUS status;
2025 /* already mapped, we're being called again with a wow64 pointer */
2026 if (params32->ret) params.ret = get_buffer_pointer( params.teb, params.target );
2027 else if ((status = gl_map_buffer64( &params ))) return status;
2029 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, 0,
2030 map_range_flags_from_map_flags( params.access ), &params32->ret );
2031 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2033 unmap_buffer( params.teb, params.target );
2034 return status;
2037 NTSTATUS wow64_ext_glMapBuffer( void *args )
2039 return wow64_gl_map_buffer( args, ext_glMapBuffer );
2042 NTSTATUS wow64_ext_glMapBufferARB( void *args )
2044 return wow64_gl_map_buffer( args, ext_glMapBufferARB );
2047 NTSTATUS wow64_ext_glMapBufferRange( void *args )
2049 struct
2051 PTR32 teb;
2052 GLenum target;
2053 PTR32 offset;
2054 PTR32 length;
2055 GLbitfield access;
2056 PTR32 ret;
2057 } *params32 = args;
2058 struct glMapBufferRange_params params =
2060 .teb = get_teb64(params32->teb),
2061 .target = params32->target,
2062 .offset = (GLintptr)ULongToPtr(params32->offset),
2063 .length = (GLsizeiptr)ULongToPtr(params32->length),
2064 .access = params32->access,
2066 NTSTATUS status;
2068 /* already mapped, we're being called again with a wow64 pointer */
2069 if (params32->ret) params.ret = (char *)get_buffer_pointer( params.teb, params.target );
2070 else if ((status = ext_glMapBufferRange( &params ))) return status;
2072 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, params.length, params.access, &params32->ret );
2073 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2075 unmap_buffer( params.teb, params.target );
2076 return status;
2079 static NTSTATUS wow64_gl_map_named_buffer( void *args, NTSTATUS (*gl_map_named_buffer64)(void *) )
2081 struct
2083 PTR32 teb;
2084 GLuint buffer;
2085 GLenum access;
2086 PTR32 ret;
2087 } *params32 = args;
2088 struct glMapNamedBuffer_params params =
2090 .teb = get_teb64(params32->teb),
2091 .buffer = params32->buffer,
2092 .access = params32->access,
2094 NTSTATUS status;
2096 /* already mapped, we're being called again with a wow64 pointer */
2097 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2098 else if ((status = gl_map_named_buffer64( &params ))) return status;
2100 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, 0,
2101 map_range_flags_from_map_flags( params.access ), &params32->ret );
2102 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2104 unmap_named_buffer( params.teb, params.buffer );
2105 return status;
2108 NTSTATUS wow64_ext_glMapNamedBuffer( void *args )
2110 return wow64_gl_map_named_buffer( args, ext_glMapNamedBuffer );
2113 NTSTATUS wow64_ext_glMapNamedBufferEXT( void *args )
2115 return wow64_gl_map_named_buffer( args, ext_glMapNamedBufferEXT );
2118 static NTSTATUS wow64_gl_map_named_buffer_range( void *args, NTSTATUS (*gl_map_named_buffer_range64)(void *) )
2120 struct
2122 PTR32 teb;
2123 GLuint buffer;
2124 PTR32 offset;
2125 PTR32 length;
2126 GLbitfield access;
2127 PTR32 ret;
2128 } *params32 = args;
2129 struct glMapNamedBufferRange_params params =
2131 .teb = get_teb64(params32->teb),
2132 .buffer = params32->buffer,
2133 .offset = (GLintptr)ULongToPtr(params32->offset),
2134 .length = (GLsizeiptr)ULongToPtr(params32->length),
2135 .access = params32->access,
2137 NTSTATUS status;
2139 /* already mapped, we're being called again with a wow64 pointer */
2140 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2141 else if ((status = gl_map_named_buffer_range64( &params ))) return status;
2143 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, params.length, params.access, &params32->ret );
2144 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2146 unmap_named_buffer( params.teb, params.buffer );
2147 return status;
2150 NTSTATUS wow64_ext_glMapNamedBufferRange( void *args )
2152 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRange );
2155 NTSTATUS wow64_ext_glMapNamedBufferRangeEXT( void *args )
2157 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRangeEXT );
2160 static NTSTATUS wow64_gl_unmap_buffer( void *args, NTSTATUS (*gl_unmap_buffer64)(void *) )
2162 PTR32 *ptr;
2163 struct
2165 PTR32 teb;
2166 GLenum target;
2167 GLboolean ret;
2168 } *params32 = args;
2169 struct glUnmapBuffer_params params =
2171 .teb = get_teb64(params32->teb),
2172 .target = params32->target,
2173 .ret = TRUE,
2175 NTSTATUS status;
2177 if (!(ptr = get_buffer_pointer( params.teb, params.target ))) return STATUS_SUCCESS;
2179 status = wow64_unmap_buffer( ptr, get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ),
2180 get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ) );
2181 gl_unmap_buffer64( &params );
2182 params32->ret = params.ret;
2184 return status;
2187 NTSTATUS wow64_ext_glUnmapBuffer( void *args )
2189 return wow64_gl_unmap_buffer( args, ext_glUnmapBuffer );
2192 NTSTATUS wow64_ext_glUnmapBufferARB( void *args )
2194 return wow64_gl_unmap_buffer( args, ext_glUnmapBufferARB );
2197 static NTSTATUS wow64_gl_unmap_named_buffer( void *args, NTSTATUS (*gl_unmap_named_buffer64)(void *) )
2199 PTR32 *ptr;
2200 struct
2202 PTR32 teb;
2203 GLint buffer;
2204 GLboolean ret;
2205 } *params32 = args;
2206 struct glUnmapNamedBuffer_params params =
2208 .teb = get_teb64(params32->teb),
2209 .buffer = params32->buffer,
2210 .ret = TRUE,
2212 NTSTATUS status;
2214 if (!(ptr = get_named_buffer_pointer( params.teb, params.buffer ))) return STATUS_SUCCESS;
2216 status = wow64_unmap_buffer( ptr, get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ),
2217 get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ) );
2218 gl_unmap_named_buffer64( &params );
2219 params32->ret = params.ret;
2221 return status;
2224 NTSTATUS wow64_ext_glUnmapNamedBuffer( void *args )
2226 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBuffer );
2229 NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args )
2231 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT );
2234 NTSTATUS wow64_thread_attach( void *args )
2236 return thread_attach( get_teb64( (ULONG_PTR)args ));
2239 NTSTATUS wow64_process_detach( void *args )
2241 NTSTATUS status;
2243 if ((status = process_detach( NULL ))) return status;
2245 free( wow64_strings );
2246 wow64_strings = NULL;
2247 wow64_strings_count = 0;
2249 return STATUS_SUCCESS;
2252 NTSTATUS wow64_get_pixel_formats( void *args )
2254 struct
2256 PTR32 teb;
2257 PTR32 hdc;
2258 PTR32 formats;
2259 UINT max_formats;
2260 UINT num_formats;
2261 UINT num_onscreen_formats;
2262 } *params32 = args;
2263 struct get_pixel_formats_params params =
2265 .teb = get_teb64(params32->teb),
2266 .hdc = ULongToPtr(params32->hdc),
2267 .formats = ULongToPtr(params32->formats),
2268 .max_formats = params32->max_formats,
2270 NTSTATUS status;
2271 status = get_pixel_formats( &params );
2272 params32->num_formats = params.num_formats;
2273 params32->num_onscreen_formats = params.num_onscreen_formats;
2274 return status;
2277 #endif