explorer: Call user driver through a new CreateDesktop callback.
[wine.git] / dlls / opengl32 / unix_wgl.c
blob6c3379b90a2421e7791cdb9e04a7fbbc7f3d29ab
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 pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER;
48 /* handle management */
50 enum wgl_handle_type
52 HANDLE_PBUFFER = 0 << 12,
53 HANDLE_CONTEXT = 1 << 12,
54 HANDLE_CONTEXT_V3 = 3 << 12,
55 HANDLE_GLSYNC = 4 << 12,
56 HANDLE_TYPE_MASK = 15 << 12,
59 struct opengl_context
61 DWORD tid; /* thread that the context is current in */
62 void (CALLBACK *debug_callback)( GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *, const void * ); /* debug callback */
63 const void *debug_user; /* debug user parameter */
64 GLubyte *extensions; /* extension string */
65 GLuint *disabled_exts; /* indices of disabled extensions */
66 struct wgl_context *drv_ctx; /* driver context */
69 struct wgl_handle
71 UINT handle;
72 struct opengl_funcs *funcs;
73 union
75 struct opengl_context *context; /* for HANDLE_CONTEXT */
76 struct wgl_pbuffer *pbuffer; /* for HANDLE_PBUFFER */
77 struct wgl_handle *next; /* for free handles */
78 } u;
81 #define MAX_WGL_HANDLES 1024
82 static struct wgl_handle wgl_handles[MAX_WGL_HANDLES];
83 static struct wgl_handle *next_free;
84 static unsigned int handle_count;
86 /* the current context is assumed valid and doesn't need locking */
87 static inline struct wgl_handle *get_current_context_ptr( TEB *teb )
89 if (!teb->glCurrentRC) return NULL;
90 return &wgl_handles[LOWORD(teb->glCurrentRC) & ~HANDLE_TYPE_MASK];
93 static inline HANDLE next_handle( struct wgl_handle *ptr, enum wgl_handle_type type )
95 WORD generation = HIWORD( ptr->handle ) + 1;
96 if (!generation) generation++;
97 ptr->handle = MAKELONG( ptr - wgl_handles, generation ) | type;
98 return ULongToHandle( ptr->handle );
101 static struct wgl_handle *get_handle_ptr( HANDLE handle, enum wgl_handle_type type )
103 unsigned int index = LOWORD( handle ) & ~HANDLE_TYPE_MASK;
105 if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle)
106 return &wgl_handles[index];
108 RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
109 return NULL;
112 static HANDLE alloc_handle( enum wgl_handle_type type, struct opengl_funcs *funcs, void *user_ptr )
114 HANDLE handle = 0;
115 struct wgl_handle *ptr = NULL;
117 if ((ptr = next_free))
118 next_free = next_free->u.next;
119 else if (handle_count < MAX_WGL_HANDLES)
120 ptr = &wgl_handles[handle_count++];
122 if (ptr)
124 ptr->funcs = funcs;
125 ptr->u.context = user_ptr;
126 handle = next_handle( ptr, type );
128 else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY );
129 return handle;
132 static void free_handle_ptr( struct wgl_handle *ptr )
134 ptr->handle |= 0xffff;
135 ptr->u.next = next_free;
136 ptr->funcs = NULL;
137 next_free = ptr;
140 /* check if the extension is present in the list */
141 static BOOL has_extension( const char *list, const char *ext, size_t len )
143 while (list)
145 while (*list == ' ') list++;
146 if (!strncmp( list, ext, len ) && (!list[len] || list[len] == ' ')) return TRUE;
147 list = strchr( list, ' ' );
149 return FALSE;
152 static GLubyte *filter_extensions_list( const char *extensions, const char *disabled )
154 const char *end;
155 char *p, *str;
157 p = str = malloc( strlen( extensions ) + 2 );
158 if (!str) return NULL;
160 TRACE( "GL_EXTENSIONS:\n" );
162 for (;;)
164 while (*extensions == ' ') extensions++;
165 if (!*extensions) break;
167 if (!(end = strchr( extensions, ' ' ))) end = extensions + strlen( extensions );
168 memcpy( p, extensions, end - extensions );
169 p[end - extensions] = 0;
171 if (!has_extension( disabled, p, strlen( p ) ))
173 TRACE( "++ %s\n", p );
174 p += end - extensions;
175 *p++ = ' ';
177 else
179 TRACE( "-- %s (disabled by config)\n", p );
181 extensions = end;
183 *p = 0;
184 return (GLubyte *)str;
187 static GLuint *filter_extensions_index( TEB *teb, const char *disabled )
189 const struct opengl_funcs *funcs = teb->glTable;
190 GLuint *disabled_index;
191 GLint extensions_count;
192 unsigned int i = 0, j;
193 const char *ext;
195 if (!funcs->ext.p_glGetStringi)
197 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
198 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
199 if (!funcs->ext.p_glGetStringi) return NULL;
202 funcs->gl.p_glGetIntegerv( GL_NUM_EXTENSIONS, &extensions_count );
203 disabled_index = malloc( extensions_count * sizeof(*disabled_index) );
204 if (!disabled_index) return NULL;
206 TRACE( "GL_EXTENSIONS:\n" );
208 for (j = 0; j < extensions_count; ++j)
210 ext = (const char *)funcs->ext.p_glGetStringi( GL_EXTENSIONS, j );
211 if (!has_extension( disabled, ext, strlen( ext ) ))
213 TRACE( "++ %s\n", ext );
215 else
217 TRACE( "-- %s (disabled by config)\n", ext );
218 disabled_index[i++] = j;
222 disabled_index[i] = ~0u;
223 return disabled_index;
226 static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
228 while (len--) *dst++ = (unsigned char)*src++;
231 static inline UINT asciiz_to_unicode( WCHAR *dst, const char *src )
233 WCHAR *p = dst;
234 while ((*p++ = *src++));
235 return (p - dst) * sizeof(WCHAR);
238 static inline void unicode_to_ascii( char *dst, const WCHAR *src, size_t len )
240 while (len--) *dst++ = *src++;
243 static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len )
245 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
246 OBJECT_ATTRIBUTES attr;
247 HANDLE ret;
249 attr.Length = sizeof(attr);
250 attr.RootDirectory = root;
251 attr.ObjectName = &nameW;
252 attr.Attributes = 0;
253 attr.SecurityDescriptor = NULL;
254 attr.SecurityQualityOfService = NULL;
256 return NtOpenKeyEx( &ret, MAXIMUM_ALLOWED, &attr, 0 ) ? 0 : ret;
259 static HKEY open_hkcu_key( const char *name )
261 WCHAR bufferW[256];
262 static HKEY hkcu;
264 if (!hkcu)
266 char buffer[256];
267 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
268 DWORD i, len = sizeof(sid_data);
269 SID *sid;
271 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len ))
272 return 0;
274 sid = ((TOKEN_USER *)sid_data)->User.Sid;
275 len = sprintf( buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
276 (int)MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
277 sid->IdentifierAuthority.Value[4] ),
278 MAKEWORD( sid->IdentifierAuthority.Value[3],
279 sid->IdentifierAuthority.Value[2] )));
280 for (i = 0; i < sid->SubAuthorityCount; i++)
281 len += sprintf( buffer + len, "-%u", (int)sid->SubAuthority[i] );
283 ascii_to_unicode( bufferW, buffer, len );
284 hkcu = reg_open_key( NULL, bufferW, len * sizeof(WCHAR) );
287 return reg_open_key( hkcu, bufferW, asciiz_to_unicode( bufferW, name ) - sizeof(WCHAR) );
290 static NTSTATUS query_reg_value( HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size )
292 unsigned int name_size = name ? lstrlenW( name ) * sizeof(WCHAR) : 0;
293 UNICODE_STRING nameW = { name_size, name_size, (WCHAR *)name };
295 return NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, info, size, &size );
298 /* build the extension string by filtering out the disabled extensions */
299 static BOOL filter_extensions( TEB * teb, const char *extensions, GLubyte **exts_list, GLuint **disabled_exts )
301 static const char *disabled;
303 if (!disabled)
305 char *str = NULL;
306 HKEY hkey;
308 /* @@ Wine registry key: HKCU\Software\Wine\OpenGL */
309 if ((hkey = open_hkcu_key( "Software\\Wine\\OpenGL" )))
311 char buffer[4096];
312 KEY_VALUE_PARTIAL_INFORMATION *value = (void *)buffer;
313 static WCHAR disabled_extensionsW[] = {'D','i','s','a','b','l','e','d','E','x','t','e','n','s','i','o','n','s',0};
315 if (!query_reg_value( hkey, disabled_extensionsW, value, sizeof(buffer) ))
317 ULONG len = value->DataLength / sizeof(WCHAR);
319 unicode_to_ascii( buffer, (WCHAR *)value->Data, len );
320 buffer[len] = 0;
321 str = strdup( buffer );
323 NtClose( hkey );
325 if (str)
327 if (InterlockedCompareExchangePointer( (void **)&disabled, str, NULL )) free( str );
329 else disabled = "";
332 if (!disabled[0]) return FALSE;
333 if (extensions && !*exts_list) *exts_list = filter_extensions_list( extensions, disabled );
334 if (!*disabled_exts) *disabled_exts = filter_extensions_index( teb, disabled );
335 return (exts_list && *exts_list) || *disabled_exts;
338 static const GLuint *disabled_extensions_index( TEB *teb )
340 struct wgl_handle *ptr = get_current_context_ptr( teb );
341 GLuint **disabled = &ptr->u.context->disabled_exts;
342 if (*disabled || filter_extensions( teb, NULL, NULL, disabled )) return *disabled;
343 return NULL;
346 /* Check if a GL extension is supported */
347 static BOOL check_extension_support( TEB *teb, const char *extension, const char *available_extensions )
349 const struct opengl_funcs *funcs = teb->glTable;
350 size_t len;
352 TRACE( "Checking for extension '%s'\n", extension );
354 /* We use the GetProcAddress function from the display driver to retrieve function pointers
355 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
356 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
357 * require the function to return NULL when an extension isn't found. For this reason we check
358 * if the OpenGL extension required for the function we are looking up is supported. */
360 while ((len = strcspn( extension, " " )))
362 /* Check if the extension is part of the GL extension string to see if it is supported. */
363 if (has_extension( available_extensions, extension, len )) return TRUE;
365 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
366 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
367 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
368 * Check if we are searching for a core GL function */
369 if (!strncmp( extension, "GL_VERSION_", 11 ))
371 const GLubyte *gl_version = funcs->gl.p_glGetString( GL_VERSION );
372 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
374 if (!gl_version)
376 ERR( "No OpenGL version found!\n" );
377 return FALSE;
380 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
381 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
382 if ((gl_version[0] > version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2]))) return TRUE;
384 WARN( "The function requires OpenGL version '%c.%c' while your drivers only provide '%c.%c'\n",
385 version[0], version[2], gl_version[0], gl_version[2] );
388 if (extension[len] == ' ') len++;
389 extension += len;
392 return FALSE;
395 static void wrap_glGetIntegerv( TEB *teb, GLenum pname, GLint *data )
397 const struct opengl_funcs *funcs = teb->glTable;
398 const GLuint *disabled;
400 funcs->gl.p_glGetIntegerv( pname, data );
402 if (pname == GL_NUM_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
403 while (*disabled++ != ~0u) (*data)--;
406 static const GLubyte *wrap_glGetString( TEB *teb, GLenum name )
408 const struct opengl_funcs *funcs = teb->glTable;
409 const GLubyte *ret;
411 if ((ret = funcs->gl.p_glGetString( name )) && name == GL_EXTENSIONS)
413 struct wgl_handle *ptr = get_current_context_ptr( teb );
414 GLubyte **extensions = &ptr->u.context->extensions;
415 GLuint **disabled = &ptr->u.context->disabled_exts;
416 if (*extensions || filter_extensions( teb, (const char *)ret, extensions, disabled )) return *extensions;
419 return ret;
422 static const GLubyte *wrap_glGetStringi( TEB *teb, GLenum name, GLuint index )
424 const struct opengl_funcs *funcs = teb->glTable;
425 const GLuint *disabled;
427 if (!funcs->ext.p_glGetStringi)
429 void **func_ptr = (void **)&funcs->ext.p_glGetStringi;
430 *func_ptr = funcs->wgl.p_wglGetProcAddress( "glGetStringi" );
433 if (name == GL_EXTENSIONS && (disabled = disabled_extensions_index( teb )))
434 while (index >= *disabled++) index++;
436 return funcs->ext.p_glGetStringi( name, index );
439 static char *build_extension_list( TEB *teb )
441 GLint len = 0, capacity, i, extensions_count;
442 char *extension, *tmp, *available_extensions;
444 wrap_glGetIntegerv( teb, GL_NUM_EXTENSIONS, &extensions_count );
445 capacity = 128 * extensions_count;
447 if (!(available_extensions = malloc( capacity ))) return NULL;
448 for (i = 0; i < extensions_count; ++i)
450 extension = (char *)wrap_glGetStringi( teb, GL_EXTENSIONS, i );
451 capacity = max( capacity, len + strlen( extension ) + 2 );
452 if (!(tmp = realloc( available_extensions, capacity ))) break;
453 available_extensions = tmp;
454 len += sprintf( available_extensions + len, "%s ", extension );
456 if (len) available_extensions[len - 1] = 0;
458 return available_extensions;
461 static inline enum wgl_handle_type get_current_context_type( TEB *teb )
463 if (!teb->glCurrentRC) return HANDLE_CONTEXT;
464 return LOWORD(teb->glCurrentRC) & HANDLE_TYPE_MASK;
467 /* Check if a GL extension is supported */
468 static BOOL is_extension_supported( TEB *teb, const char *extension )
470 enum wgl_handle_type type = get_current_context_type( teb );
471 char *available_extensions = NULL;
472 BOOL ret = FALSE;
474 if (type == HANDLE_CONTEXT) available_extensions = strdup( (const char *)wrap_glGetString( teb, GL_EXTENSIONS ) );
475 if (!available_extensions) available_extensions = build_extension_list( teb );
477 if (!available_extensions) ERR( "No OpenGL extensions found, check if your OpenGL setup is correct!\n" );
478 else ret = check_extension_support( teb, extension, available_extensions );
480 free( available_extensions );
481 return ret;
484 static int registry_entry_cmp( const void *a, const void *b )
486 const struct registry_entry *entry_a = a, *entry_b = b;
487 return strcmp( entry_a->name, entry_b->name );
490 static PROC wrap_wglGetProcAddress( TEB *teb, LPCSTR name )
492 const struct registry_entry entry = {.name = name}, *found;
493 struct opengl_funcs *funcs = teb->glTable;
494 const void **func_ptr;
496 /* Without an active context opengl32 doesn't know to what
497 * driver it has to dispatch wglGetProcAddress.
499 if (!get_current_context_ptr( teb ))
501 WARN( "No active WGL context found\n" );
502 return (void *)-1;
505 if (!(found = bsearch( &entry, extension_registry, extension_registry_size, sizeof(entry), registry_entry_cmp )))
507 WARN( "Function %s unknown\n", name );
508 return (void *)-1;
511 func_ptr = (const void **)&funcs->ext + (found - extension_registry);
512 if (!*func_ptr)
514 void *driver_func = funcs->wgl.p_wglGetProcAddress( name );
516 if (!is_extension_supported( teb, found->extension ))
518 unsigned int i;
519 static const struct { const char *name, *alt; } alternatives[] =
521 { "glCopyTexSubImage3DEXT", "glCopyTexSubImage3D" }, /* needed by RuneScape */
522 { "glVertexAttribDivisor", "glVertexAttribDivisorARB"}, /* needed by Caffeine */
525 for (i = 0; i < ARRAY_SIZE(alternatives); i++)
527 if (strcmp( name, alternatives[i].name )) continue;
528 WARN( "Extension %s required for %s not supported, trying %s\n", found->extension,
529 name, alternatives[i].alt );
530 return wrap_wglGetProcAddress( teb, alternatives[i].alt );
533 WARN( "Extension %s required for %s not supported\n", found->extension, name );
534 return (void *)-1;
537 if (driver_func == NULL)
539 WARN( "Function %s not supported by driver\n", name );
540 return (void *)-1;
543 *func_ptr = driver_func;
546 /* Return the index into the extension registry instead of a useless
547 * function pointer, PE side will returns its own function pointers.
549 return (void *)(UINT_PTR)(found - extension_registry);
552 static BOOL wrap_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
554 struct wgl_handle *src, *dst;
555 BOOL ret = FALSE;
557 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
558 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
560 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
561 else ret = src->funcs->wgl.p_wglCopyContext( src->u.context->drv_ctx, dst->u.context->drv_ctx, mask );
563 return ret;
566 static HGLRC wrap_wglCreateContext( HDC hdc )
568 HGLRC ret = 0;
569 struct wgl_context *drv_ctx;
570 struct opengl_context *context;
571 struct opengl_funcs *funcs = get_dc_funcs( hdc );
573 if (!funcs) return 0;
574 if (!(drv_ctx = funcs->wgl.p_wglCreateContext( hdc ))) return 0;
575 if ((context = calloc( 1, sizeof(*context) )))
577 context->drv_ctx = drv_ctx;
578 if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) free( context );
580 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
581 return ret;
584 static BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc )
586 BOOL ret = TRUE;
587 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
588 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
590 if (hglrc)
592 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
593 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
595 ret = ptr->funcs->wgl.p_wglMakeCurrent( hdc, ptr->u.context->drv_ctx );
596 if (ret)
598 if (prev) prev->u.context->tid = 0;
599 ptr->u.context->tid = tid;
600 teb->glReserved1[0] = hdc;
601 teb->glReserved1[1] = hdc;
602 teb->glCurrentRC = hglrc;
603 teb->glTable = ptr->funcs;
606 else
608 RtlSetLastWin32Error( ERROR_BUSY );
609 ret = FALSE;
612 else if (prev)
614 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
615 prev->u.context->tid = 0;
616 teb->glCurrentRC = 0;
617 teb->glTable = &null_opengl_funcs;
619 else if (!hdc)
621 RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
622 ret = FALSE;
624 return ret;
627 static BOOL wrap_wglDeleteContext( TEB *teb, HGLRC hglrc )
629 struct wgl_handle *ptr;
630 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
632 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
633 if (ptr->u.context->tid && ptr->u.context->tid != tid)
635 RtlSetLastWin32Error( ERROR_BUSY );
636 return FALSE;
638 if (hglrc == teb->glCurrentRC) wrap_wglMakeCurrent( teb, 0, 0 );
639 ptr->funcs->wgl.p_wglDeleteContext( ptr->u.context->drv_ctx );
640 free( ptr->u.context->disabled_exts );
641 free( ptr->u.context->extensions );
642 free( ptr->u.context );
643 free_handle_ptr( ptr );
644 return TRUE;
647 static BOOL wrap_wglShareLists( HGLRC hglrcSrc, HGLRC hglrcDst )
649 BOOL ret = FALSE;
650 struct wgl_handle *src, *dst;
652 if (!(src = get_handle_ptr( hglrcSrc, HANDLE_CONTEXT ))) return FALSE;
653 if ((dst = get_handle_ptr( hglrcDst, HANDLE_CONTEXT )))
655 if (src->funcs != dst->funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE );
656 else ret = src->funcs->wgl.p_wglShareLists( src->u.context->drv_ctx, dst->u.context->drv_ctx );
658 return ret;
661 static BOOL wrap_wglBindTexImageARB( HPBUFFERARB handle, int buffer )
663 struct wgl_handle *ptr;
664 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
665 return ptr->funcs->ext.p_wglBindTexImageARB( ptr->u.pbuffer, buffer );
668 static HGLRC wrap_wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *attribs )
670 HGLRC ret = 0;
671 struct wgl_context *drv_ctx;
672 struct wgl_handle *share_ptr = NULL;
673 struct opengl_context *context;
674 struct opengl_funcs *funcs = get_dc_funcs( hdc );
676 if (!funcs)
678 RtlSetLastWin32Error( ERROR_DC_NOT_FOUND );
679 return 0;
681 if (!funcs->ext.p_wglCreateContextAttribsARB) return 0;
682 if (share && !(share_ptr = get_handle_ptr( share, HANDLE_CONTEXT )))
684 RtlSetLastWin32Error( ERROR_INVALID_OPERATION );
685 return 0;
687 if ((drv_ctx = funcs->ext.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->u.context->drv_ctx : NULL, attribs )))
689 if ((context = calloc( 1, sizeof(*context) )))
691 enum wgl_handle_type type = HANDLE_CONTEXT;
693 if (attribs)
695 while (*attribs)
697 if (attribs[0] == WGL_CONTEXT_MAJOR_VERSION_ARB)
699 if (attribs[1] >= 3) type = HANDLE_CONTEXT_V3;
700 break;
702 attribs += 2;
706 context->drv_ctx = drv_ctx;
707 if (!(ret = alloc_handle( type, funcs, context ))) free( context );
709 if (!ret) funcs->wgl.p_wglDeleteContext( drv_ctx );
712 return ret;
715 static HPBUFFERARB wrap_wglCreatePbufferARB( HDC hdc, int format, int width, int height, const int *attribs )
717 HPBUFFERARB ret;
718 struct wgl_pbuffer *pbuffer;
719 struct opengl_funcs *funcs = get_dc_funcs( hdc );
721 if (!funcs || !funcs->ext.p_wglCreatePbufferARB) return 0;
722 if (!(pbuffer = funcs->ext.p_wglCreatePbufferARB( hdc, format, width, height, attribs ))) return 0;
723 ret = alloc_handle( HANDLE_PBUFFER, funcs, pbuffer );
724 if (!ret) funcs->ext.p_wglDestroyPbufferARB( pbuffer );
725 return ret;
728 static BOOL wrap_wglDestroyPbufferARB( HPBUFFERARB handle )
730 struct wgl_handle *ptr;
732 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
733 ptr->funcs->ext.p_wglDestroyPbufferARB( ptr->u.pbuffer );
734 free_handle_ptr( ptr );
735 return TRUE;
738 static HDC wrap_wglGetPbufferDCARB( HPBUFFERARB handle )
740 struct wgl_handle *ptr;
741 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return 0;
742 return ptr->funcs->ext.p_wglGetPbufferDCARB( ptr->u.pbuffer );
745 static BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC hglrc )
747 BOOL ret = TRUE;
748 DWORD tid = HandleToULong(teb->ClientId.UniqueThread);
749 struct wgl_handle *ptr, *prev = get_current_context_ptr( teb );
751 if (hglrc)
753 if (!(ptr = get_handle_ptr( hglrc, HANDLE_CONTEXT ))) return FALSE;
754 if (!ptr->u.context->tid || ptr->u.context->tid == tid)
756 ret = (ptr->funcs->ext.p_wglMakeContextCurrentARB &&
757 ptr->funcs->ext.p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->u.context->drv_ctx ));
758 if (ret)
760 if (prev) prev->u.context->tid = 0;
761 ptr->u.context->tid = tid;
762 teb->glReserved1[0] = draw_hdc;
763 teb->glReserved1[1] = read_hdc;
764 teb->glCurrentRC = hglrc;
765 teb->glTable = ptr->funcs;
768 else
770 RtlSetLastWin32Error( ERROR_BUSY );
771 ret = FALSE;
774 else if (prev)
776 if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
777 prev->u.context->tid = 0;
778 teb->glCurrentRC = 0;
779 teb->glTable = &null_opengl_funcs;
781 return ret;
784 static BOOL wrap_wglQueryPbufferARB( HPBUFFERARB handle, int attrib, int *value )
786 struct wgl_handle *ptr;
787 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
788 return ptr->funcs->ext.p_wglQueryPbufferARB( ptr->u.pbuffer, attrib, value );
791 static int wrap_wglReleasePbufferDCARB( HPBUFFERARB handle, HDC hdc )
793 struct wgl_handle *ptr;
794 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
795 return ptr->funcs->ext.p_wglReleasePbufferDCARB( ptr->u.pbuffer, hdc );
798 static BOOL wrap_wglReleaseTexImageARB( HPBUFFERARB handle, int buffer )
800 struct wgl_handle *ptr;
801 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
802 return ptr->funcs->ext.p_wglReleaseTexImageARB( ptr->u.pbuffer, buffer );
805 static BOOL wrap_wglSetPbufferAttribARB( HPBUFFERARB handle, const int *attribs )
807 struct wgl_handle *ptr;
808 if (!(ptr = get_handle_ptr( handle, HANDLE_PBUFFER ))) return FALSE;
809 return ptr->funcs->ext.p_wglSetPbufferAttribARB( ptr->u.pbuffer, attribs );
812 static void gl_debug_message_callback( GLenum source, GLenum type, GLuint id, GLenum severity,
813 GLsizei length, const GLchar *message, const void *userParam )
815 struct wine_gl_debug_message_params params =
817 .source = source,
818 .type = type,
819 .id = id,
820 .severity = severity,
821 .length = length,
822 .message = message,
824 void *ret_ptr;
825 ULONG ret_len;
827 struct wgl_handle *ptr = (struct wgl_handle *)userParam;
828 if (!(params.user_callback = ptr->u.context->debug_callback)) return;
829 params.user_data = ptr->u.context->debug_user;
831 KeUserModeCallback( NtUserCallOpenGLDebugMessageCallback, &params, sizeof(params),
832 &ret_ptr, &ret_len );
835 static void wrap_glDebugMessageCallback( TEB *teb, GLDEBUGPROC callback, const void *userParam )
837 struct wgl_handle *ptr = get_current_context_ptr( teb );
838 const struct opengl_funcs *funcs = teb->glTable;
840 if (!funcs->ext.p_glDebugMessageCallback) return;
842 ptr->u.context->debug_callback = callback;
843 ptr->u.context->debug_user = userParam;
844 funcs->ext.p_glDebugMessageCallback( gl_debug_message_callback, ptr );
847 static void wrap_glDebugMessageCallbackAMD( TEB *teb, GLDEBUGPROCAMD callback, void *userParam )
849 struct wgl_handle *ptr = get_current_context_ptr( teb );
850 const struct opengl_funcs *funcs = teb->glTable;
852 if (!funcs->ext.p_glDebugMessageCallbackAMD) return;
854 ptr->u.context->debug_callback = callback;
855 ptr->u.context->debug_user = userParam;
856 funcs->ext.p_glDebugMessageCallbackAMD( gl_debug_message_callback, ptr );
859 static void wrap_glDebugMessageCallbackARB( TEB *teb, GLDEBUGPROCARB callback, const void *userParam )
861 struct wgl_handle *ptr = get_current_context_ptr( teb );
862 const struct opengl_funcs *funcs = teb->glTable;
864 if (!funcs->ext.p_glDebugMessageCallbackARB) return;
866 ptr->u.context->debug_callback = callback;
867 ptr->u.context->debug_user = userParam;
868 funcs->ext.p_glDebugMessageCallbackARB( gl_debug_message_callback, ptr );
871 NTSTATUS wgl_wglCopyContext( void *args )
873 struct wglCopyContext_params *params = args;
874 pthread_mutex_lock( &wgl_lock );
875 params->ret = wrap_wglCopyContext( params->hglrcSrc, params->hglrcDst, params->mask );
876 pthread_mutex_unlock( &wgl_lock );
877 return STATUS_SUCCESS;
880 NTSTATUS wgl_wglCreateContext( void *args )
882 struct wglCreateContext_params *params = args;
883 pthread_mutex_lock( &wgl_lock );
884 params->ret = wrap_wglCreateContext( params->hDc );
885 pthread_mutex_unlock( &wgl_lock );
886 return STATUS_SUCCESS;
889 NTSTATUS wgl_wglDeleteContext( void *args )
891 struct wglDeleteContext_params *params = args;
892 pthread_mutex_lock( &wgl_lock );
893 params->ret = wrap_wglDeleteContext( params->teb, params->oldContext );
894 pthread_mutex_unlock( &wgl_lock );
895 return STATUS_SUCCESS;
898 NTSTATUS wgl_wglGetProcAddress( void *args )
900 struct wglGetProcAddress_params *params = args;
901 params->ret = wrap_wglGetProcAddress( params->teb, params->lpszProc );
902 return STATUS_SUCCESS;
905 NTSTATUS wgl_wglMakeCurrent( void *args )
907 struct wglMakeCurrent_params *params = args;
908 if (params->newContext) pthread_mutex_lock( &wgl_lock );
909 params->ret = wrap_wglMakeCurrent( params->teb, params->hDc, params->newContext );
910 if (params->newContext) pthread_mutex_unlock( &wgl_lock );
911 return STATUS_SUCCESS;
914 NTSTATUS wgl_wglShareLists( void *args )
916 struct wglShareLists_params *params = args;
917 pthread_mutex_lock( &wgl_lock );
918 params->ret = wrap_wglShareLists( params->hrcSrvShare, params->hrcSrvSource );
919 pthread_mutex_unlock( &wgl_lock );
920 return STATUS_SUCCESS;
923 NTSTATUS gl_glGetIntegerv( void *args )
925 struct glGetIntegerv_params *params = args;
926 wrap_glGetIntegerv( params->teb, params->pname, params->data );
927 return STATUS_SUCCESS;
930 NTSTATUS gl_glGetString( void *args )
932 struct glGetString_params *params = args;
933 params->ret = wrap_glGetString( params->teb, params->name );
934 return STATUS_SUCCESS;
937 NTSTATUS ext_glDebugMessageCallback( void *args )
939 struct glDebugMessageCallback_params *params = args;
940 wrap_glDebugMessageCallback( params->teb, params->callback, params->userParam );
941 return STATUS_SUCCESS;
944 NTSTATUS ext_glDebugMessageCallbackAMD( void *args )
946 struct glDebugMessageCallbackAMD_params *params = args;
947 wrap_glDebugMessageCallbackAMD( params->teb, params->callback, params->userParam );
948 return STATUS_SUCCESS;
951 NTSTATUS ext_glDebugMessageCallbackARB( void *args )
953 struct glDebugMessageCallbackARB_params *params = args;
954 wrap_glDebugMessageCallbackARB( params->teb, params->callback, params->userParam );
955 return STATUS_SUCCESS;
958 NTSTATUS ext_glGetStringi( void *args )
960 struct glGetStringi_params *params = args;
961 params->ret = wrap_glGetStringi( params->teb, params->name, params->index );
962 return STATUS_SUCCESS;
965 NTSTATUS ext_wglBindTexImageARB( void *args )
967 struct wglBindTexImageARB_params *params = args;
968 pthread_mutex_lock( &wgl_lock );
969 params->ret = wrap_wglBindTexImageARB( params->hPbuffer, params->iBuffer );
970 pthread_mutex_unlock( &wgl_lock );
971 return STATUS_SUCCESS;
974 NTSTATUS ext_wglCreateContextAttribsARB( void *args )
976 struct wglCreateContextAttribsARB_params *params = args;
977 pthread_mutex_lock( &wgl_lock );
978 params->ret = wrap_wglCreateContextAttribsARB( params->hDC, params->hShareContext, params->attribList );
979 pthread_mutex_unlock( &wgl_lock );
980 return STATUS_SUCCESS;
983 NTSTATUS ext_wglCreatePbufferARB( void *args )
985 struct wglCreatePbufferARB_params *params = args;
986 pthread_mutex_lock( &wgl_lock );
987 params->ret = wrap_wglCreatePbufferARB( params->hDC, params->iPixelFormat, params->iWidth, params->iHeight, params->piAttribList );
988 pthread_mutex_unlock( &wgl_lock );
989 return STATUS_SUCCESS;
992 NTSTATUS ext_wglDestroyPbufferARB( void *args )
994 struct wglDestroyPbufferARB_params *params = args;
995 pthread_mutex_lock( &wgl_lock );
996 params->ret = wrap_wglDestroyPbufferARB( params->hPbuffer );
997 pthread_mutex_unlock( &wgl_lock );
998 return STATUS_SUCCESS;
1001 NTSTATUS ext_wglGetPbufferDCARB( void *args )
1003 struct wglGetPbufferDCARB_params *params = args;
1004 pthread_mutex_lock( &wgl_lock );
1005 params->ret = wrap_wglGetPbufferDCARB( params->hPbuffer );
1006 pthread_mutex_unlock( &wgl_lock );
1007 return STATUS_SUCCESS;
1010 NTSTATUS ext_wglMakeContextCurrentARB( void *args )
1012 struct wglMakeContextCurrentARB_params *params = args;
1013 if (params->hglrc) pthread_mutex_lock( &wgl_lock );
1014 params->ret = wrap_wglMakeContextCurrentARB( params->teb, params->hDrawDC, params->hReadDC, params->hglrc );
1015 if (params->hglrc) pthread_mutex_unlock( &wgl_lock );
1016 return STATUS_SUCCESS;
1019 NTSTATUS ext_wglQueryPbufferARB( void *args )
1021 struct wglQueryPbufferARB_params *params = args;
1022 pthread_mutex_lock( &wgl_lock );
1023 params->ret = wrap_wglQueryPbufferARB( params->hPbuffer, params->iAttribute, params->piValue );
1024 pthread_mutex_unlock( &wgl_lock );
1025 return STATUS_SUCCESS;
1028 NTSTATUS ext_wglReleasePbufferDCARB( void *args )
1030 struct wglReleasePbufferDCARB_params *params = args;
1031 pthread_mutex_lock( &wgl_lock );
1032 params->ret = wrap_wglReleasePbufferDCARB( params->hPbuffer, params->hDC );
1033 pthread_mutex_unlock( &wgl_lock );
1034 return STATUS_SUCCESS;
1037 NTSTATUS ext_wglReleaseTexImageARB( void *args )
1039 struct wglReleaseTexImageARB_params *params = args;
1040 pthread_mutex_lock( &wgl_lock );
1041 params->ret = wrap_wglReleaseTexImageARB( params->hPbuffer, params->iBuffer );
1042 pthread_mutex_unlock( &wgl_lock );
1043 return STATUS_SUCCESS;
1046 NTSTATUS ext_wglSetPbufferAttribARB( void *args )
1048 struct wglSetPbufferAttribARB_params *params = args;
1049 pthread_mutex_lock( &wgl_lock );
1050 params->ret = wrap_wglSetPbufferAttribARB( params->hPbuffer, params->piAttribList );
1051 pthread_mutex_unlock( &wgl_lock );
1052 return STATUS_SUCCESS;
1055 NTSTATUS thread_attach( void *args )
1057 TEB *teb = args;
1058 teb->glTable = &null_opengl_funcs;
1059 return STATUS_SUCCESS;
1062 NTSTATUS process_detach( void *args )
1064 return STATUS_SUCCESS;
1067 #ifdef _WIN64
1069 typedef ULONG PTR32;
1071 extern NTSTATUS ext_glClientWaitSync( void *args ) DECLSPEC_HIDDEN;
1072 extern NTSTATUS ext_glDeleteSync( void *args ) DECLSPEC_HIDDEN;
1073 extern NTSTATUS ext_glFenceSync( void *args ) DECLSPEC_HIDDEN;
1074 extern NTSTATUS ext_glGetBufferPointerv( void *args ) DECLSPEC_HIDDEN;
1075 extern NTSTATUS ext_glGetBufferPointervARB( void *args ) DECLSPEC_HIDDEN;
1076 extern NTSTATUS ext_glGetNamedBufferPointerv( void *args ) DECLSPEC_HIDDEN;
1077 extern NTSTATUS ext_glGetNamedBufferPointervEXT( void *args ) DECLSPEC_HIDDEN;
1078 extern NTSTATUS ext_glGetSynciv( void *args ) DECLSPEC_HIDDEN;
1079 extern NTSTATUS ext_glIsSync( void *args ) DECLSPEC_HIDDEN;
1080 extern NTSTATUS ext_glMapBuffer( void *args ) DECLSPEC_HIDDEN;
1082 extern NTSTATUS ext_glUnmapBuffer( void *args ) DECLSPEC_HIDDEN;
1083 extern NTSTATUS ext_glUnmapBufferARB( void *args ) DECLSPEC_HIDDEN;
1084 extern NTSTATUS ext_glUnmapNamedBuffer( void *args ) DECLSPEC_HIDDEN;
1085 extern NTSTATUS ext_glUnmapNamedBufferEXT( void *args ) DECLSPEC_HIDDEN;
1087 extern NTSTATUS ext_glMapBufferARB( void *args ) DECLSPEC_HIDDEN;
1088 extern NTSTATUS ext_glMapBufferRange( void *args ) DECLSPEC_HIDDEN;
1089 extern NTSTATUS ext_glMapNamedBuffer( void *args ) DECLSPEC_HIDDEN;
1090 extern NTSTATUS ext_glMapNamedBufferEXT( void *args ) DECLSPEC_HIDDEN;
1091 extern NTSTATUS ext_glMapNamedBufferRange( void *args ) DECLSPEC_HIDDEN;
1092 extern NTSTATUS ext_glMapNamedBufferRangeEXT( void *args ) DECLSPEC_HIDDEN;
1093 extern NTSTATUS ext_glPathGlyphIndexRangeNV( void *args ) DECLSPEC_HIDDEN;
1094 extern NTSTATUS ext_glWaitSync( void *args ) DECLSPEC_HIDDEN;
1095 extern NTSTATUS ext_wglGetExtensionsStringARB( void *args ) DECLSPEC_HIDDEN;
1096 extern NTSTATUS ext_wglGetExtensionsStringEXT( void *args ) DECLSPEC_HIDDEN;
1097 extern NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
1098 extern NTSTATUS ext_wglQueryRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
1100 struct wow64_string_entry
1102 const char *str;
1103 PTR32 wow64_str;
1105 static struct wow64_string_entry *wow64_strings;
1106 static SIZE_T wow64_strings_count;
1108 static PTR32 find_wow64_string( const char *str, PTR32 wow64_str )
1110 void *tmp;
1111 SIZE_T i;
1113 pthread_mutex_lock( &wgl_lock );
1115 for (i = 0; i < wow64_strings_count; i++) if (wow64_strings[i].str == str) break;
1116 if (i == wow64_strings_count && (tmp = realloc( wow64_strings, (i + 1) * sizeof(*wow64_strings) )))
1118 wow64_strings = tmp;
1119 wow64_strings[i].str = str;
1120 wow64_strings[i].wow64_str = 0;
1121 wow64_strings_count += 1;
1124 if (i == wow64_strings_count) ERR( "Failed to allocate memory for wow64 strings\n" );
1125 else if (wow64_strings[i].wow64_str) wow64_str = wow64_strings[i].wow64_str;
1126 else if (wow64_str)
1128 strcpy( UlongToPtr(wow64_str), (char *)str );
1129 wow64_strings[i].wow64_str = wow64_str;
1132 pthread_mutex_unlock( &wgl_lock );
1134 return wow64_str;
1137 static inline void update_teb32_context( TEB *teb )
1139 void *teb32;
1141 if (!teb->WowTebOffset) return;
1142 teb32 = (char *)teb + teb->WowTebOffset;
1144 ((TEB32 *)teb32)->glCurrentRC = (UINT_PTR)teb->glCurrentRC;
1145 ((TEB32 *)teb32)->glReserved1[0] = (UINT_PTR)teb->glReserved1[0];
1146 ((TEB32 *)teb32)->glReserved1[1] = (UINT_PTR)teb->glReserved1[1];
1149 NTSTATUS wow64_wgl_wglCreateContext( void *args )
1151 struct
1153 PTR32 teb;
1154 PTR32 hDc;
1155 PTR32 ret;
1156 } *params32 = args;
1157 struct wglCreateContext_params params =
1159 .teb = get_teb64(params32->teb),
1160 .hDc = ULongToPtr(params32->hDc),
1162 NTSTATUS status;
1163 if ((status = wgl_wglCreateContext( &params ))) return status;
1164 params32->ret = (UINT_PTR)params.ret;
1165 return STATUS_SUCCESS;
1168 NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args )
1170 struct
1172 PTR32 teb;
1173 PTR32 hDC;
1174 PTR32 hShareContext;
1175 PTR32 attribList;
1176 PTR32 ret;
1177 } *params32 = args;
1178 struct wglCreateContextAttribsARB_params params =
1180 .teb = get_teb64(params32->teb),
1181 .hDC = ULongToPtr(params32->hDC),
1182 .hShareContext = ULongToPtr(params32->hShareContext),
1183 .attribList = ULongToPtr(params32->attribList),
1185 NTSTATUS status;
1186 if ((status = ext_wglCreateContextAttribsARB( &params ))) return status;
1187 params32->ret = (UINT_PTR)params.ret;
1188 return STATUS_SUCCESS;
1191 NTSTATUS wow64_ext_wglCreatePbufferARB( void *args )
1193 struct
1195 PTR32 teb;
1196 PTR32 hDC;
1197 GLint iPixelFormat;
1198 GLint iWidth;
1199 GLint iHeight;
1200 PTR32 piAttribList;
1201 PTR32 ret;
1202 } *params32 = args;
1203 struct wglCreatePbufferARB_params params =
1205 .teb = get_teb64(params32->teb),
1206 .hDC = ULongToPtr(params32->hDC),
1207 .iPixelFormat = params32->iPixelFormat,
1208 .iWidth = params32->iWidth,
1209 .iHeight = params32->iHeight,
1210 .piAttribList = ULongToPtr(params32->piAttribList),
1212 NTSTATUS status;
1213 if ((status = ext_wglCreatePbufferARB( &params ))) return status;
1214 params32->ret = (UINT_PTR)params.ret;
1215 return STATUS_SUCCESS;
1218 NTSTATUS wow64_wgl_wglDeleteContext( void *args )
1220 struct
1222 PTR32 teb;
1223 PTR32 oldContext;
1224 BOOL ret;
1225 } *params32 = args;
1226 struct wglDeleteContext_params params =
1228 .teb = get_teb64(params32->teb),
1229 .oldContext = ULongToPtr(params32->oldContext),
1231 NTSTATUS status;
1232 if (!(status = wgl_wglDeleteContext( &params ))) update_teb32_context( params.teb );
1233 params32->ret = params.ret;
1234 return status;
1237 NTSTATUS wow64_wgl_wglMakeCurrent( void *args )
1239 struct
1241 PTR32 teb;
1242 PTR32 hDc;
1243 PTR32 newContext;
1244 BOOL ret;
1245 } *params32 = args;
1246 struct wglMakeCurrent_params params =
1248 .teb = get_teb64(params32->teb),
1249 .hDc = ULongToPtr(params32->hDc),
1250 .newContext = ULongToPtr(params32->newContext),
1252 NTSTATUS status;
1253 if (!(status = wgl_wglMakeCurrent( &params ))) update_teb32_context( params.teb );
1254 params32->ret = params.ret;
1255 return status;
1258 NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args )
1260 struct
1262 PTR32 teb;
1263 PTR32 hDrawDC;
1264 PTR32 hReadDC;
1265 PTR32 hglrc;
1266 BOOL ret;
1267 } *params32 = args;
1268 struct wglMakeContextCurrentARB_params params =
1270 .teb = get_teb64(params32->teb),
1271 .hDrawDC = ULongToPtr(params32->hDrawDC),
1272 .hReadDC = ULongToPtr(params32->hReadDC),
1273 .hglrc = ULongToPtr(params32->hglrc),
1275 NTSTATUS status;
1276 if (!(status = ext_wglMakeContextCurrentARB( &params ))) update_teb32_context( params.teb );
1277 params32->ret = params.ret;
1278 return status;
1281 NTSTATUS wow64_ext_wglGetPbufferDCARB( void *args )
1283 struct
1285 PTR32 teb;
1286 PTR32 hPbuffer;
1287 PTR32 ret;
1288 } *params32 = args;
1289 struct wglGetPbufferDCARB_params params =
1291 .teb = get_teb64(params32->teb),
1292 .hPbuffer = (HPBUFFERARB)ULongToPtr(params32->hPbuffer),
1294 NTSTATUS status;
1295 if ((status = ext_wglGetPbufferDCARB( &params ))) return status;
1296 params32->ret = (UINT_PTR)params.ret;
1297 return STATUS_SUCCESS;
1300 NTSTATUS wow64_wgl_wglGetProcAddress( void *args )
1302 struct
1304 PTR32 teb;
1305 PTR32 lpszProc;
1306 PTR32 ret;
1307 } *params32 = args;
1308 struct wglGetProcAddress_params params =
1310 .teb = get_teb64(params32->teb),
1311 .lpszProc = ULongToPtr(params32->lpszProc),
1313 NTSTATUS status;
1314 if ((status = wgl_wglGetProcAddress( &params ))) return status;
1315 params32->ret = (UINT_PTR)params.ret;
1316 return STATUS_SUCCESS;
1319 NTSTATUS wow64_gl_glGetString( void *args )
1321 struct
1323 PTR32 teb;
1324 GLenum name;
1325 PTR32 ret;
1326 } *params32 = args;
1327 struct glGetString_params params =
1329 .teb = get_teb64(params32->teb),
1330 .name = params32->name,
1332 NTSTATUS status;
1334 if ((status = gl_glGetString( &params ))) return status;
1336 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1338 params32->ret = strlen( (char *)params.ret ) + 1;
1339 return STATUS_BUFFER_TOO_SMALL;
1342 return STATUS_SUCCESS;
1345 NTSTATUS wow64_ext_glGetStringi( void *args )
1347 struct
1349 PTR32 teb;
1350 GLenum name;
1351 GLuint index;
1352 PTR32 ret;
1353 } *params32 = args;
1354 struct glGetStringi_params params =
1356 .teb = get_teb64(params32->teb),
1357 .name = params32->name,
1358 .index = params32->index,
1360 NTSTATUS status;
1362 if ((status = ext_glGetStringi( &params ))) return status;
1364 if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
1366 params32->ret = strlen( (char *)params.ret ) + 1;
1367 return STATUS_BUFFER_TOO_SMALL;
1370 return STATUS_SUCCESS;
1373 NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
1375 struct
1377 PTR32 teb;
1378 GLenum fontTarget;
1379 PTR32 fontName;
1380 GLbitfield fontStyle;
1381 GLuint pathParameterTemplate;
1382 GLfloat emScale;
1383 GLuint baseAndCount[2];
1384 GLenum ret;
1385 } *params32 = args;
1386 struct glPathGlyphIndexRangeNV_params params =
1388 .teb = get_teb64(params32->teb),
1389 .fontTarget = params32->fontTarget,
1390 .fontName = ULongToPtr(params32->fontName),
1391 .fontStyle = params32->fontStyle,
1392 .pathParameterTemplate = params32->pathParameterTemplate,
1393 .emScale = params32->emScale,
1394 .baseAndCount = {params32->baseAndCount[0], params32->baseAndCount[1]},
1396 NTSTATUS status;
1397 if ((status = ext_glPathGlyphIndexRangeNV( &params ))) return status;
1398 params32->ret = params.ret;
1399 return status;
1402 NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
1404 struct
1406 PTR32 teb;
1407 PTR32 hdc;
1408 PTR32 ret;
1409 } *params32 = args;
1410 struct wglGetExtensionsStringARB_params params =
1412 .teb = get_teb64(params32->teb),
1413 .hdc = ULongToPtr(params32->hdc),
1415 NTSTATUS status;
1417 if ((status = ext_wglGetExtensionsStringARB( &params ))) return status;
1419 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1421 params32->ret = strlen( params.ret ) + 1;
1422 return STATUS_BUFFER_TOO_SMALL;
1425 return STATUS_SUCCESS;
1428 NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
1430 struct
1432 PTR32 teb;
1433 PTR32 ret;
1434 } *params32 = args;
1435 struct wglGetExtensionsStringEXT_params params =
1437 .teb = get_teb64(params32->teb),
1439 NTSTATUS status;
1441 if ((status = ext_wglGetExtensionsStringEXT( &params ))) return status;
1443 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1445 params32->ret = strlen( params.ret ) + 1;
1446 return STATUS_BUFFER_TOO_SMALL;
1449 return STATUS_SUCCESS;
1452 NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
1454 struct
1456 PTR32 teb;
1457 GLenum attribute;
1458 PTR32 ret;
1459 } *params32 = args;
1460 struct wglQueryCurrentRendererStringWINE_params params =
1462 .teb = get_teb64(params32->teb),
1463 .attribute = params32->attribute,
1465 NTSTATUS status;
1467 if ((status = ext_wglQueryCurrentRendererStringWINE( &params ))) return status;
1469 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1471 params32->ret = strlen( params.ret ) + 1;
1472 return STATUS_BUFFER_TOO_SMALL;
1475 return STATUS_SUCCESS;
1478 NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
1480 struct
1482 PTR32 teb;
1483 PTR32 dc;
1484 GLint renderer;
1485 GLenum attribute;
1486 PTR32 ret;
1487 } *params32 = args;
1488 struct wglQueryRendererStringWINE_params params =
1490 .teb = get_teb64(params32->teb),
1491 .dc = ULongToPtr(params32->dc),
1492 .renderer = params32->renderer,
1493 .attribute = params32->attribute,
1495 NTSTATUS status;
1497 if ((status = ext_wglQueryRendererStringWINE( &params ))) return status;
1499 if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
1501 params32->ret = strlen( params.ret ) + 1;
1502 return STATUS_BUFFER_TOO_SMALL;
1505 return STATUS_SUCCESS;
1508 NTSTATUS wow64_ext_glClientWaitSync( void *args )
1510 struct wgl_handle *handle;
1511 struct
1513 PTR32 teb;
1514 PTR32 sync;
1515 GLbitfield flags;
1516 GLuint64 timeout;
1517 GLenum ret;
1518 } *params32 = args;
1519 NTSTATUS status;
1521 pthread_mutex_lock( &wgl_lock );
1523 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1524 status = STATUS_INVALID_HANDLE;
1525 else
1527 struct glClientWaitSync_params params =
1529 .teb = get_teb64(params32->teb),
1530 .sync = (GLsync)handle->u.context,
1531 .flags = params32->flags,
1532 .timeout = params32->timeout,
1534 status = ext_glClientWaitSync( &params );
1535 params32->ret = params.ret;
1538 pthread_mutex_unlock( &wgl_lock );
1539 return status;
1542 NTSTATUS wow64_ext_glDeleteSync( void *args )
1544 struct wgl_handle *handle;
1545 struct
1547 PTR32 teb;
1548 PTR32 sync;
1549 } *params32 = args;
1550 NTSTATUS status;
1552 pthread_mutex_lock( &wgl_lock );
1554 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1555 status = STATUS_INVALID_HANDLE;
1556 else
1558 struct glDeleteSync_params params =
1560 .teb = get_teb64(params32->teb),
1561 .sync = (GLsync)handle->u.context,
1563 status = ext_glDeleteSync( &params );
1564 free_handle_ptr( handle );
1567 pthread_mutex_unlock( &wgl_lock );
1568 return status;
1571 NTSTATUS wow64_ext_glFenceSync( void *args )
1573 struct
1575 PTR32 teb;
1576 GLenum condition;
1577 GLbitfield flags;
1578 PTR32 ret;
1579 } *params32 = args;
1580 struct glFenceSync_params params =
1582 .teb = get_teb64(params32->teb),
1583 .condition = params32->condition,
1584 .flags = params32->flags,
1586 NTSTATUS status;
1588 if ((status = ext_glFenceSync( &params ))) return status;
1590 pthread_mutex_lock( &wgl_lock );
1592 if (!(params32->ret = (UINT_PTR)alloc_handle( HANDLE_GLSYNC, NULL, params.ret )))
1594 struct glDeleteSync_params delete_params =
1596 .teb = params.teb,
1597 .sync = params.ret,
1600 ext_glDeleteSync( &delete_params );
1601 status = STATUS_NO_MEMORY;
1604 pthread_mutex_unlock( &wgl_lock );
1605 return status;
1608 NTSTATUS wow64_ext_glGetSynciv( void *args )
1610 struct wgl_handle *handle;
1611 struct
1613 PTR32 teb;
1614 PTR32 sync;
1615 GLenum pname;
1616 GLsizei count;
1617 PTR32 length;
1618 PTR32 values;
1619 } *params32 = args;
1620 NTSTATUS status;
1622 pthread_mutex_lock( &wgl_lock );
1624 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1625 status = STATUS_INVALID_HANDLE;
1626 else
1628 struct glGetSynciv_params params =
1630 .teb = get_teb64(params32->teb),
1631 .sync = (GLsync)handle->u.context,
1632 .pname = params32->pname,
1633 .count = params32->count,
1634 .length = ULongToPtr(params32->length),
1635 .values = ULongToPtr(params32->values),
1637 status = ext_glGetSynciv( &params );
1640 pthread_mutex_unlock( &wgl_lock );
1641 return status;
1644 NTSTATUS wow64_ext_glIsSync( void *args )
1646 struct wgl_handle *handle;
1647 struct
1649 PTR32 teb;
1650 PTR32 sync;
1651 GLboolean ret;
1652 } *params32 = args;
1653 NTSTATUS status;
1655 pthread_mutex_lock( &wgl_lock );
1657 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1658 status = STATUS_INVALID_HANDLE;
1659 else
1661 struct glIsSync_params params =
1663 .teb = get_teb64(params32->teb),
1664 .sync = (GLsync)handle->u.context,
1666 status = ext_glIsSync( &params );
1667 params32->ret = params.ret;
1670 pthread_mutex_unlock( &wgl_lock );
1671 return status;
1674 NTSTATUS wow64_ext_glWaitSync( void *args )
1676 struct wgl_handle *handle;
1677 struct
1679 PTR32 teb;
1680 PTR32 sync;
1681 GLbitfield flags;
1682 GLuint64 timeout;
1683 } *params32 = args;
1684 NTSTATUS status;
1686 pthread_mutex_lock( &wgl_lock );
1688 if (!(handle = get_handle_ptr( ULongToPtr(params32->sync), HANDLE_GLSYNC )))
1689 status = STATUS_INVALID_HANDLE;
1690 else
1692 struct glWaitSync_params params =
1694 .teb = get_teb64(params32->teb),
1695 .sync = (GLsync)handle->u.context,
1696 .flags = params32->flags,
1697 .timeout = params32->timeout,
1699 status = ext_glWaitSync( &params );
1702 pthread_mutex_unlock( &wgl_lock );
1703 return status;
1706 static GLint get_buffer_param( TEB *teb, GLenum target, GLenum param )
1708 const struct opengl_funcs *funcs = teb->glTable;
1709 typeof(*funcs->ext.p_glGetBufferParameteriv) *func;
1710 GLint size = 0;
1711 if (!(func = funcs->ext.p_glGetBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferParameteriv" );
1712 if (func) func( target, param, &size );
1713 return size;
1716 static void *get_buffer_pointer( TEB *teb, GLenum target )
1718 const struct opengl_funcs *funcs = teb->glTable;
1719 typeof(*funcs->ext.p_glGetBufferPointerv) *func;
1720 void *ptr = NULL;
1721 if (!(func = funcs->ext.p_glGetBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetBufferPointerv" );
1722 if (func) func( target, GL_BUFFER_MAP_POINTER, &ptr );
1723 return ptr;
1726 static GLint get_named_buffer_param( TEB *teb, GLint buffer, GLenum param )
1728 const struct opengl_funcs *funcs = teb->glTable;
1729 typeof(*funcs->ext.p_glGetNamedBufferParameteriv) *func;
1730 GLint size = 0;
1731 if (!(func = funcs->ext.p_glGetNamedBufferParameteriv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferParameteriv" );
1732 if (func) func( buffer, param, &size );
1733 return size;
1736 static void *get_named_buffer_pointer( TEB *teb, GLint buffer )
1738 const struct opengl_funcs *funcs = teb->glTable;
1739 typeof(*funcs->ext.p_glGetNamedBufferPointerv) *func;
1740 void *ptr = NULL;
1741 if (!(func = funcs->ext.p_glGetNamedBufferPointerv)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glGetNamedBufferPointerv" );
1742 if (func) func( buffer, GL_BUFFER_MAP_POINTER, &ptr );
1743 return ptr;
1746 static void unmap_buffer( TEB *teb, GLenum target )
1748 const struct opengl_funcs *funcs = teb->glTable;
1749 typeof(*funcs->ext.p_glUnmapBuffer) *func;
1750 if (!(func = funcs->ext.p_glUnmapBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapBuffer" );
1751 if (func) func( target );
1754 static void unmap_named_buffer( TEB *teb, GLint buffer )
1756 const struct opengl_funcs *funcs = teb->glTable;
1757 typeof(*funcs->ext.p_glUnmapNamedBuffer) *func;
1758 if (!(func = funcs->ext.p_glUnmapNamedBuffer)) func = (void *)funcs->wgl.p_wglGetProcAddress( "glUnmapNamedBuffer" );
1759 if (func) func( buffer );
1762 static NTSTATUS wow64_map_buffer( TEB *teb, GLint buffer, GLenum target, void *ptr, SIZE_T size,
1763 GLbitfield access, PTR32 *ret )
1765 if (*ret) /* wow64 pointer provided, map buffer to it */
1767 if (access & GL_MAP_READ_BIT)
1769 TRACE( "Copying %#zx from buffer at %p to wow64 buffer %p\n", size, ptr, UlongToPtr(*ret) );
1770 memcpy( UlongToPtr(*ret), ptr, size );
1773 /* save the wow64 pointer in the buffer data, we'll overwrite it on unmap */
1774 *(PTR32 *)ptr = (UINT_PTR)*ret;
1775 return STATUS_SUCCESS;
1778 if (ULongToPtr(*ret = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1779 if (access & GL_MAP_PERSISTENT_BIT)
1781 FIXME( "GL_MAP_PERSISTENT_BIT not supported!\n" );
1782 return STATUS_NOT_SUPPORTED;
1785 if (!size) size = buffer ? get_named_buffer_param( teb, buffer, GL_BUFFER_SIZE ) : get_buffer_param( teb, target, GL_BUFFER_SIZE );
1786 if ((PTR32)size != size) return STATUS_NO_MEMORY; /* overflow */
1787 if (size < sizeof(PTR32))
1789 FIXME( "Buffer too small for metadata!\n" );
1790 return STATUS_BUFFER_TOO_SMALL;
1793 *ret = size;
1794 return STATUS_INVALID_ADDRESS;
1797 static NTSTATUS wow64_unmap_buffer( void *ptr, SIZE_T size, GLbitfield access )
1799 void *wow_ptr;
1801 if (ULongToPtr(PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1803 wow_ptr = UlongToPtr(*(PTR32 *)ptr);
1804 if (access & GL_MAP_WRITE_BIT)
1806 TRACE( "Copying %#zx from wow64 buffer %p to buffer %p\n", size, wow_ptr, ptr );
1807 memcpy( ptr, wow_ptr, size );
1810 return STATUS_INVALID_ADDRESS;
1813 static NTSTATUS wow64_gl_get_buffer_pointer_v( void *args, NTSTATUS (*get_buffer_pointer_v64)(void *) )
1815 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1816 struct
1818 PTR32 teb;
1819 GLenum target;
1820 GLenum pname;
1821 PTR32 params;
1822 } *params32 = args;
1823 struct glGetBufferPointerv_params params =
1825 .teb = get_teb64(params32->teb),
1826 .target = params32->target,
1827 .pname = params32->pname,
1828 .params = (void **)&ptr,
1830 PTR32 *wow_ptr = UlongToPtr(params32->params);
1831 NTSTATUS status;
1833 if ((status = get_buffer_pointer_v64( &params ))) return status;
1834 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1835 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1836 *wow_ptr = ptr[0];
1837 return STATUS_SUCCESS;
1840 NTSTATUS wow64_ext_glGetBufferPointerv( void *args )
1842 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointerv );
1845 NTSTATUS wow64_ext_glGetBufferPointervARB( void *args )
1847 return wow64_gl_get_buffer_pointer_v( args, ext_glGetBufferPointervARB );
1850 static NTSTATUS wow64_gl_get_named_buffer_pointer_v( void *args, NTSTATUS (*gl_get_named_buffer_pointer_v64)(void *) )
1852 PTR32 *ptr; /* pointer to the buffer data, where we saved the wow64 pointer */
1853 struct
1855 PTR32 teb;
1856 GLuint buffer;
1857 GLenum pname;
1858 PTR32 params;
1859 } *params32 = args;
1860 struct glGetNamedBufferPointerv_params params =
1862 .teb = get_teb64(params32->teb),
1863 .buffer = params32->buffer,
1864 .pname = params32->pname,
1865 .params = (void **)&ptr,
1867 PTR32 *wow_ptr = UlongToPtr(params32->params);
1868 NTSTATUS status;
1870 if ((status = gl_get_named_buffer_pointer_v64( &params ))) return status;
1871 if (params.pname != GL_BUFFER_MAP_POINTER) return STATUS_NOT_IMPLEMENTED;
1872 if (ULongToPtr(*wow_ptr = PtrToUlong(ptr)) == ptr) return STATUS_SUCCESS; /* we're lucky */
1873 *wow_ptr = ptr[0];
1874 return STATUS_SUCCESS;
1877 NTSTATUS wow64_ext_glGetNamedBufferPointerv( void *args )
1879 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointerv );
1882 NTSTATUS wow64_ext_glGetNamedBufferPointervEXT( void *args )
1884 return wow64_gl_get_named_buffer_pointer_v( args, ext_glGetNamedBufferPointervEXT );
1887 static NTSTATUS wow64_gl_map_buffer( void *args, NTSTATUS (*gl_map_buffer64)(void *) )
1889 struct
1891 PTR32 teb;
1892 GLenum target;
1893 GLenum access;
1894 PTR32 ret;
1895 } *params32 = args;
1896 struct glMapBuffer_params params =
1898 .teb = get_teb64(params32->teb),
1899 .target = params32->target,
1900 .access = params32->access,
1902 NTSTATUS status;
1904 /* already mapped, we're being called again with a wow64 pointer */
1905 if (params32->ret) params.ret = get_buffer_pointer( params.teb, params.target );
1906 else if ((status = gl_map_buffer64( &params ))) return status;
1908 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, 0, params.access, &params32->ret );
1909 if (!status || status == STATUS_INVALID_ADDRESS) return status;
1911 unmap_buffer( params.teb, params.target );
1912 return status;
1915 NTSTATUS wow64_ext_glMapBuffer( void *args )
1917 return wow64_gl_map_buffer( args, ext_glMapBuffer );
1920 NTSTATUS wow64_ext_glMapBufferARB( void *args )
1922 return wow64_gl_map_buffer( args, ext_glMapBufferARB );
1925 NTSTATUS wow64_ext_glMapBufferRange( void *args )
1927 struct
1929 PTR32 teb;
1930 GLenum target;
1931 PTR32 offset;
1932 PTR32 length;
1933 GLbitfield access;
1934 PTR32 ret;
1935 } *params32 = args;
1936 struct glMapBufferRange_params params =
1938 .teb = get_teb64(params32->teb),
1939 .target = params32->target,
1940 .offset = (GLintptr)ULongToPtr(params32->offset),
1941 .length = (GLsizeiptr)ULongToPtr(params32->length),
1942 .access = params32->access,
1944 NTSTATUS status;
1946 /* already mapped, we're being called again with a wow64 pointer */
1947 if (params32->ret) params.ret = (char *)get_buffer_pointer( params.teb, params.target );
1948 else if ((status = ext_glMapBufferRange( &params ))) return status;
1950 status = wow64_map_buffer( params.teb, 0, params.target, params.ret, params.length, params.access, &params32->ret );
1951 if (!status || status == STATUS_INVALID_ADDRESS) return status;
1953 unmap_buffer( params.teb, params.target );
1954 return status;
1957 static NTSTATUS wow64_gl_map_named_buffer( void *args, NTSTATUS (*gl_map_named_buffer64)(void *) )
1959 struct
1961 PTR32 teb;
1962 GLuint buffer;
1963 GLenum access;
1964 PTR32 ret;
1965 } *params32 = args;
1966 struct glMapNamedBuffer_params params =
1968 .teb = get_teb64(params32->teb),
1969 .buffer = params32->buffer,
1970 .access = params32->access,
1972 NTSTATUS status;
1974 /* already mapped, we're being called again with a wow64 pointer */
1975 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
1976 else if ((status = gl_map_named_buffer64( &params ))) return status;
1978 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, 0, params.access, &params32->ret );
1979 if (!status || status == STATUS_INVALID_ADDRESS) return status;
1981 unmap_named_buffer( params.teb, params.buffer );
1982 return status;
1985 NTSTATUS wow64_ext_glMapNamedBuffer( void *args )
1987 return wow64_gl_map_named_buffer( args, ext_glMapNamedBuffer );
1990 NTSTATUS wow64_ext_glMapNamedBufferEXT( void *args )
1992 return wow64_gl_map_named_buffer( args, ext_glMapNamedBufferEXT );
1995 static NTSTATUS wow64_gl_map_named_buffer_range( void *args, NTSTATUS (*gl_map_named_buffer_range64)(void *) )
1997 struct
1999 PTR32 teb;
2000 GLuint buffer;
2001 PTR32 offset;
2002 PTR32 length;
2003 GLbitfield access;
2004 PTR32 ret;
2005 } *params32 = args;
2006 struct glMapNamedBufferRange_params params =
2008 .teb = get_teb64(params32->teb),
2009 .buffer = params32->buffer,
2010 .offset = (GLintptr)ULongToPtr(params32->offset),
2011 .length = (GLsizeiptr)ULongToPtr(params32->length),
2012 .access = params32->access,
2014 NTSTATUS status;
2016 /* already mapped, we're being called again with a wow64 pointer */
2017 if (params32->ret) params.ret = get_named_buffer_pointer( params.teb, params.buffer );
2018 else if ((status = gl_map_named_buffer_range64( &params ))) return status;
2020 status = wow64_map_buffer( params.teb, params.buffer, 0, params.ret, params.length, params.access, &params32->ret );
2021 if (!status || status == STATUS_INVALID_ADDRESS) return status;
2023 unmap_named_buffer( params.teb, params.buffer );
2024 return status;
2027 NTSTATUS wow64_ext_glMapNamedBufferRange( void *args )
2029 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRange );
2032 NTSTATUS wow64_ext_glMapNamedBufferRangeEXT( void *args )
2034 return wow64_gl_map_named_buffer_range( args, ext_glMapNamedBufferRangeEXT );
2037 static NTSTATUS wow64_gl_unmap_buffer( void *args, NTSTATUS (*gl_unmap_buffer64)(void *) )
2039 PTR32 *ptr;
2040 struct
2042 PTR32 teb;
2043 GLenum target;
2044 GLboolean ret;
2045 } *params32 = args;
2046 struct glUnmapBuffer_params params =
2048 .teb = get_teb64(params32->teb),
2049 .target = params32->target,
2050 .ret = TRUE,
2052 NTSTATUS status;
2054 if (!(ptr = get_buffer_pointer( params.teb, params.target ))) return STATUS_SUCCESS;
2056 status = wow64_unmap_buffer( ptr, get_buffer_param( params.teb, params.target, GL_BUFFER_MAP_LENGTH ),
2057 get_buffer_param( params.teb, params.target, GL_BUFFER_ACCESS_FLAGS ) );
2058 gl_unmap_buffer64( &params );
2059 params32->ret = params.ret;
2061 return status;
2064 NTSTATUS wow64_ext_glUnmapBuffer( void *args )
2066 return wow64_gl_unmap_buffer( args, ext_glUnmapBuffer );
2069 NTSTATUS wow64_ext_glUnmapBufferARB( void *args )
2071 return wow64_gl_unmap_buffer( args, ext_glUnmapBufferARB );
2074 static NTSTATUS wow64_gl_unmap_named_buffer( void *args, NTSTATUS (*gl_unmap_named_buffer64)(void *) )
2076 PTR32 *ptr;
2077 struct
2079 PTR32 teb;
2080 GLint buffer;
2081 GLboolean ret;
2082 } *params32 = args;
2083 struct glUnmapNamedBuffer_params params =
2085 .teb = get_teb64(params32->teb),
2086 .buffer = params32->buffer,
2087 .ret = TRUE,
2089 NTSTATUS status;
2091 if (!(ptr = get_named_buffer_pointer( params.teb, params.buffer ))) return STATUS_SUCCESS;
2093 status = wow64_unmap_buffer( ptr, get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_MAP_LENGTH ),
2094 get_named_buffer_param( params.teb, params.buffer, GL_BUFFER_ACCESS_FLAGS ) );
2095 gl_unmap_named_buffer64( &params );
2096 params32->ret = params.ret;
2098 return status;
2101 NTSTATUS wow64_ext_glUnmapNamedBuffer( void *args )
2103 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBuffer );
2106 NTSTATUS wow64_ext_glUnmapNamedBufferEXT( void *args )
2108 return wow64_gl_unmap_named_buffer( args, ext_glUnmapNamedBufferEXT );
2111 NTSTATUS wow64_thread_attach( void *args )
2113 return thread_attach( get_teb64( (ULONG_PTR)args ));
2116 NTSTATUS wow64_process_detach( void *args )
2118 NTSTATUS status;
2120 if ((status = process_detach( NULL ))) return status;
2122 free( wow64_strings );
2123 wow64_strings = NULL;
2124 wow64_strings_count = 0;
2126 return STATUS_SUCCESS;
2129 #endif