comctl32/tests: Use CRT allocation functions.
[wine.git] / dlls / opengl32 / unix_wgl.c
blobe03bbc0a9c01b5b8d24cc76abff7ea365259cbce
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 = sprintf( 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 += sprintf( 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 = malloc( 3 + strlen( rest ) + 1 );
496 sprintf( 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 += sprintf( available_extensions + 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 #ifdef _WIN64
1162 typedef ULONG PTR32;
1164 extern NTSTATUS ext_glClientWaitSync( void *args );
1165 extern NTSTATUS ext_glDeleteSync( void *args );
1166 extern NTSTATUS ext_glFenceSync( void *args );
1167 extern NTSTATUS ext_glGetBufferPointerv( void *args );
1168 extern NTSTATUS ext_glGetBufferPointervARB( void *args );
1169 extern NTSTATUS ext_glGetNamedBufferPointerv( void *args );
1170 extern NTSTATUS ext_glGetNamedBufferPointervEXT( void *args );
1171 extern NTSTATUS ext_glGetSynciv( void *args );
1172 extern NTSTATUS ext_glIsSync( void *args );
1173 extern NTSTATUS ext_glMapBuffer( void *args );
1175 extern NTSTATUS ext_glUnmapBuffer( void *args );
1176 extern NTSTATUS ext_glUnmapBufferARB( void *args );
1177 extern NTSTATUS ext_glUnmapNamedBuffer( void *args );
1178 extern NTSTATUS ext_glUnmapNamedBufferEXT( void *args );
1180 extern NTSTATUS ext_glMapBufferARB( void *args );
1181 extern NTSTATUS ext_glMapBufferRange( void *args );
1182 extern NTSTATUS ext_glMapNamedBuffer( void *args );
1183 extern NTSTATUS ext_glMapNamedBufferEXT( void *args );
1184 extern NTSTATUS ext_glMapNamedBufferRange( void *args );
1185 extern NTSTATUS ext_glMapNamedBufferRangeEXT( void *args );
1186 extern NTSTATUS ext_glPathGlyphIndexRangeNV( void *args );
1187 extern NTSTATUS ext_glWaitSync( void *args );
1188 extern NTSTATUS ext_wglGetExtensionsStringARB( void *args );
1189 extern NTSTATUS ext_wglGetExtensionsStringEXT( void *args );
1190 extern NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args );
1191 extern NTSTATUS ext_wglQueryRendererStringWINE( void *args );
1193 struct wow64_string_entry
1195 const char *str;
1196 PTR32 wow64_str;
1198 static struct wow64_string_entry *wow64_strings;
1199 static SIZE_T wow64_strings_count;
1201 static PTR32 find_wow64_string( const char *str, PTR32 wow64_str )
1203 void *tmp;
1204 SIZE_T i;
1206 pthread_mutex_lock( &wgl_lock );
1208 for (i = 0; i < wow64_strings_count; i++) if (wow64_strings[i].str == str) break;
1209 if (i == wow64_strings_count && (tmp = realloc( wow64_strings, (i + 1) * sizeof(*wow64_strings) )))
1211 wow64_strings = tmp;
1212 wow64_strings[i].str = str;
1213 wow64_strings[i].wow64_str = 0;
1214 wow64_strings_count += 1;
1217 if (i == wow64_strings_count) ERR( "Failed to allocate memory for wow64 strings\n" );
1218 else if (wow64_strings[i].wow64_str) wow64_str = wow64_strings[i].wow64_str;
1219 else if (wow64_str)
1221 strcpy( UlongToPtr(wow64_str), (char *)str );
1222 wow64_strings[i].wow64_str = wow64_str;
1225 pthread_mutex_unlock( &wgl_lock );
1227 return wow64_str;
1230 static inline void update_teb32_context( TEB *teb )
1232 void *teb32;
1234 if (!teb->WowTebOffset) return;
1235 teb32 = (char *)teb + teb->WowTebOffset;
1237 ((TEB32 *)teb32)->glCurrentRC = (UINT_PTR)teb->glCurrentRC;
1238 ((TEB32 *)teb32)->glReserved1[0] = (UINT_PTR)teb->glReserved1[0];
1239 ((TEB32 *)teb32)->glReserved1[1] = (UINT_PTR)teb->glReserved1[1];
1242 NTSTATUS wow64_wgl_wglCreateContext( void *args )
1244 struct
1246 PTR32 teb;
1247 PTR32 hDc;
1248 PTR32 ret;
1249 } *params32 = args;
1250 struct wglCreateContext_params params =
1252 .teb = get_teb64(params32->teb),
1253 .hDc = ULongToPtr(params32->hDc),
1255 NTSTATUS status;
1256 if ((status = wgl_wglCreateContext( &params ))) return status;
1257 params32->ret = (UINT_PTR)params.ret;
1258 return STATUS_SUCCESS;
1261 NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args )
1263 struct
1265 PTR32 teb;
1266 PTR32 hDC;
1267 PTR32 hShareContext;
1268 PTR32 attribList;
1269 PTR32 ret;
1270 } *params32 = args;
1271 struct wglCreateContextAttribsARB_params params =
1273 .teb = get_teb64(params32->teb),
1274 .hDC = ULongToPtr(params32->hDC),
1275 .hShareContext = ULongToPtr(params32->hShareContext),
1276 .attribList = ULongToPtr(params32->attribList),
1278 NTSTATUS status;
1279 if ((status = ext_wglCreateContextAttribsARB( &params ))) return status;
1280 params32->ret = (UINT_PTR)params.ret;
1281 return STATUS_SUCCESS;
1284 NTSTATUS wow64_ext_wglCreatePbufferARB( void *args )
1286 struct
1288 PTR32 teb;
1289 PTR32 hDC;
1290 GLint iPixelFormat;
1291 GLint iWidth;
1292 GLint iHeight;
1293 PTR32 piAttribList;
1294 PTR32 ret;
1295 } *params32 = args;
1296 struct wglCreatePbufferARB_params params =
1298 .teb = get_teb64(params32->teb),
1299 .hDC = ULongToPtr(params32->hDC),
1300 .iPixelFormat = params32->iPixelFormat,
1301 .iWidth = params32->iWidth,
1302 .iHeight = params32->iHeight,
1303 .piAttribList = ULongToPtr(params32->piAttribList),
1305 NTSTATUS status;
1306 if ((status = ext_wglCreatePbufferARB( &params ))) return status;
1307 params32->ret = (UINT_PTR)params.ret;
1308 return STATUS_SUCCESS;
1311 NTSTATUS wow64_wgl_wglDeleteContext( void *args )
1313 struct
1315 PTR32 teb;
1316 PTR32 oldContext;
1317 BOOL ret;
1318 } *params32 = args;
1319 struct wglDeleteContext_params params =
1321 .teb = get_teb64(params32->teb),
1322 .oldContext = ULongToPtr(params32->oldContext),
1324 NTSTATUS status;
1325 if (!(status = wgl_wglDeleteContext( &params ))) update_teb32_context( params.teb );
1326 params32->ret = params.ret;
1327 return status;
1330 NTSTATUS wow64_wgl_wglMakeCurrent( void *args )
1332 struct
1334 PTR32 teb;
1335 PTR32 hDc;
1336 PTR32 newContext;
1337 BOOL ret;
1338 } *params32 = args;
1339 struct wglMakeCurrent_params params =
1341 .teb = get_teb64(params32->teb),
1342 .hDc = ULongToPtr(params32->hDc),
1343 .newContext = ULongToPtr(params32->newContext),
1345 NTSTATUS status;
1346 if (!(status = wgl_wglMakeCurrent( &params ))) update_teb32_context( params.teb );
1347 params32->ret = params.ret;
1348 return status;
1351 NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args )
1353 struct
1355 PTR32 teb;
1356 PTR32 hDrawDC;
1357 PTR32 hReadDC;
1358 PTR32 hglrc;
1359 BOOL ret;
1360 } *params32 = args;
1361 struct wglMakeContextCurrentARB_params params =
1363 .teb = get_teb64(params32->teb),
1364 .hDrawDC = ULongToPtr(params32->hDrawDC),
1365 .hReadDC = ULongToPtr(params32->hReadDC),
1366 .hglrc = ULongToPtr(params32->hglrc),
1368 NTSTATUS status;
1369 if (!(status = ext_wglMakeContextCurrentARB( &params ))) update_teb32_context( params.teb );
1370 params32->ret = params.ret;
1371 return status;
1374 NTSTATUS wow64_ext_wglGetPbufferDCARB( void *args )
1376 struct
1378 PTR32 teb;
1379 PTR32 hPbuffer;
1380 PTR32 ret;
1381 } *params32 = args;
1382 struct wglGetPbufferDCARB_params params =
1384 .teb = get_teb64(params32->teb),
1385 .hPbuffer = (HPBUFFERARB)ULongToPtr(params32->hPbuffer),
1387 NTSTATUS status;
1388 if ((status = ext_wglGetPbufferDCARB( &params ))) return status;
1389 params32->ret = (UINT_PTR)params.ret;
1390 return STATUS_SUCCESS;
1393 NTSTATUS wow64_wgl_wglGetProcAddress( void *args )
1395 struct
1397 PTR32 teb;
1398 PTR32 lpszProc;
1399 PTR32 ret;
1400 } *params32 = args;
1401 struct wglGetProcAddress_params params =
1403 .teb = get_teb64(params32->teb),
1404 .lpszProc = ULongToPtr(params32->lpszProc),
1406 NTSTATUS status;
1407 if ((status = wgl_wglGetProcAddress( &params ))) return status;
1408 params32->ret = (UINT_PTR)params.ret;
1409 return STATUS_SUCCESS;
1412 NTSTATUS wow64_gl_glGetString( void *args )
1414 struct
1416 PTR32 teb;
1417 GLenum name;
1418 PTR32 ret;
1419 } *params32 = args;
1420 struct glGetString_params params =
1422 .teb = get_teb64(params32->teb),
1423 .name = params32->name,
1425 NTSTATUS status;
1427 if ((status = gl_glGetString( &params ))) return status;
1429 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1431 params32->ret = strlen( (char *)params.ret ) + 1;
1432 return STATUS_BUFFER_TOO_SMALL;
1435 return STATUS_SUCCESS;
1438 NTSTATUS wow64_ext_glGetStringi( void *args )
1440 struct
1442 PTR32 teb;
1443 GLenum name;
1444 GLuint index;
1445 PTR32 ret;
1446 } *params32 = args;
1447 struct glGetStringi_params params =
1449 .teb = get_teb64(params32->teb),
1450 .name = params32->name,
1451 .index = params32->index,
1453 NTSTATUS status;
1455 if ((status = ext_glGetStringi( &params ))) return status;
1457 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1459 params32->ret = strlen( (char *)params.ret ) + 1;
1460 return STATUS_BUFFER_TOO_SMALL;
1463 return STATUS_SUCCESS;
1466 NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
1468 struct
1470 PTR32 teb;
1471 GLenum fontTarget;
1472 PTR32 fontName;
1473 GLbitfield fontStyle;
1474 GLuint pathParameterTemplate;
1475 GLfloat emScale;
1476 GLuint baseAndCount[2];
1477 GLenum ret;
1478 } *params32 = args;
1479 struct glPathGlyphIndexRangeNV_params params =
1481 .teb = get_teb64(params32->teb),
1482 .fontTarget = params32->fontTarget,
1483 .fontName = ULongToPtr(params32->fontName),
1484 .fontStyle = params32->fontStyle,
1485 .pathParameterTemplate = params32->pathParameterTemplate,
1486 .emScale = params32->emScale,
1487 .baseAndCount = {params32->baseAndCount[0], params32->baseAndCount[1]},
1489 NTSTATUS status;
1490 if ((status = ext_glPathGlyphIndexRangeNV( &params ))) return status;
1491 params32->ret = params.ret;
1492 return status;
1495 NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
1497 struct
1499 PTR32 teb;
1500 PTR32 hdc;
1501 PTR32 ret;
1502 } *params32 = args;
1503 struct wglGetExtensionsStringARB_params params =
1505 .teb = get_teb64(params32->teb),
1506 .hdc = ULongToPtr(params32->hdc),
1508 NTSTATUS status;
1510 if ((status = ext_wglGetExtensionsStringARB( &params ))) return status;
1512 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1514 params32->ret = strlen( params.ret ) + 1;
1515 return STATUS_BUFFER_TOO_SMALL;
1518 return STATUS_SUCCESS;
1521 NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
1523 struct
1525 PTR32 teb;
1526 PTR32 ret;
1527 } *params32 = args;
1528 struct wglGetExtensionsStringEXT_params params =
1530 .teb = get_teb64(params32->teb),
1532 NTSTATUS status;
1534 if ((status = ext_wglGetExtensionsStringEXT( &params ))) return status;
1536 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1538 params32->ret = strlen( params.ret ) + 1;
1539 return STATUS_BUFFER_TOO_SMALL;
1542 return STATUS_SUCCESS;
1545 NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
1547 struct
1549 PTR32 teb;
1550 GLenum attribute;
1551 PTR32 ret;
1552 } *params32 = args;
1553 struct wglQueryCurrentRendererStringWINE_params params =
1555 .teb = get_teb64(params32->teb),
1556 .attribute = params32->attribute,
1558 NTSTATUS status;
1560 if ((status = ext_wglQueryCurrentRendererStringWINE( &params ))) return status;
1562 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1564 params32->ret = strlen( params.ret ) + 1;
1565 return STATUS_BUFFER_TOO_SMALL;
1568 return STATUS_SUCCESS;
1571 NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
1573 struct
1575 PTR32 teb;
1576 PTR32 dc;
1577 GLint renderer;
1578 GLenum attribute;
1579 PTR32 ret;
1580 } *params32 = args;
1581 struct wglQueryRendererStringWINE_params params =
1583 .teb = get_teb64(params32->teb),
1584 .dc = ULongToPtr(params32->dc),
1585 .renderer = params32->renderer,
1586 .attribute = params32->attribute,
1588 NTSTATUS status;
1590 if ((status = ext_wglQueryRendererStringWINE( &params ))) return status;
1592 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1594 params32->ret = strlen( params.ret ) + 1;
1595 return STATUS_BUFFER_TOO_SMALL;
1598 return STATUS_SUCCESS;
1601 NTSTATUS wow64_ext_glClientWaitSync( void *args )
1603 struct wgl_handle *handle;
1604 struct
1606 PTR32 teb;
1607 PTR32 sync;
1608 GLbitfield flags;
1609 GLuint64 timeout;
1610 GLenum ret;
1611 } *params32 = args;
1612 NTSTATUS status;
1614 pthread_mutex_lock( &wgl_lock );
1616 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1617 status = STATUS_INVALID_HANDLE;
1618 else
1620 struct glClientWaitSync_params params =
1622 .teb = get_teb64(params32->teb),
1623 .sync = (GLsync)handle->u.context,
1624 .flags = params32->flags,
1625 .timeout = params32->timeout,
1627 status = ext_glClientWaitSync( &params );
1628 params32->ret = params.ret;
1631 pthread_mutex_unlock( &wgl_lock );
1632 return status;
1635 NTSTATUS wow64_ext_glDeleteSync( void *args )
1637 struct wgl_handle *handle;
1638 struct
1640 PTR32 teb;
1641 PTR32 sync;
1642 } *params32 = args;
1643 NTSTATUS status;
1645 pthread_mutex_lock( &wgl_lock );
1647 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1648 status = STATUS_INVALID_HANDLE;
1649 else
1651 struct glDeleteSync_params params =
1653 .teb = get_teb64(params32->teb),
1654 .sync = (GLsync)handle->u.context,
1656 status = ext_glDeleteSync( &params );
1657 free_handle_ptr( handle );
1660 pthread_mutex_unlock( &wgl_lock );
1661 return status;
1664 NTSTATUS wow64_ext_glFenceSync( void *args )
1666 struct
1668 PTR32 teb;
1669 GLenum condition;
1670 GLbitfield flags;
1671 PTR32 ret;
1672 } *params32 = args;
1673 struct glFenceSync_params params =
1675 .teb = get_teb64(params32->teb),
1676 .condition = params32->condition,
1677 .flags = params32->flags,
1679 NTSTATUS status;
1681 if ((status = ext_glFenceSync( &params ))) return status;
1683 pthread_mutex_lock( &wgl_lock );
1685 if (!(params32->ret = (UINT_PTR)alloc_handle( HANDLE_GLSYNC, NULL, params.ret )))
1687 struct glDeleteSync_params delete_params =
1689 .teb = params.teb,
1690 .sync = params.ret,
1693 ext_glDeleteSync( &delete_params );
1694 status = STATUS_NO_MEMORY;
1697 pthread_mutex_unlock( &wgl_lock );
1698 return status;
1701 NTSTATUS wow64_ext_glGetSynciv( void *args )
1703 struct wgl_handle *handle;
1704 struct
1706 PTR32 teb;
1707 PTR32 sync;
1708 GLenum pname;
1709 GLsizei count;
1710 PTR32 length;
1711 PTR32 values;
1712 } *params32 = args;
1713 NTSTATUS status;
1715 pthread_mutex_lock( &wgl_lock );
1717 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1718 status = STATUS_INVALID_HANDLE;
1719 else
1721 struct glGetSynciv_params params =
1723 .teb = get_teb64(params32->teb),
1724 .sync = (GLsync)handle->u.context,
1725 .pname = params32->pname,
1726 .count = params32->count,
1727 .length = ULongToPtr(params32->length),
1728 .values = ULongToPtr(params32->values),
1730 status = ext_glGetSynciv( &params );
1733 pthread_mutex_unlock( &wgl_lock );
1734 return status;
1737 NTSTATUS wow64_ext_glIsSync( void *args )
1739 struct wgl_handle *handle;
1740 struct
1742 PTR32 teb;
1743 PTR32 sync;
1744 GLboolean ret;
1745 } *params32 = args;
1746 NTSTATUS status;
1748 pthread_mutex_lock( &wgl_lock );
1750 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1751 status = STATUS_INVALID_HANDLE;
1752 else
1754 struct glIsSync_params params =
1756 .teb = get_teb64(params32->teb),
1757 .sync = (GLsync)handle->u.context,
1759 status = ext_glIsSync( &params );
1760 params32->ret = params.ret;
1763 pthread_mutex_unlock( &wgl_lock );
1764 return status;
1767 NTSTATUS wow64_ext_glWaitSync( void *args )
1769 struct wgl_handle *handle;
1770 struct
1772 PTR32 teb;
1773 PTR32 sync;
1774 GLbitfield flags;
1775 GLuint64 timeout;
1776 } *params32 = args;
1777 NTSTATUS status;
1779 pthread_mutex_lock( &wgl_lock );
1781 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1782 status = STATUS_INVALID_HANDLE;
1783 else
1785 struct glWaitSync_params params =
1787 .teb = get_teb64(params32->teb),
1788 .sync = (GLsync)handle->u.context,
1789 .flags = params32->flags,
1790 .timeout = params32->timeout,
1792 status = ext_glWaitSync( &params );
1795 pthread_mutex_unlock( &wgl_lock );
1796 return status;
1799 static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param )
1801 const struct opengl_funcs *funcs = teb->glTable;
1802 typeof(*funcs->ext.p_glGetBufferParameteriv) *func;
1803 GLint size = 0;
1804 if (!(func = funcs->ext.p_glGetBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferParameteriv" );
1805 if (func) func( target, param, &size );
1806 return size;
1809 static void *get_buffer_pointer( TEB *teb, GLenum target )
1811 const struct opengl_funcs *funcs = teb->glTable;
1812 typeof(*funcs->ext.p_glGetBufferPointerv) *func;
1813 void *ptr = NULL;
1814 if (!(func = funcs->ext.p_glGetBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferPointerv" );
1815 if (func) func( target, GL_BUFFER_MAP_POINTER, &ptr );
1816 return ptr;
1819 static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param )
1821 const struct opengl_funcs *funcs = teb->glTable;
1822 typeof(*funcs->ext.p_glGetNamedBufferParameteriv) *func;
1823 GLint size = 0;
1824 if (!(func = funcs->ext.p_glGetNamedBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferParameteriv" );
1825 if (func) func( buffer, param, &size );
1826 return size;
1829 static void *get_named_buffer_pointer( TEB *teb, GLint buffer )
1831 const struct opengl_funcs *funcs = teb->glTable;
1832 typeof(*funcs->ext.p_glGetNamedBufferPointerv) *func;
1833 void *ptr = NULL;
1834 if (!(func = funcs->ext.p_glGetNamedBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferPointerv" );
1835 if (func) func( buffer, GL_BUFFER_MAP_POINTER, &ptr );
1836 return ptr;
1839 static void unmap_buffer( TEB *teb, GLenum target )
1841 const struct opengl_funcs *funcs = teb->glTable;
1842 typeof(*funcs->ext.p_glUnmapBuffer) *func;
1843 if (!(func = funcs->ext.p_glUnmapBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapBuffer" );
1844 if (func) func( target );
1847 static void unmap_named_buffer( TEB *teb, GLint buffer )
1849 const struct opengl_funcs *funcs = teb->glTable;
1850 typeof(*funcs->ext.p_glUnmapNamedBuffer) *func;
1851 if (!(func = funcs->ext.p_glUnmapNamedBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapNamedBuffer" );
1852 if (func) func( buffer );
1855 static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *ptr, SIZE_T size,
1856 GLbitfield access, PTR32 *ret )
1858 if (*ret) /* wow64 pointer provided, map buffer to it */
1860 if (!(access & (GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)))
1862 TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*ret) );
1863 memcpy( UlongToPtr(*ret), ptr, size );
1866 /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */
1867 *(PTR32 *)ptr = (UINT_PTR)*ret;
1868 return STATUS_SUCCESS;
1871 if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1872 if (access & GL_MAP_PERSISTENT_BIT)
1874 FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" );
1875 return STATUS_NOT_SUPPORTED;
1878 if (!size) size = buffer ? get_named_buffer_param( teb, buffer, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE );
1879 if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */
1880 if (size < sizeof(PTR32))
1882 FIXME( "Buffer too small for metadata!\n" );
1883 return STATUS_BUFFER_TOO_SMALL;
1886 *ret = size;
1887 return STATUS_INVALID_ADDRESS;
1890 static GLbitfield map_range_flags_from_map_flags( GLenum flags )
1892 switch (flags)
1894 case GL_READ_ONLY: return GL_MAP_READ_BIT;
1895 case GL_WRITE_ONLY: return GL_MAP_WRITE_BIT;
1896 case GL_READ_WRITE: return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1897 default:
1898 ERR( "invalid map flags %#x\n", flags );
1899 return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1903 static NTSTATUS wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access )
1905 void *wow_ptr;
1907 if (ULongToPtr(PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1909 wow_ptr = UlongToPtr(*(PTR32 *)ptr);
1910 if (access & GL_MAP_WRITE_BIT)
1912 TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr );
1913 memcpy( ptr, wow_ptr, size );
1916 return STATUS_INVALID_ADDRESS;
1919 static NTSTATUS wow64_gl_get_buffer_pointer_v( void *args, NTSTATUS (*get_buffer_pointer_v64)(void *) )
1921 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1922 struct
1924 PTR32 teb;
1925 GLenum target;
1926 GLenum pname;
1927 PTR32 params;
1928 } *params32 = args;
1929 struct glGetBufferPointerv_params params =
1931 .teb = get_teb64(params32->teb),
1932 .target = params32->target,
1933 .pname = params32->pname,
1934 .params = (void **)&ptr,
1936 PTR32 *wow_ptr = UlongToPtr(params32->params);
1937 NTSTATUS status;
1939 if ((status = get_buffer_pointer_v64( &params ))) return status;
1940 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1941 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1942 *wow_ptr = ptr[0];
1943 return STATUS_SUCCESS;
1946 NTSTATUS wow64_ext_glGetBufferPointerv( void *args )
1948 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointerv );
1951 NTSTATUS wow64_ext_glGetBufferPointervARB( void *args )
1953 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointervARB );
1956 static NTSTATUS wow64_gl_get_named_buffer_pointer_v( void *args, NTSTATUS (*gl_get_named_buffer_pointer_v64)(void *) )
1958 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1959 struct
1961 PTR32 teb;
1962 GLuint buffer;
1963 GLenum pname;
1964 PTR32 params;
1965 } *params32 = args;
1966 struct glGetNamedBufferPointerv_params params =
1968 .teb = get_teb64(params32->teb),
1969 .buffer = params32->buffer,
1970 .pname = params32->pname,
1971 .params = (void **)&ptr,
1973 PTR32 *wow_ptr = UlongToPtr(params32->params);
1974 NTSTATUS status;
1976 if ((status = gl_get_named_buffer_pointer_v64( &params ))) return status;
1977 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1978 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1979 *wow_ptr = ptr[0];
1980 return STATUS_SUCCESS;
1983 NTSTATUS wow64_ext_glGetNamedBufferPointerv( void *args )
1985 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointerv );
1988 NTSTATUS wow64_ext_glGetNamedBufferPointervEXT( void *args )
1990 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointervEXT );
1993 static NTSTATUS wow64_gl_map_buffer( void *args, NTSTATUS (*gl_map_buffer64)(void *) )
1995 struct
1997 PTR32 teb;
1998 GLenum target;
1999 GLenum access;
2000 PTR32 ret;
2001 } *params32 = args;
2002 struct glMapBuffer_params params =
2004 .teb = get_teb64(params32->teb),
2005 .target = params32->target,
2006 .access = params32->access,
2008 NTSTATUS status;
2010 /* already mapped, we're being called again with a wow64 pointer */
2011 if (params32->ret) params.ret = get_buffer_pointer( params.teb, params.target );
2012 else if ((status = gl_map_buffer64( &params ))) return status;
2014 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, 0,
2015 map_range_flags_from_map_flags( params.access ), &params32->ret );
2016 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2018 unmap_buffer( params.teb, params.target );
2019 return status;
2022 NTSTATUS wow64_ext_glMapBuffer( void *args )
2024 return wow64_gl_map_buffer( args, ext_glMapBuffer );
2027 NTSTATUS wow64_ext_glMapBufferARB( void *args )
2029 return wow64_gl_map_buffer( args, ext_glMapBufferARB );
2032 NTSTATUS wow64_ext_glMapBufferRange( void *args )
2034 struct
2036 PTR32 teb;
2037 GLenum target;
2038 PTR32 offset;
2039 PTR32 length;
2040 GLbitfield access;
2041 PTR32 ret;
2042 } *params32 = args;
2043 struct glMapBufferRange_params params =
2045 .teb = get_teb64(params32->teb),
2046 .target = params32->target,
2047 .offset = (GLintptr)ULongToPtr(params32->offset),
2048 .length = (GLsizeiptr)ULongToPtr(params32->length),
2049 .access = params32->access,
2051 NTSTATUS status;
2053 /* already mapped, we're being called again with a wow64 pointer */
2054 if (params32->ret) params.ret = (char *)get_buffer_pointer( params.teb, params.target );
2055 else if ((status = ext_glMapBufferRange( &params ))) return status;
2057 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, params.length, params.access, &params32->ret );
2058 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2060 unmap_buffer( params.teb, params.target );
2061 return status;
2064 static NTSTATUS wow64_gl_map_named_buffer( void *args, NTSTATUS (*gl_map_named_buffer64)(void *) )
2066 struct
2068 PTR32 teb;
2069 GLuint buffer;
2070 GLenum access;
2071 PTR32 ret;
2072 } *params32 = args;
2073 struct glMapNamedBuffer_params params =
2075 .teb = get_teb64(params32->teb),
2076 .buffer = params32->buffer,
2077 .access = params32->access,
2079 NTSTATUS status;
2081 /* already mapped, we're being called again with a wow64 pointer */
2082 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2083 else if ((status = gl_map_named_buffer64( &params ))) return status;
2085 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, 0,
2086 map_range_flags_from_map_flags( params.access ), &params32->ret );
2087 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2089 unmap_named_buffer( params.teb, params.buffer );
2090 return status;
2093 NTSTATUS wow64_ext_glMapNamedBuffer( void *args )
2095 return wow64_gl_map_named_buffer( args, ext_glMapNamedBuffer );
2098 NTSTATUS wow64_ext_glMapNamedBufferEXT( void *args )
2100 return wow64_gl_map_named_buffer( args, ext_glMapNamedBufferEXT );
2103 static NTSTATUS wow64_gl_map_named_buffer_range( void *args, NTSTATUS (*gl_map_named_buffer_range64)(void *) )
2105 struct
2107 PTR32 teb;
2108 GLuint buffer;
2109 PTR32 offset;
2110 PTR32 length;
2111 GLbitfield access;
2112 PTR32 ret;
2113 } *params32 = args;
2114 struct glMapNamedBufferRange_params params =
2116 .teb = get_teb64(params32->teb),
2117 .buffer = params32->buffer,
2118 .offset = (GLintptr)ULongToPtr(params32->offset),
2119 .length = (GLsizeiptr)ULongToPtr(params32->length),
2120 .access = params32->access,
2122 NTSTATUS status;
2124 /* already mapped, we're being called again with a wow64 pointer */
2125 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2126 else if ((status = gl_map_named_buffer_range64( &params ))) return status;
2128 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, params.length, params.access, &params32->ret );
2129 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2131 unmap_named_buffer( params.teb, params.buffer );
2132 return status;
2135 NTSTATUS wow64_ext_glMapNamedBufferRange( void *args )
2137 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRange );
2140 NTSTATUS wow64_ext_glMapNamedBufferRangeEXT( void *args )
2142 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRangeEXT );
2145 static NTSTATUS wow64_gl_unmap_buffer( void *args, NTSTATUS (*gl_unmap_buffer64)(void *) )
2147 PTR32 *ptr;
2148 struct
2150 PTR32 teb;
2151 GLenum target;
2152 GLboolean ret;
2153 } *params32 = args;
2154 struct glUnmapBuffer_params params =
2156 .teb = get_teb64(params32->teb),
2157 .target = params32->target,
2158 .ret = TRUE,
2160 NTSTATUS status;
2162 if (!(ptr = get_buffer_pointer( params.teb, params.target ))) return STATUS_SUCCESS;
2164 status = wow64_unmap_buffer( ptr, get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ),
2165 get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ) );
2166 gl_unmap_buffer64( &params );
2167 params32->ret = params.ret;
2169 return status;
2172 NTSTATUS wow64_ext_glUnmapBuffer( void *args )
2174 return wow64_gl_unmap_buffer( args, ext_glUnmapBuffer );
2177 NTSTATUS wow64_ext_glUnmapBufferARB( void *args )
2179 return wow64_gl_unmap_buffer( args, ext_glUnmapBufferARB );
2182 static NTSTATUS wow64_gl_unmap_named_buffer( void *args, NTSTATUS (*gl_unmap_named_buffer64)(void *) )
2184 PTR32 *ptr;
2185 struct
2187 PTR32 teb;
2188 GLint buffer;
2189 GLboolean ret;
2190 } *params32 = args;
2191 struct glUnmapNamedBuffer_params params =
2193 .teb = get_teb64(params32->teb),
2194 .buffer = params32->buffer,
2195 .ret = TRUE,
2197 NTSTATUS status;
2199 if (!(ptr = get_named_buffer_pointer( params.teb, params.buffer ))) return STATUS_SUCCESS;
2201 status = wow64_unmap_buffer( ptr, get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ),
2202 get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ) );
2203 gl_unmap_named_buffer64( &params );
2204 params32->ret = params.ret;
2206 return status;
2209 NTSTATUS wow64_ext_glUnmapNamedBuffer( void *args )
2211 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBuffer );
2214 NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args )
2216 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT );
2219 NTSTATUS wow64_thread_attach( void *args )
2221 return thread_attach( get_teb64( (ULONG_PTR)args ));
2224 NTSTATUS wow64_process_detach( void *args )
2226 NTSTATUS status;
2228 if ((status = process_detach( NULL ))) return status;
2230 free( wow64_strings );
2231 wow64_strings = NULL;
2232 wow64_strings_count = 0;
2234 return STATUS_SUCCESS;
2237 #endif