opengl32: Skip debug callback messages called from native thread.
[wine.git] / dlls / opengl32 / unix_wgl.c
blob4cf128935410aba84be53f81dde8dc68f7e6fa6d
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 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, 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 GLuint *filter_extensions_index( TEB *teb, const char *disabled )
203 const struct opengl_funcs *funcs = teb->glTable;
204 GLuint *disabled_index;
205 GLint extensions_count;
206 unsigned int i = 0, j;
207 const char *ext;
209 if (!funcs->ext.p_glGetStringi)
211 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
212 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
213 if (!funcs->ext.p_glGetStringi) return NULL;
216 funcs->gl.p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count );
217 disabled_index = malloc( extensions_count * sizeof(*disabled_index) );
218 if (!disabled_index) return NULL;
220 TRACE( "GL_EXTENSIONS:\n" );
222 for (j = 0; j < extensions_count; ++j)
224 ext = (const char *)funcs->ext.p_glGetStringi( GL_EXTENSIONS, j );
226 /* We do not support GL_MAP_PERSISTENT_BIT, and hence
227 * ARB_buffer_storage, on wow64. */
228 if (is_win64 && is_wow64() && (!strcmp( ext, "GL_ARB_buffer_storage" ) || !strcmp( ext, "GL_EXT_buffer_storage" )))
230 TRACE( "-- %s (disabled due to wow64)\n", ext );
231 disabled_index[i++] = j;
233 else if (!has_extension( disabled, ext, strlen( ext ) ))
235 TRACE( "++ %s\n", ext );
237 else
239 TRACE( "-- %s (disabled by config)\n", ext );
240 disabled_index[i++] = j;
244 disabled_index[i] = ~0u;
245 return disabled_index;
248 static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
250 while (len--) *dst++ = (unsigned char)*src++;
253 static inline UINT asciiz_to_unicode( WCHAR *dst, const char *src )
255 WCHAR *p = dst;
256 while ((*p++ = *src++));
257 return (p - dst) * sizeof(WCHAR);
260 static inline void unicode_to_ascii( char *dst, const WCHAR *src, size_t len )
262 while (len--) *dst++ = *src++;
265 static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
267 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
268 OBJECT_ATTRIBUTES attr;
269 HANDLE ret;
271 attr.Length = sizeof(attr);
272 attr.RootDirectory = root;
273 attr.ObjectName = &nameW;
274 attr.Attributes = 0;
275 attr.SecurityDescriptor = NULL;
276 attr.SecurityQualityOfService = NULL;
278 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
281 static HKEY open_hkcu_key( const char *name )
283 WCHAR bufferW[256];
284 static HKEY hkcu;
286 if (!hkcu)
288 char buffer[256];
289 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
290 DWORD i, len = sizeof(sid_data);
291 SID *sid;
293 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
294 return 0;
296 sid = ((TOKEN_USER *)sid_data)->User.Sid;
297 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
298 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
299 sid->IdentifierAuthority.Value[4] ),
300 MAKEWORD( sid->IdentifierAuthority.Value[3],
301 sid->IdentifierAuthority.Value[2] )));
302 for (i = 0; i < sid->SubAuthorityCount; i++)
303 len += sprintf( buffer + len, "-%u", (int)sid->SubAuthority[i] );
305 ascii_to_unicode( bufferW, buffer, len );
306 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
309 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
312 static NTSTATUS query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
314 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
315 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
317 return NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size, &size );
320 /* build the extension string by filtering out the disabled extensions */
321 static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts_list, GLuint **disabled_exts )
323 static const char *disabled;
325 if (!disabled)
327 char *str = NULL;
328 HKEY hkey;
330 /* @@ Wine registry key: HKCU\Software\Wine\OpenGL */
331 if ((hkey = open_hkcu_key( "Software\\Wine\\OpenGL" )))
333 char buffer[4096];
334 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
335 static WCHAR disabled_extensionsW[] = {'D','i','s','a','b','l','e','d','E','x','t','e','n','s','i','o','n','s',0};
337 if (!query_reg_value( hkey, disabled_extensionsW, value, sizeof(buffer) ))
339 ULONG len = value->DataLength / sizeof(WCHAR);
341 unicode_to_ascii( buffer, (WCHAR *)value->Data, len );
342 buffer[len] = 0;
343 str = strdup( buffer );
345 NtClose( hkey );
347 if (str)
349 if (InterlockedCompareExchangePointer( (void **)&disabled, str, NULL )) free( str );
351 else disabled = "";
354 if (extensions && !*exts_list) *exts_list = filter_extensions_list( extensions, disabled );
355 if (!*disabled_exts) *disabled_exts = filter_extensions_index( teb, disabled );
356 return (exts_list && *exts_list) || *disabled_exts;
359 static const GLuint *disabled_extensions_index( TEB *teb )
361 struct wgl_handle *ptr = get_current_context_ptr( teb );
362 GLuint **disabled = &ptr->u.context->disabled_exts;
363 if (*disabled || filter_extensions( teb, NULL, NULL, disabled )) return *disabled;
364 return NULL;
367 /* Check if a GL extension is supported */
368 static BOOL check_extension_support( TEB *teb, const char *extension, const char *available_extensions )
370 const struct opengl_funcs *funcs = teb->glTable;
371 size_t len;
373 TRACE( "Checking for extension '%s'\n", extension );
375 /* We use the GetProcAddress function from the display driver to retrieve function pointers
376 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
377 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
378 * require the function to return NULL when an extension isn't found. For this reason we check
379 * if the OpenGL extension required for the function we are looking up is supported. */
381 while ((len = strcspn( extension, " " )))
383 /* Check if the extension is part of the GL extension string to see if it is supported. */
384 if (has_extension( available_extensions, extension, len )) return TRUE;
386 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
387 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
388 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
389 * Check if we are searching for a core GL function */
390 if (!strncmp( extension, "GL_VERSION_", 11 ))
392 const GLubyte *gl_version = funcs->gl.p_glGetString( GL_VERSION );
393 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
395 if (!gl_version)
397 ERR( "No OpenGL version found!\n" );
398 return FALSE;
401 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
402 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
403 if ((gl_version[0] > version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2]))) return TRUE;
405 WARN( "The function requires OpenGL version '%c.%c' while your drivers only provide '%c.%c'\n",
406 version[0], version[2], gl_version[0], gl_version[2] );
409 if (extension[len] == ' ') len++;
410 extension += len;
413 return FALSE;
416 static const char *parse_gl_version( const char *gl_version, int *major, int *minor )
418 const char *ptr = gl_version;
420 *major = atoi( ptr );
421 if (*major <= 0)
422 ERR( "Invalid OpenGL major version %d.\n", *major );
424 while (isdigit( *ptr )) ++ptr;
425 if (*ptr++ != '.')
426 ERR( "Invalid OpenGL version string %s.\n", debugstr_a(gl_version) );
428 *minor = atoi( ptr );
430 while (isdigit( *ptr )) ++ptr;
431 return ptr;
434 static void wrap_glGetIntegerv( TEB *teb, GLenum pname, GLint *data )
436 const struct opengl_funcs *funcs = teb->glTable;
437 const GLuint *disabled;
439 funcs->gl.p_glGetIntegerv( pname, data );
441 if (pname == GL_NUM_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
442 while (*disabled++ != ~0u) (*data)--;
444 if (is_win64 && is_wow64())
446 /* 4.4 depends on ARB_buffer_storage, which we don't support on wow64. */
447 if (pname == GL_MAJOR_VERSION && *data > 4)
448 *data = 4;
449 else if (pname == GL_MINOR_VERSION)
451 GLint major;
453 funcs->gl.p_glGetIntegerv( GL_MAJOR_VERSION, &major );
454 if (major == 4 && *data > 3)
455 *data = 3;
460 static const GLubyte *wrap_glGetString( TEB *teb, GLenum name )
462 const struct opengl_funcs *funcs = teb->glTable;
463 const GLubyte *ret;
465 if ((ret = funcs->gl.p_glGetString( name )))
467 if (name == GL_EXTENSIONS)
469 struct wgl_handle *ptr = get_current_context_ptr( teb );
470 GLubyte **extensions = &ptr->u.context->extensions;
471 GLuint **disabled = &ptr->u.context->disabled_exts;
472 if (*extensions || filter_extensions( teb, (const char *)ret, extensions, disabled )) return *extensions;
474 else if (name == GL_VERSION && is_win64 && is_wow64())
476 struct wgl_handle *ptr = get_current_context_ptr( teb );
477 int major, minor;
478 const char *rest;
480 if (ptr->u.context->version_string)
481 return ptr->u.context->version_string;
483 rest = parse_gl_version( (const char *)ret, &major, &minor );
485 /* 4.4 depends on ARB_buffer_storage, which we don't support on wow64. */
486 if (major > 4 || (major == 4 && minor >= 4))
488 char *str = malloc( 3 + strlen( rest ) + 1 );
490 sprintf( str, "4.3%s", rest );
491 if (InterlockedCompareExchangePointer( (void **)&ptr->u.context->version_string, str, NULL ))
492 free( str );
493 return ptr->u.context->version_string;
498 return ret;
501 static const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index )
503 const struct opengl_funcs *funcs = teb->glTable;
504 const GLuint *disabled;
506 if (!funcs->ext.p_glGetStringi)
508 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
509 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
512 if (name == GL_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
513 while (index >= *disabled++) index++;
515 return funcs->ext.p_glGetStringi( name, index );
518 static char *build_extension_list( TEB *teb )
520 GLint len = 0, capacity, i, extensions_count;
521 char *extension, *tmp, *available_extensions;
523 wrap_glGetIntegerv( teb, GL_NUM_EXTENSIONS, &extensions_count );
524 capacity = 128 * extensions_count;
526 if (!(available_extensions = malloc( capacity ))) return NULL;
527 for (i = 0; i < extensions_count; ++i)
529 extension = (char *)wrap_glGetStringi( teb, GL_EXTENSIONS, i );
530 capacity = max( capacity, len + strlen( extension ) + 2 );
531 if (!(tmp = realloc( available_extensions, capacity ))) break;
532 available_extensions = tmp;
533 len += sprintf( available_extensions + len, "%s ", extension );
535 if (len) available_extensions[len - 1] = 0;
537 return available_extensions;
540 static inline enum wgl_handle_type get_current_context_type( TEB *teb )
542 if (!teb->glCurrentRC) return HANDLE_CONTEXT;
543 return LOWORD(teb->glCurrentRC) & HANDLE_TYPE_MASK;
546 /* Check if a GL extension is supported */
547 static BOOL is_extension_supported( TEB *teb, const char *extension )
549 enum wgl_handle_type type = get_current_context_type( teb );
550 char *available_extensions = NULL;
551 BOOL ret = FALSE;
553 if (type == HANDLE_CONTEXT) available_extensions = strdup( (const char *)wrap_glGetString( teb, GL_EXTENSIONS ) );
554 if (!available_extensions) available_extensions = build_extension_list( teb );
556 if (!available_extensions) ERR( "No OpenGL extensions found, check if your OpenGL setup is correct!\n" );
557 else ret = check_extension_support( teb, extension, available_extensions );
559 free( available_extensions );
560 return ret;
563 static int registry_entry_cmp( const void *a, const void *b )
565 const struct registry_entry *entry_a = a, *entry_b = b;
566 return strcmp( entry_a->name, entry_b->name );
569 static PROC wrap_wglGetProcAddress( TEB *teb, LPCSTR name )
571 const struct registry_entry entry = {.name = name}, *found;
572 struct opengl_funcs *funcs = teb->glTable;
573 const void **func_ptr;
575 /* Without an active context opengl32 doesn't know to what
576 * driver it has to dispatch wglGetProcAddress.
578 if (!get_current_context_ptr( teb ))
580 WARN( "No active WGL context found\n" );
581 return (void *)-1;
584 if (!(found = bsearch( &entry, extension_registry, extension_registry_size, sizeof(entry), registry_entry_cmp )))
586 WARN( "Function %s unknown\n", name );
587 return (void *)-1;
590 func_ptr = (const void **)&funcs->ext + (found - extension_registry);
591 if (!*func_ptr)
593 void *driver_func = funcs->wgl.p_wglGetProcAddress( name );
595 if (!is_extension_supported( teb, found->extension ))
597 unsigned int i;
598 static const struct { const char *name, *alt; } alternatives[] =
600 { "glCopyTexSubImage3DEXT", "glCopyTexSubImage3D" }, /* needed by RuneScape */
601 { "glVertexAttribDivisor", "glVertexAttribDivisorARB"}, /* needed by Caffeine */
604 for (i = 0; i < ARRAY_SIZE(alternatives); i++)
606 if (strcmp( name, alternatives[i].name )) continue;
607 WARN( "Extension %s required for %s not supported, trying %s\n", found->extension,
608 name, alternatives[i].alt );
609 return wrap_wglGetProcAddress( teb, alternatives[i].alt );
612 WARN( "Extension %s required for %s not supported\n", found->extension, name );
613 return (void *)-1;
616 if (driver_func == NULL)
618 WARN( "Function %s not supported by driver\n", name );
619 return (void *)-1;
622 *func_ptr = driver_func;
625 /* Return the index into the extension registry instead of a useless
626 * function pointer, PE side will returns its own function pointers.
628 return (void *)(UINT_PTR)(found - extension_registry);
631 static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
633 struct wgl_handle *src, *dst;
634 BOOL ret = FALSE;
636 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
637 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
639 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
640 else ret = src->funcs->wgl.p_wglCopyContext( src->u.context->drv_ctx, dst->u.context->drv_ctx, mask );
642 return ret;
645 static HGLRC wrap_wglCreateContext( HDC hdc )
647 HGLRC ret = 0;
648 struct wgl_context *drv_ctx;
649 struct opengl_context *context;
650 struct opengl_funcs *funcs = get_dc_funcs( hdc );
652 if (!funcs) return 0;
653 if (!(drv_ctx = funcs->wgl.p_wglCreateContext( hdc ))) return 0;
654 if ((context = calloc( 1, sizeof(*context) )))
656 context->drv_ctx = drv_ctx;
657 if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context );
659 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
660 return ret;
663 static BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc )
665 BOOL ret = TRUE;
666 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
667 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
669 if (hglrc)
671 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
672 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
674 ret = ptr->funcs->wgl.p_wglMakeCurrent( hdc, ptr->u.context->drv_ctx );
675 if (ret)
677 if (prev) prev->u.context->tid = 0;
678 ptr->u.context->tid = tid;
679 teb->glReserved1[0] = hdc;
680 teb->glReserved1[1] = hdc;
681 teb->glCurrentRC = hglrc;
682 teb->glTable = ptr->funcs;
685 else
687 RtlSetLastWin32Error( ERROR_BUSY );
688 ret = FALSE;
691 else if (prev)
693 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
694 prev->u.context->tid = 0;
695 teb->glCurrentRC = 0;
696 teb->glTable = &null_opengl_funcs;
698 else if (!hdc)
700 RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
701 ret = FALSE;
703 return ret;
706 static BOOL wrap_wglDeleteContext( TEB *teb, HGLRC hglrc )
708 struct wgl_handle *ptr;
709 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
711 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
712 if (ptr->u.context->tid && ptr->u.context->tid != tid)
714 RtlSetLastWin32Error( ERROR_BUSY );
715 return FALSE;
717 if (hglrc == teb->glCurrentRC) wrap_wglMakeCurrent( teb, 0, 0 );
718 ptr->funcs->wgl.p_wglDeleteContext( ptr->u.context->drv_ctx );
719 free( ptr->u.context->version_string );
720 free( ptr->u.context->disabled_exts );
721 free( ptr->u.context->extensions );
722 free( ptr->u.context );
723 free_handle_ptr( ptr );
724 return TRUE;
727 static BOOL wrap_wglShareLists( HGLRC hglrcSrc, HGLRC hglrcDst )
729 BOOL ret = FALSE;
730 struct wgl_handle *src, *dst;
732 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
733 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
735 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
736 else ret = src->funcs->wgl.p_wglShareLists( src->u.context->drv_ctx, dst->u.context->drv_ctx );
738 return ret;
741 static BOOL wrap_wglBindTexImageARB( HPBUFFERARB handle, int buffer )
743 struct wgl_handle *ptr;
744 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
745 return ptr->funcs->ext.p_wglBindTexImageARB( ptr->u.pbuffer, buffer );
748 static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *attribs )
750 HGLRC ret = 0;
751 struct wgl_context *drv_ctx;
752 struct wgl_handle *share_ptr = NULL;
753 struct opengl_context *context;
754 struct opengl_funcs *funcs = get_dc_funcs( hdc );
756 if (!funcs)
758 RtlSetLastWin32Error( ERROR_DC_NOT_FOUND );
759 return 0;
761 if (!funcs->ext.p_wglCreateContextAttribsARB) return 0;
762 if (share && !(share_ptr = get_handle_ptr( share, HANDLE_CONTEXT )))
764 RtlSetLastWin32Error( ERROR_INVALID_OPERATION );
765 return 0;
767 if ((drv_ctx = funcs->ext.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->u.context->drv_ctx : NULL, attribs )))
769 if ((context = calloc( 1, sizeof(*context) )))
771 enum wgl_handle_type type = HANDLE_CONTEXT;
773 if (attribs)
775 while (*attribs)
777 if (attribs[0] == WGL_CONTEXT_MAJOR_VERSION_ARB)
779 if (attribs[1] >= 3) type = HANDLE_CONTEXT_V3;
780 break;
782 attribs += 2;
786 context->drv_ctx = drv_ctx;
787 if (!(ret = alloc_handle( type, funcs, context ))) free( context );
789 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
792 return ret;
795 static HPBUFFERARB wrap_wglCreatePbufferARB( HDC hdc, int format, int width, int height, const int *attribs )
797 HPBUFFERARB ret;
798 struct wgl_pbuffer *pbuffer;
799 struct opengl_funcs *funcs = get_dc_funcs( hdc );
801 if (!funcs || !funcs->ext.p_wglCreatePbufferARB) return 0;
802 if (!(pbuffer = funcs->ext.p_wglCreatePbufferARB( hdc, format, width, height, attribs ))) return 0;
803 ret = alloc_handle( HANDLE_PBUFFER, funcs, pbuffer );
804 if (!ret) funcs->ext.p_wglDestroyPbufferARB( pbuffer );
805 return ret;
808 static BOOL wrap_wglDestroyPbufferARB( HPBUFFERARB handle )
810 struct wgl_handle *ptr;
812 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
813 ptr->funcs->ext.p_wglDestroyPbufferARB( ptr->u.pbuffer );
814 free_handle_ptr( ptr );
815 return TRUE;
818 static HDC wrap_wglGetPbufferDCARB( HPBUFFERARB handle )
820 struct wgl_handle *ptr;
821 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return 0;
822 return ptr->funcs->ext.p_wglGetPbufferDCARB( ptr->u.pbuffer );
825 static BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC hglrc )
827 BOOL ret = TRUE;
828 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
829 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
831 if (hglrc)
833 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
834 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
836 ret = (ptr->funcs->ext.p_wglMakeContextCurrentARB &&
837 ptr->funcs->ext.p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->u.context->drv_ctx ));
838 if (ret)
840 if (prev) prev->u.context->tid = 0;
841 ptr->u.context->tid = tid;
842 teb->glReserved1[0] = draw_hdc;
843 teb->glReserved1[1] = read_hdc;
844 teb->glCurrentRC = hglrc;
845 teb->glTable = ptr->funcs;
848 else
850 RtlSetLastWin32Error( ERROR_BUSY );
851 ret = FALSE;
854 else if (prev)
856 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
857 prev->u.context->tid = 0;
858 teb->glCurrentRC = 0;
859 teb->glTable = &null_opengl_funcs;
861 return ret;
864 static BOOL wrap_wglQueryPbufferARB( HPBUFFERARB handle, int attrib, int *value )
866 struct wgl_handle *ptr;
867 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
868 return ptr->funcs->ext.p_wglQueryPbufferARB( ptr->u.pbuffer, attrib, value );
871 static int wrap_wglReleasePbufferDCARB( HPBUFFERARB handle, HDC hdc )
873 struct wgl_handle *ptr;
874 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
875 return ptr->funcs->ext.p_wglReleasePbufferDCARB( ptr->u.pbuffer, hdc );
878 static BOOL wrap_wglReleaseTexImageARB( HPBUFFERARB handle, int buffer )
880 struct wgl_handle *ptr;
881 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
882 return ptr->funcs->ext.p_wglReleaseTexImageARB( ptr->u.pbuffer, buffer );
885 static BOOL wrap_wglSetPbufferAttribARB( HPBUFFERARB handle, const int *attribs )
887 struct wgl_handle *ptr;
888 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
889 return ptr->funcs->ext.p_wglSetPbufferAttribARB( ptr->u.pbuffer, attribs );
892 static void gl_debug_message_callback( GLenum source, GLenum type, GLuint id, GLenum severity,
893 GLsizei length, const GLchar *message, const void *userParam )
895 struct wine_gl_debug_message_params params =
897 .source = source,
898 .type = type,
899 .id = id,
900 .severity = severity,
901 .length = length,
902 .message = message,
904 void *ret_ptr;
905 ULONG ret_len;
906 struct wgl_handle *ptr = (struct wgl_handle *)userParam;
908 if (!NtCurrentTeb())
910 fprintf( stderr, "msg:gl_debug_message_callback called from native thread, severity %#x, message \"%.*s\".\n",
911 severity, length, message );
912 return;
915 if (!(params.user_callback = ptr->u.context->debug_callback)) return;
916 params.user_data = ptr->u.context->debug_user;
918 KeUserModeCallback( NtUserCallOpenGLDebugMessageCallback, &params, sizeof(params),
919 &ret_ptr, &ret_len );
922 static void wrap_glDebugMessageCallback( TEB *teb, GLDEBUGPROC callback, const void *userParam )
924 struct wgl_handle *ptr = get_current_context_ptr( teb );
925 const struct opengl_funcs *funcs = teb->glTable;
927 if (!funcs->ext.p_glDebugMessageCallback) return;
929 ptr->u.context->debug_callback = callback;
930 ptr->u.context->debug_user = userParam;
931 funcs->ext.p_glDebugMessageCallback( gl_debug_message_callback, ptr );
934 static void wrap_glDebugMessageCallbackAMD( TEB *teb, GLDEBUGPROCAMD callback, void *userParam )
936 struct wgl_handle *ptr = get_current_context_ptr( teb );
937 const struct opengl_funcs *funcs = teb->glTable;
939 if (!funcs->ext.p_glDebugMessageCallbackAMD) return;
941 ptr->u.context->debug_callback = callback;
942 ptr->u.context->debug_user = userParam;
943 funcs->ext.p_glDebugMessageCallbackAMD( gl_debug_message_callback, ptr );
946 static void wrap_glDebugMessageCallbackARB( TEB *teb, GLDEBUGPROCARB callback, const void *userParam )
948 struct wgl_handle *ptr = get_current_context_ptr( teb );
949 const struct opengl_funcs *funcs = teb->glTable;
951 if (!funcs->ext.p_glDebugMessageCallbackARB) return;
953 ptr->u.context->debug_callback = callback;
954 ptr->u.context->debug_user = userParam;
955 funcs->ext.p_glDebugMessageCallbackARB( gl_debug_message_callback, ptr );
958 NTSTATUS wgl_wglCopyContext( void *args )
960 struct wglCopyContext_params *params = args;
961 pthread_mutex_lock( &wgl_lock );
962 params->ret = wrap_wglCopyContext( params->hglrcSrc, params->hglrcDst, params->mask );
963 pthread_mutex_unlock( &wgl_lock );
964 return STATUS_SUCCESS;
967 NTSTATUS wgl_wglCreateContext( void *args )
969 struct wglCreateContext_params *params = args;
970 pthread_mutex_lock( &wgl_lock );
971 params->ret = wrap_wglCreateContext( params->hDc );
972 pthread_mutex_unlock( &wgl_lock );
973 return STATUS_SUCCESS;
976 NTSTATUS wgl_wglDeleteContext( void *args )
978 struct wglDeleteContext_params *params = args;
979 pthread_mutex_lock( &wgl_lock );
980 params->ret = wrap_wglDeleteContext( params->teb, params->oldContext );
981 pthread_mutex_unlock( &wgl_lock );
982 return STATUS_SUCCESS;
985 NTSTATUS wgl_wglGetProcAddress( void *args )
987 struct wglGetProcAddress_params *params = args;
988 params->ret = wrap_wglGetProcAddress( params->teb, params->lpszProc );
989 return STATUS_SUCCESS;
992 NTSTATUS wgl_wglMakeCurrent( void *args )
994 struct wglMakeCurrent_params *params = args;
995 if (params->newContext) pthread_mutex_lock( &wgl_lock );
996 params->ret = wrap_wglMakeCurrent( params->teb, params->hDc, params->newContext );
997 if (params->newContext) pthread_mutex_unlock( &wgl_lock );
998 return STATUS_SUCCESS;
1001 NTSTATUS wgl_wglShareLists( void *args )
1003 struct wglShareLists_params *params = args;
1004 pthread_mutex_lock( &wgl_lock );
1005 params->ret = wrap_wglShareLists( params->hrcSrvShare, params->hrcSrvSource );
1006 pthread_mutex_unlock( &wgl_lock );
1007 return STATUS_SUCCESS;
1010 NTSTATUS gl_glGetIntegerv( void *args )
1012 struct glGetIntegerv_params *params = args;
1013 wrap_glGetIntegerv( params->teb, params->pname, params->data );
1014 return STATUS_SUCCESS;
1017 NTSTATUS gl_glGetString( void *args )
1019 struct glGetString_params *params = args;
1020 params->ret = wrap_glGetString( params->teb, params->name );
1021 return STATUS_SUCCESS;
1024 NTSTATUS ext_glDebugMessageCallback( void *args )
1026 struct glDebugMessageCallback_params *params = args;
1027 wrap_glDebugMessageCallback( params->teb, params->callback, params->userParam );
1028 return STATUS_SUCCESS;
1031 NTSTATUS ext_glDebugMessageCallbackAMD( void *args )
1033 struct glDebugMessageCallbackAMD_params *params = args;
1034 wrap_glDebugMessageCallbackAMD( params->teb, params->callback, params->userParam );
1035 return STATUS_SUCCESS;
1038 NTSTATUS ext_glDebugMessageCallbackARB( void *args )
1040 struct glDebugMessageCallbackARB_params *params = args;
1041 wrap_glDebugMessageCallbackARB( params->teb, params->callback, params->userParam );
1042 return STATUS_SUCCESS;
1045 NTSTATUS ext_glGetStringi( void *args )
1047 struct glGetStringi_params *params = args;
1048 params->ret = wrap_glGetStringi( params->teb, params->name, params->index );
1049 return STATUS_SUCCESS;
1052 NTSTATUS ext_wglBindTexImageARB( void *args )
1054 struct wglBindTexImageARB_params *params = args;
1055 pthread_mutex_lock( &wgl_lock );
1056 params->ret = wrap_wglBindTexImageARB( params->hPbuffer, params->iBuffer );
1057 pthread_mutex_unlock( &wgl_lock );
1058 return STATUS_SUCCESS;
1061 NTSTATUS ext_wglCreateContextAttribsARB( void *args )
1063 struct wglCreateContextAttribsARB_params *params = args;
1064 pthread_mutex_lock( &wgl_lock );
1065 params->ret = wrap_wglCreateContextAttribsARB( params->hDC, params->hShareContext, params->attribList );
1066 pthread_mutex_unlock( &wgl_lock );
1067 return STATUS_SUCCESS;
1070 NTSTATUS ext_wglCreatePbufferARB( void *args )
1072 struct wglCreatePbufferARB_params *params = args;
1073 pthread_mutex_lock( &wgl_lock );
1074 params->ret = wrap_wglCreatePbufferARB( params->hDC, params->iPixelFormat, params->iWidth, params->iHeight, params->piAttribList );
1075 pthread_mutex_unlock( &wgl_lock );
1076 return STATUS_SUCCESS;
1079 NTSTATUS ext_wglDestroyPbufferARB( void *args )
1081 struct wglDestroyPbufferARB_params *params = args;
1082 pthread_mutex_lock( &wgl_lock );
1083 params->ret = wrap_wglDestroyPbufferARB( params->hPbuffer );
1084 pthread_mutex_unlock( &wgl_lock );
1085 return STATUS_SUCCESS;
1088 NTSTATUS ext_wglGetPbufferDCARB( void *args )
1090 struct wglGetPbufferDCARB_params *params = args;
1091 pthread_mutex_lock( &wgl_lock );
1092 params->ret = wrap_wglGetPbufferDCARB( params->hPbuffer );
1093 pthread_mutex_unlock( &wgl_lock );
1094 return STATUS_SUCCESS;
1097 NTSTATUS ext_wglMakeContextCurrentARB( void *args )
1099 struct wglMakeContextCurrentARB_params *params = args;
1100 if (params->hglrc) pthread_mutex_lock( &wgl_lock );
1101 params->ret = wrap_wglMakeContextCurrentARB( params->teb, params->hDrawDC, params->hReadDC, params->hglrc );
1102 if (params->hglrc) pthread_mutex_unlock( &wgl_lock );
1103 return STATUS_SUCCESS;
1106 NTSTATUS ext_wglQueryPbufferARB( void *args )
1108 struct wglQueryPbufferARB_params *params = args;
1109 pthread_mutex_lock( &wgl_lock );
1110 params->ret = wrap_wglQueryPbufferARB( params->hPbuffer, params->iAttribute, params->piValue );
1111 pthread_mutex_unlock( &wgl_lock );
1112 return STATUS_SUCCESS;
1115 NTSTATUS ext_wglReleasePbufferDCARB( void *args )
1117 struct wglReleasePbufferDCARB_params *params = args;
1118 pthread_mutex_lock( &wgl_lock );
1119 params->ret = wrap_wglReleasePbufferDCARB( params->hPbuffer, params->hDC );
1120 pthread_mutex_unlock( &wgl_lock );
1121 return STATUS_SUCCESS;
1124 NTSTATUS ext_wglReleaseTexImageARB( void *args )
1126 struct wglReleaseTexImageARB_params *params = args;
1127 pthread_mutex_lock( &wgl_lock );
1128 params->ret = wrap_wglReleaseTexImageARB( params->hPbuffer, params->iBuffer );
1129 pthread_mutex_unlock( &wgl_lock );
1130 return STATUS_SUCCESS;
1133 NTSTATUS ext_wglSetPbufferAttribARB( void *args )
1135 struct wglSetPbufferAttribARB_params *params = args;
1136 pthread_mutex_lock( &wgl_lock );
1137 params->ret = wrap_wglSetPbufferAttribARB( params->hPbuffer, params->piAttribList );
1138 pthread_mutex_unlock( &wgl_lock );
1139 return STATUS_SUCCESS;
1142 NTSTATUS thread_attach( void *args )
1144 TEB *teb = args;
1145 teb->glTable = &null_opengl_funcs;
1146 return STATUS_SUCCESS;
1149 NTSTATUS process_detach( void *args )
1151 return STATUS_SUCCESS;
1154 #ifdef _WIN64
1156 typedef ULONG PTR32;
1158 extern NTSTATUS ext_glClientWaitSync( void *args ) DECLSPEC_HIDDEN;
1159 extern NTSTATUS ext_glDeleteSync( void *args ) DECLSPEC_HIDDEN;
1160 extern NTSTATUS ext_glFenceSync( void *args ) DECLSPEC_HIDDEN;
1161 extern NTSTATUS ext_glGetBufferPointerv( void *args ) DECLSPEC_HIDDEN;
1162 extern NTSTATUS ext_glGetBufferPointervARB( void *args ) DECLSPEC_HIDDEN;
1163 extern NTSTATUS ext_glGetNamedBufferPointerv( void *args ) DECLSPEC_HIDDEN;
1164 extern NTSTATUS ext_glGetNamedBufferPointervEXT( void *args ) DECLSPEC_HIDDEN;
1165 extern NTSTATUS ext_glGetSynciv( void *args ) DECLSPEC_HIDDEN;
1166 extern NTSTATUS ext_glIsSync( void *args ) DECLSPEC_HIDDEN;
1167 extern NTSTATUS ext_glMapBuffer( void *args ) DECLSPEC_HIDDEN;
1169 extern NTSTATUS ext_glUnmapBuffer( void *args ) DECLSPEC_HIDDEN;
1170 extern NTSTATUS ext_glUnmapBufferARB( void *args ) DECLSPEC_HIDDEN;
1171 extern NTSTATUS ext_glUnmapNamedBuffer( void *args ) DECLSPEC_HIDDEN;
1172 extern NTSTATUS ext_glUnmapNamedBufferEXT( void *args ) DECLSPEC_HIDDEN;
1174 extern NTSTATUS ext_glMapBufferARB( void *args ) DECLSPEC_HIDDEN;
1175 extern NTSTATUS ext_glMapBufferRange( void *args ) DECLSPEC_HIDDEN;
1176 extern NTSTATUS ext_glMapNamedBuffer( void *args ) DECLSPEC_HIDDEN;
1177 extern NTSTATUS ext_glMapNamedBufferEXT( void *args ) DECLSPEC_HIDDEN;
1178 extern NTSTATUS ext_glMapNamedBufferRange( void *args ) DECLSPEC_HIDDEN;
1179 extern NTSTATUS ext_glMapNamedBufferRangeEXT( void *args ) DECLSPEC_HIDDEN;
1180 extern NTSTATUS ext_glPathGlyphIndexRangeNV( void *args ) DECLSPEC_HIDDEN;
1181 extern NTSTATUS ext_glWaitSync( void *args ) DECLSPEC_HIDDEN;
1182 extern NTSTATUS ext_wglGetExtensionsStringARB( void *args ) DECLSPEC_HIDDEN;
1183 extern NTSTATUS ext_wglGetExtensionsStringEXT( void *args ) DECLSPEC_HIDDEN;
1184 extern NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
1185 extern NTSTATUS ext_wglQueryRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
1187 struct wow64_string_entry
1189 const char *str;
1190 PTR32 wow64_str;
1192 static struct wow64_string_entry *wow64_strings;
1193 static SIZE_T wow64_strings_count;
1195 static PTR32 find_wow64_string( const char *str, PTR32 wow64_str )
1197 void *tmp;
1198 SIZE_T i;
1200 pthread_mutex_lock( &wgl_lock );
1202 for (i = 0; i < wow64_strings_count; i++) if (wow64_strings[i].str == str) break;
1203 if (i == wow64_strings_count && (tmp = realloc( wow64_strings, (i + 1) * sizeof(*wow64_strings) )))
1205 wow64_strings = tmp;
1206 wow64_strings[i].str = str;
1207 wow64_strings[i].wow64_str = 0;
1208 wow64_strings_count += 1;
1211 if (i == wow64_strings_count) ERR( "Failed to allocate memory for wow64 strings\n" );
1212 else if (wow64_strings[i].wow64_str) wow64_str = wow64_strings[i].wow64_str;
1213 else if (wow64_str)
1215 strcpy( UlongToPtr(wow64_str), (char *)str );
1216 wow64_strings[i].wow64_str = wow64_str;
1219 pthread_mutex_unlock( &wgl_lock );
1221 return wow64_str;
1224 static inline void update_teb32_context( TEB *teb )
1226 void *teb32;
1228 if (!teb->WowTebOffset) return;
1229 teb32 = (char *)teb + teb->WowTebOffset;
1231 ((TEB32 *)teb32)->glCurrentRC = (UINT_PTR)teb->glCurrentRC;
1232 ((TEB32 *)teb32)->glReserved1[0] = (UINT_PTR)teb->glReserved1[0];
1233 ((TEB32 *)teb32)->glReserved1[1] = (UINT_PTR)teb->glReserved1[1];
1236 NTSTATUS wow64_wgl_wglCreateContext( void *args )
1238 struct
1240 PTR32 teb;
1241 PTR32 hDc;
1242 PTR32 ret;
1243 } *params32 = args;
1244 struct wglCreateContext_params params =
1246 .teb = get_teb64(params32->teb),
1247 .hDc = ULongToPtr(params32->hDc),
1249 NTSTATUS status;
1250 if ((status = wgl_wglCreateContext( &params ))) return status;
1251 params32->ret = (UINT_PTR)params.ret;
1252 return STATUS_SUCCESS;
1255 NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args )
1257 struct
1259 PTR32 teb;
1260 PTR32 hDC;
1261 PTR32 hShareContext;
1262 PTR32 attribList;
1263 PTR32 ret;
1264 } *params32 = args;
1265 struct wglCreateContextAttribsARB_params params =
1267 .teb = get_teb64(params32->teb),
1268 .hDC = ULongToPtr(params32->hDC),
1269 .hShareContext = ULongToPtr(params32->hShareContext),
1270 .attribList = ULongToPtr(params32->attribList),
1272 NTSTATUS status;
1273 if ((status = ext_wglCreateContextAttribsARB( &params ))) return status;
1274 params32->ret = (UINT_PTR)params.ret;
1275 return STATUS_SUCCESS;
1278 NTSTATUS wow64_ext_wglCreatePbufferARB( void *args )
1280 struct
1282 PTR32 teb;
1283 PTR32 hDC;
1284 GLint iPixelFormat;
1285 GLint iWidth;
1286 GLint iHeight;
1287 PTR32 piAttribList;
1288 PTR32 ret;
1289 } *params32 = args;
1290 struct wglCreatePbufferARB_params params =
1292 .teb = get_teb64(params32->teb),
1293 .hDC = ULongToPtr(params32->hDC),
1294 .iPixelFormat = params32->iPixelFormat,
1295 .iWidth = params32->iWidth,
1296 .iHeight = params32->iHeight,
1297 .piAttribList = ULongToPtr(params32->piAttribList),
1299 NTSTATUS status;
1300 if ((status = ext_wglCreatePbufferARB( &params ))) return status;
1301 params32->ret = (UINT_PTR)params.ret;
1302 return STATUS_SUCCESS;
1305 NTSTATUS wow64_wgl_wglDeleteContext( void *args )
1307 struct
1309 PTR32 teb;
1310 PTR32 oldContext;
1311 BOOL ret;
1312 } *params32 = args;
1313 struct wglDeleteContext_params params =
1315 .teb = get_teb64(params32->teb),
1316 .oldContext = ULongToPtr(params32->oldContext),
1318 NTSTATUS status;
1319 if (!(status = wgl_wglDeleteContext( &params ))) update_teb32_context( params.teb );
1320 params32->ret = params.ret;
1321 return status;
1324 NTSTATUS wow64_wgl_wglMakeCurrent( void *args )
1326 struct
1328 PTR32 teb;
1329 PTR32 hDc;
1330 PTR32 newContext;
1331 BOOL ret;
1332 } *params32 = args;
1333 struct wglMakeCurrent_params params =
1335 .teb = get_teb64(params32->teb),
1336 .hDc = ULongToPtr(params32->hDc),
1337 .newContext = ULongToPtr(params32->newContext),
1339 NTSTATUS status;
1340 if (!(status = wgl_wglMakeCurrent( &params ))) update_teb32_context( params.teb );
1341 params32->ret = params.ret;
1342 return status;
1345 NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args )
1347 struct
1349 PTR32 teb;
1350 PTR32 hDrawDC;
1351 PTR32 hReadDC;
1352 PTR32 hglrc;
1353 BOOL ret;
1354 } *params32 = args;
1355 struct wglMakeContextCurrentARB_params params =
1357 .teb = get_teb64(params32->teb),
1358 .hDrawDC = ULongToPtr(params32->hDrawDC),
1359 .hReadDC = ULongToPtr(params32->hReadDC),
1360 .hglrc = ULongToPtr(params32->hglrc),
1362 NTSTATUS status;
1363 if (!(status = ext_wglMakeContextCurrentARB( &params ))) update_teb32_context( params.teb );
1364 params32->ret = params.ret;
1365 return status;
1368 NTSTATUS wow64_ext_wglGetPbufferDCARB( void *args )
1370 struct
1372 PTR32 teb;
1373 PTR32 hPbuffer;
1374 PTR32 ret;
1375 } *params32 = args;
1376 struct wglGetPbufferDCARB_params params =
1378 .teb = get_teb64(params32->teb),
1379 .hPbuffer = (HPBUFFERARB)ULongToPtr(params32->hPbuffer),
1381 NTSTATUS status;
1382 if ((status = ext_wglGetPbufferDCARB( &params ))) return status;
1383 params32->ret = (UINT_PTR)params.ret;
1384 return STATUS_SUCCESS;
1387 NTSTATUS wow64_wgl_wglGetProcAddress( void *args )
1389 struct
1391 PTR32 teb;
1392 PTR32 lpszProc;
1393 PTR32 ret;
1394 } *params32 = args;
1395 struct wglGetProcAddress_params params =
1397 .teb = get_teb64(params32->teb),
1398 .lpszProc = ULongToPtr(params32->lpszProc),
1400 NTSTATUS status;
1401 if ((status = wgl_wglGetProcAddress( &params ))) return status;
1402 params32->ret = (UINT_PTR)params.ret;
1403 return STATUS_SUCCESS;
1406 NTSTATUS wow64_gl_glGetString( void *args )
1408 struct
1410 PTR32 teb;
1411 GLenum name;
1412 PTR32 ret;
1413 } *params32 = args;
1414 struct glGetString_params params =
1416 .teb = get_teb64(params32->teb),
1417 .name = params32->name,
1419 NTSTATUS status;
1421 if ((status = gl_glGetString( &params ))) return status;
1423 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1425 params32->ret = strlen( (char *)params.ret ) + 1;
1426 return STATUS_BUFFER_TOO_SMALL;
1429 return STATUS_SUCCESS;
1432 NTSTATUS wow64_ext_glGetStringi( void *args )
1434 struct
1436 PTR32 teb;
1437 GLenum name;
1438 GLuint index;
1439 PTR32 ret;
1440 } *params32 = args;
1441 struct glGetStringi_params params =
1443 .teb = get_teb64(params32->teb),
1444 .name = params32->name,
1445 .index = params32->index,
1447 NTSTATUS status;
1449 if ((status = ext_glGetStringi( &params ))) return status;
1451 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1453 params32->ret = strlen( (char *)params.ret ) + 1;
1454 return STATUS_BUFFER_TOO_SMALL;
1457 return STATUS_SUCCESS;
1460 NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
1462 struct
1464 PTR32 teb;
1465 GLenum fontTarget;
1466 PTR32 fontName;
1467 GLbitfield fontStyle;
1468 GLuint pathParameterTemplate;
1469 GLfloat emScale;
1470 GLuint baseAndCount[2];
1471 GLenum ret;
1472 } *params32 = args;
1473 struct glPathGlyphIndexRangeNV_params params =
1475 .teb = get_teb64(params32->teb),
1476 .fontTarget = params32->fontTarget,
1477 .fontName = ULongToPtr(params32->fontName),
1478 .fontStyle = params32->fontStyle,
1479 .pathParameterTemplate = params32->pathParameterTemplate,
1480 .emScale = params32->emScale,
1481 .baseAndCount = {params32->baseAndCount[0], params32->baseAndCount[1]},
1483 NTSTATUS status;
1484 if ((status = ext_glPathGlyphIndexRangeNV( &params ))) return status;
1485 params32->ret = params.ret;
1486 return status;
1489 NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
1491 struct
1493 PTR32 teb;
1494 PTR32 hdc;
1495 PTR32 ret;
1496 } *params32 = args;
1497 struct wglGetExtensionsStringARB_params params =
1499 .teb = get_teb64(params32->teb),
1500 .hdc = ULongToPtr(params32->hdc),
1502 NTSTATUS status;
1504 if ((status = ext_wglGetExtensionsStringARB( &params ))) return status;
1506 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1508 params32->ret = strlen( params.ret ) + 1;
1509 return STATUS_BUFFER_TOO_SMALL;
1512 return STATUS_SUCCESS;
1515 NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
1517 struct
1519 PTR32 teb;
1520 PTR32 ret;
1521 } *params32 = args;
1522 struct wglGetExtensionsStringEXT_params params =
1524 .teb = get_teb64(params32->teb),
1526 NTSTATUS status;
1528 if ((status = ext_wglGetExtensionsStringEXT( &params ))) return status;
1530 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1532 params32->ret = strlen( params.ret ) + 1;
1533 return STATUS_BUFFER_TOO_SMALL;
1536 return STATUS_SUCCESS;
1539 NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
1541 struct
1543 PTR32 teb;
1544 GLenum attribute;
1545 PTR32 ret;
1546 } *params32 = args;
1547 struct wglQueryCurrentRendererStringWINE_params params =
1549 .teb = get_teb64(params32->teb),
1550 .attribute = params32->attribute,
1552 NTSTATUS status;
1554 if ((status = ext_wglQueryCurrentRendererStringWINE( &params ))) return status;
1556 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1558 params32->ret = strlen( params.ret ) + 1;
1559 return STATUS_BUFFER_TOO_SMALL;
1562 return STATUS_SUCCESS;
1565 NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
1567 struct
1569 PTR32 teb;
1570 PTR32 dc;
1571 GLint renderer;
1572 GLenum attribute;
1573 PTR32 ret;
1574 } *params32 = args;
1575 struct wglQueryRendererStringWINE_params params =
1577 .teb = get_teb64(params32->teb),
1578 .dc = ULongToPtr(params32->dc),
1579 .renderer = params32->renderer,
1580 .attribute = params32->attribute,
1582 NTSTATUS status;
1584 if ((status = ext_wglQueryRendererStringWINE( &params ))) return status;
1586 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1588 params32->ret = strlen( params.ret ) + 1;
1589 return STATUS_BUFFER_TOO_SMALL;
1592 return STATUS_SUCCESS;
1595 NTSTATUS wow64_ext_glClientWaitSync( void *args )
1597 struct wgl_handle *handle;
1598 struct
1600 PTR32 teb;
1601 PTR32 sync;
1602 GLbitfield flags;
1603 GLuint64 timeout;
1604 GLenum ret;
1605 } *params32 = args;
1606 NTSTATUS status;
1608 pthread_mutex_lock( &wgl_lock );
1610 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1611 status = STATUS_INVALID_HANDLE;
1612 else
1614 struct glClientWaitSync_params params =
1616 .teb = get_teb64(params32->teb),
1617 .sync = (GLsync)handle->u.context,
1618 .flags = params32->flags,
1619 .timeout = params32->timeout,
1621 status = ext_glClientWaitSync( &params );
1622 params32->ret = params.ret;
1625 pthread_mutex_unlock( &wgl_lock );
1626 return status;
1629 NTSTATUS wow64_ext_glDeleteSync( void *args )
1631 struct wgl_handle *handle;
1632 struct
1634 PTR32 teb;
1635 PTR32 sync;
1636 } *params32 = args;
1637 NTSTATUS status;
1639 pthread_mutex_lock( &wgl_lock );
1641 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1642 status = STATUS_INVALID_HANDLE;
1643 else
1645 struct glDeleteSync_params params =
1647 .teb = get_teb64(params32->teb),
1648 .sync = (GLsync)handle->u.context,
1650 status = ext_glDeleteSync( &params );
1651 free_handle_ptr( handle );
1654 pthread_mutex_unlock( &wgl_lock );
1655 return status;
1658 NTSTATUS wow64_ext_glFenceSync( void *args )
1660 struct
1662 PTR32 teb;
1663 GLenum condition;
1664 GLbitfield flags;
1665 PTR32 ret;
1666 } *params32 = args;
1667 struct glFenceSync_params params =
1669 .teb = get_teb64(params32->teb),
1670 .condition = params32->condition,
1671 .flags = params32->flags,
1673 NTSTATUS status;
1675 if ((status = ext_glFenceSync( &params ))) return status;
1677 pthread_mutex_lock( &wgl_lock );
1679 if (!(params32->ret = (UINT_PTR)alloc_handle( HANDLE_GLSYNC, NULL, params.ret )))
1681 struct glDeleteSync_params delete_params =
1683 .teb = params.teb,
1684 .sync = params.ret,
1687 ext_glDeleteSync( &delete_params );
1688 status = STATUS_NO_MEMORY;
1691 pthread_mutex_unlock( &wgl_lock );
1692 return status;
1695 NTSTATUS wow64_ext_glGetSynciv( void *args )
1697 struct wgl_handle *handle;
1698 struct
1700 PTR32 teb;
1701 PTR32 sync;
1702 GLenum pname;
1703 GLsizei count;
1704 PTR32 length;
1705 PTR32 values;
1706 } *params32 = args;
1707 NTSTATUS status;
1709 pthread_mutex_lock( &wgl_lock );
1711 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1712 status = STATUS_INVALID_HANDLE;
1713 else
1715 struct glGetSynciv_params params =
1717 .teb = get_teb64(params32->teb),
1718 .sync = (GLsync)handle->u.context,
1719 .pname = params32->pname,
1720 .count = params32->count,
1721 .length = ULongToPtr(params32->length),
1722 .values = ULongToPtr(params32->values),
1724 status = ext_glGetSynciv( &params );
1727 pthread_mutex_unlock( &wgl_lock );
1728 return status;
1731 NTSTATUS wow64_ext_glIsSync( void *args )
1733 struct wgl_handle *handle;
1734 struct
1736 PTR32 teb;
1737 PTR32 sync;
1738 GLboolean ret;
1739 } *params32 = args;
1740 NTSTATUS status;
1742 pthread_mutex_lock( &wgl_lock );
1744 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1745 status = STATUS_INVALID_HANDLE;
1746 else
1748 struct glIsSync_params params =
1750 .teb = get_teb64(params32->teb),
1751 .sync = (GLsync)handle->u.context,
1753 status = ext_glIsSync( &params );
1754 params32->ret = params.ret;
1757 pthread_mutex_unlock( &wgl_lock );
1758 return status;
1761 NTSTATUS wow64_ext_glWaitSync( void *args )
1763 struct wgl_handle *handle;
1764 struct
1766 PTR32 teb;
1767 PTR32 sync;
1768 GLbitfield flags;
1769 GLuint64 timeout;
1770 } *params32 = args;
1771 NTSTATUS status;
1773 pthread_mutex_lock( &wgl_lock );
1775 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1776 status = STATUS_INVALID_HANDLE;
1777 else
1779 struct glWaitSync_params params =
1781 .teb = get_teb64(params32->teb),
1782 .sync = (GLsync)handle->u.context,
1783 .flags = params32->flags,
1784 .timeout = params32->timeout,
1786 status = ext_glWaitSync( &params );
1789 pthread_mutex_unlock( &wgl_lock );
1790 return status;
1793 static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param )
1795 const struct opengl_funcs *funcs = teb->glTable;
1796 typeof(*funcs->ext.p_glGetBufferParameteriv) *func;
1797 GLint size = 0;
1798 if (!(func = funcs->ext.p_glGetBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferParameteriv" );
1799 if (func) func( target, param, &size );
1800 return size;
1803 static void *get_buffer_pointer( TEB *teb, GLenum target )
1805 const struct opengl_funcs *funcs = teb->glTable;
1806 typeof(*funcs->ext.p_glGetBufferPointerv) *func;
1807 void *ptr = NULL;
1808 if (!(func = funcs->ext.p_glGetBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferPointerv" );
1809 if (func) func( target, GL_BUFFER_MAP_POINTER, &ptr );
1810 return ptr;
1813 static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param )
1815 const struct opengl_funcs *funcs = teb->glTable;
1816 typeof(*funcs->ext.p_glGetNamedBufferParameteriv) *func;
1817 GLint size = 0;
1818 if (!(func = funcs->ext.p_glGetNamedBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferParameteriv" );
1819 if (func) func( buffer, param, &size );
1820 return size;
1823 static void *get_named_buffer_pointer( TEB *teb, GLint buffer )
1825 const struct opengl_funcs *funcs = teb->glTable;
1826 typeof(*funcs->ext.p_glGetNamedBufferPointerv) *func;
1827 void *ptr = NULL;
1828 if (!(func = funcs->ext.p_glGetNamedBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferPointerv" );
1829 if (func) func( buffer, GL_BUFFER_MAP_POINTER, &ptr );
1830 return ptr;
1833 static void unmap_buffer( TEB *teb, GLenum target )
1835 const struct opengl_funcs *funcs = teb->glTable;
1836 typeof(*funcs->ext.p_glUnmapBuffer) *func;
1837 if (!(func = funcs->ext.p_glUnmapBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapBuffer" );
1838 if (func) func( target );
1841 static void unmap_named_buffer( TEB *teb, GLint buffer )
1843 const struct opengl_funcs *funcs = teb->glTable;
1844 typeof(*funcs->ext.p_glUnmapNamedBuffer) *func;
1845 if (!(func = funcs->ext.p_glUnmapNamedBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapNamedBuffer" );
1846 if (func) func( buffer );
1849 static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *ptr, SIZE_T size,
1850 GLbitfield access, PTR32 *ret )
1852 if (*ret) /* wow64 pointer provided, map buffer to it */
1854 if (!(access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)))
1856 TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*ret) );
1857 memcpy( UlongToPtr(*ret), ptr, size );
1860 /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */
1861 *(PTR32 *)ptr = (UINT_PTR)*ret;
1862 return STATUS_SUCCESS;
1865 if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1866 if (access & GL_MAP_PERSISTENT_BIT)
1868 FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" );
1869 return STATUS_NOT_SUPPORTED;
1872 if (!size) size = buffer ? get_named_buffer_param( teb, buffer, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE );
1873 if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */
1874 if (size < sizeof(PTR32))
1876 FIXME( "Buffer too small for metadata!\n" );
1877 return STATUS_BUFFER_TOO_SMALL;
1880 *ret = size;
1881 return STATUS_INVALID_ADDRESS;
1884 static GLbitfield map_range_flags_from_map_flags( GLenum flags )
1886 switch (flags)
1888 case GL_READ_ONLY: return GL_MAP_READ_BIT;
1889 case GL_WRITE_ONLY: return GL_MAP_WRITE_BIT;
1890 case GL_READ_WRITE: return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1891 default:
1892 ERR( "invalid map flags %#x\n", flags );
1893 return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1897 static NTSTATUS wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access )
1899 void *wow_ptr;
1901 if (ULongToPtr(PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1903 wow_ptr = UlongToPtr(*(PTR32 *)ptr);
1904 if (access & GL_MAP_WRITE_BIT)
1906 TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr );
1907 memcpy( ptr, wow_ptr, size );
1910 return STATUS_INVALID_ADDRESS;
1913 static NTSTATUS wow64_gl_get_buffer_pointer_v( void *args, NTSTATUS (*get_buffer_pointer_v64)(void *) )
1915 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1916 struct
1918 PTR32 teb;
1919 GLenum target;
1920 GLenum pname;
1921 PTR32 params;
1922 } *params32 = args;
1923 struct glGetBufferPointerv_params params =
1925 .teb = get_teb64(params32->teb),
1926 .target = params32->target,
1927 .pname = params32->pname,
1928 .params = (void **)&ptr,
1930 PTR32 *wow_ptr = UlongToPtr(params32->params);
1931 NTSTATUS status;
1933 if ((status = get_buffer_pointer_v64( &params ))) return status;
1934 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1935 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1936 *wow_ptr = ptr[0];
1937 return STATUS_SUCCESS;
1940 NTSTATUS wow64_ext_glGetBufferPointerv( void *args )
1942 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointerv );
1945 NTSTATUS wow64_ext_glGetBufferPointervARB( void *args )
1947 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointervARB );
1950 static NTSTATUS wow64_gl_get_named_buffer_pointer_v( void *args, NTSTATUS (*gl_get_named_buffer_pointer_v64)(void *) )
1952 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1953 struct
1955 PTR32 teb;
1956 GLuint buffer;
1957 GLenum pname;
1958 PTR32 params;
1959 } *params32 = args;
1960 struct glGetNamedBufferPointerv_params params =
1962 .teb = get_teb64(params32->teb),
1963 .buffer = params32->buffer,
1964 .pname = params32->pname,
1965 .params = (void **)&ptr,
1967 PTR32 *wow_ptr = UlongToPtr(params32->params);
1968 NTSTATUS status;
1970 if ((status = gl_get_named_buffer_pointer_v64( &params ))) return status;
1971 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1972 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1973 *wow_ptr = ptr[0];
1974 return STATUS_SUCCESS;
1977 NTSTATUS wow64_ext_glGetNamedBufferPointerv( void *args )
1979 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointerv );
1982 NTSTATUS wow64_ext_glGetNamedBufferPointervEXT( void *args )
1984 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointervEXT );
1987 static NTSTATUS wow64_gl_map_buffer( void *args, NTSTATUS (*gl_map_buffer64)(void *) )
1989 struct
1991 PTR32 teb;
1992 GLenum target;
1993 GLenum access;
1994 PTR32 ret;
1995 } *params32 = args;
1996 struct glMapBuffer_params params =
1998 .teb = get_teb64(params32->teb),
1999 .target = params32->target,
2000 .access = params32->access,
2002 NTSTATUS status;
2004 /* already mapped, we're being called again with a wow64 pointer */
2005 if (params32->ret) params.ret = get_buffer_pointer( params.teb, params.target );
2006 else if ((status = gl_map_buffer64( &params ))) return status;
2008 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, 0,
2009 map_range_flags_from_map_flags( params.access ), &params32->ret );
2010 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2012 unmap_buffer( params.teb, params.target );
2013 return status;
2016 NTSTATUS wow64_ext_glMapBuffer( void *args )
2018 return wow64_gl_map_buffer( args, ext_glMapBuffer );
2021 NTSTATUS wow64_ext_glMapBufferARB( void *args )
2023 return wow64_gl_map_buffer( args, ext_glMapBufferARB );
2026 NTSTATUS wow64_ext_glMapBufferRange( void *args )
2028 struct
2030 PTR32 teb;
2031 GLenum target;
2032 PTR32 offset;
2033 PTR32 length;
2034 GLbitfield access;
2035 PTR32 ret;
2036 } *params32 = args;
2037 struct glMapBufferRange_params params =
2039 .teb = get_teb64(params32->teb),
2040 .target = params32->target,
2041 .offset = (GLintptr)ULongToPtr(params32->offset),
2042 .length = (GLsizeiptr)ULongToPtr(params32->length),
2043 .access = params32->access,
2045 NTSTATUS status;
2047 /* already mapped, we're being called again with a wow64 pointer */
2048 if (params32->ret) params.ret = (char *)get_buffer_pointer( params.teb, params.target );
2049 else if ((status = ext_glMapBufferRange( &params ))) return status;
2051 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, params.length, params.access, &params32->ret );
2052 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2054 unmap_buffer( params.teb, params.target );
2055 return status;
2058 static NTSTATUS wow64_gl_map_named_buffer( void *args, NTSTATUS (*gl_map_named_buffer64)(void *) )
2060 struct
2062 PTR32 teb;
2063 GLuint buffer;
2064 GLenum access;
2065 PTR32 ret;
2066 } *params32 = args;
2067 struct glMapNamedBuffer_params params =
2069 .teb = get_teb64(params32->teb),
2070 .buffer = params32->buffer,
2071 .access = params32->access,
2073 NTSTATUS status;
2075 /* already mapped, we're being called again with a wow64 pointer */
2076 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2077 else if ((status = gl_map_named_buffer64( &params ))) return status;
2079 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, 0,
2080 map_range_flags_from_map_flags( params.access ), &params32->ret );
2081 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2083 unmap_named_buffer( params.teb, params.buffer );
2084 return status;
2087 NTSTATUS wow64_ext_glMapNamedBuffer( void *args )
2089 return wow64_gl_map_named_buffer( args, ext_glMapNamedBuffer );
2092 NTSTATUS wow64_ext_glMapNamedBufferEXT( void *args )
2094 return wow64_gl_map_named_buffer( args, ext_glMapNamedBufferEXT );
2097 static NTSTATUS wow64_gl_map_named_buffer_range( void *args, NTSTATUS (*gl_map_named_buffer_range64)(void *) )
2099 struct
2101 PTR32 teb;
2102 GLuint buffer;
2103 PTR32 offset;
2104 PTR32 length;
2105 GLbitfield access;
2106 PTR32 ret;
2107 } *params32 = args;
2108 struct glMapNamedBufferRange_params params =
2110 .teb = get_teb64(params32->teb),
2111 .buffer = params32->buffer,
2112 .offset = (GLintptr)ULongToPtr(params32->offset),
2113 .length = (GLsizeiptr)ULongToPtr(params32->length),
2114 .access = params32->access,
2116 NTSTATUS status;
2118 /* already mapped, we're being called again with a wow64 pointer */
2119 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2120 else if ((status = gl_map_named_buffer_range64( &params ))) return status;
2122 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, params.length, params.access, &params32->ret );
2123 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2125 unmap_named_buffer( params.teb, params.buffer );
2126 return status;
2129 NTSTATUS wow64_ext_glMapNamedBufferRange( void *args )
2131 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRange );
2134 NTSTATUS wow64_ext_glMapNamedBufferRangeEXT( void *args )
2136 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRangeEXT );
2139 static NTSTATUS wow64_gl_unmap_buffer( void *args, NTSTATUS (*gl_unmap_buffer64)(void *) )
2141 PTR32 *ptr;
2142 struct
2144 PTR32 teb;
2145 GLenum target;
2146 GLboolean ret;
2147 } *params32 = args;
2148 struct glUnmapBuffer_params params =
2150 .teb = get_teb64(params32->teb),
2151 .target = params32->target,
2152 .ret = TRUE,
2154 NTSTATUS status;
2156 if (!(ptr = get_buffer_pointer( params.teb, params.target ))) return STATUS_SUCCESS;
2158 status = wow64_unmap_buffer( ptr, get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ),
2159 get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ) );
2160 gl_unmap_buffer64( &params );
2161 params32->ret = params.ret;
2163 return status;
2166 NTSTATUS wow64_ext_glUnmapBuffer( void *args )
2168 return wow64_gl_unmap_buffer( args, ext_glUnmapBuffer );
2171 NTSTATUS wow64_ext_glUnmapBufferARB( void *args )
2173 return wow64_gl_unmap_buffer( args, ext_glUnmapBufferARB );
2176 static NTSTATUS wow64_gl_unmap_named_buffer( void *args, NTSTATUS (*gl_unmap_named_buffer64)(void *) )
2178 PTR32 *ptr;
2179 struct
2181 PTR32 teb;
2182 GLint buffer;
2183 GLboolean ret;
2184 } *params32 = args;
2185 struct glUnmapNamedBuffer_params params =
2187 .teb = get_teb64(params32->teb),
2188 .buffer = params32->buffer,
2189 .ret = TRUE,
2191 NTSTATUS status;
2193 if (!(ptr = get_named_buffer_pointer( params.teb, params.buffer ))) return STATUS_SUCCESS;
2195 status = wow64_unmap_buffer( ptr, get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ),
2196 get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ) );
2197 gl_unmap_named_buffer64( &params );
2198 params32->ret = params.ret;
2200 return status;
2203 NTSTATUS wow64_ext_glUnmapNamedBuffer( void *args )
2205 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBuffer );
2208 NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args )
2210 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT );
2213 NTSTATUS wow64_thread_attach( void *args )
2215 return thread_attach( get_teb64( (ULONG_PTR)args ));
2218 NTSTATUS wow64_process_detach( void *args )
2220 NTSTATUS status;
2222 if ((status = process_detach( NULL ))) return status;
2224 free( wow64_strings );
2225 wow64_strings = NULL;
2226 wow64_strings_count = 0;
2228 return STATUS_SUCCESS;
2231 #endif