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
33 #define WIN32_NO_STATUS
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 */
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,
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 */
72 struct opengl_funcs
*funcs
;
75 struct opengl_context
*context
; /* for HANDLE_CONTEXT */
76 struct wgl_pbuffer
*pbuffer
; /* for HANDLE_PBUFFER */
77 struct wgl_handle
*next
; /* for free handles */
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
);
112 static HANDLE
alloc_handle( enum wgl_handle_type type
, struct opengl_funcs
*funcs
, void *user_ptr
)
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
++];
125 ptr
->u
.context
= user_ptr
;
126 handle
= next_handle( ptr
, type
);
128 else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY
);
132 static void free_handle_ptr( struct wgl_handle
*ptr
)
134 ptr
->handle
|= 0xffff;
135 ptr
->u
.next
= next_free
;
140 /* check if the extension is present in the list */
141 static BOOL
has_extension( const char *list
, const char *ext
, size_t len
)
145 while (*list
== ' ') list
++;
146 if (!strncmp( list
, ext
, len
) && (!list
[len
] || list
[len
] == ' ')) return TRUE
;
147 list
= strchr( list
, ' ' );
152 static GLubyte
*filter_extensions_list( const char *extensions
, const char *disabled
)
157 p
= str
= malloc( strlen( extensions
) + 2 );
158 if (!str
) return NULL
;
160 TRACE( "GL_EXTENSIONS:\n" );
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
;
179 TRACE( "-- %s (disabled by config)\n", p
);
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
;
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
);
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
)
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
;
249 attr
.Length
= sizeof(attr
);
250 attr
.RootDirectory
= root
;
251 attr
.ObjectName
= &nameW
;
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
)
267 DWORD_PTR sid_data
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(DWORD_PTR
)];
268 DWORD i
, len
= sizeof(sid_data
);
271 if (NtQueryInformationToken( GetCurrentThreadEffectiveToken(), TokenUser
, sid_data
, len
, &len
))
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
;
308 /* @@ Wine registry key: HKCU\Software\Wine\OpenGL */
309 if ((hkey
= open_hkcu_key( "Software\\Wine\\OpenGL" )))
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
);
321 str
= strdup( buffer
);
327 if (InterlockedCompareExchangePointer( (void **)&disabled
, str
, NULL
)) free( str
);
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
;
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
;
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_' */
376 ERR( "No OpenGL version found!\n" );
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
++;
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
;
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
;
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
;
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
);
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" );
505 if (!(found
= bsearch( &entry
, extension_registry
, extension_registry_size
, sizeof(entry
), registry_entry_cmp
)))
507 WARN( "Function %s unknown\n", name
);
511 func_ptr
= (const void **)&funcs
->ext
+ (found
- extension_registry
);
514 void *driver_func
= funcs
->wgl
.p_wglGetProcAddress( name
);
516 if (!is_extension_supported( teb
, found
->extension
))
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
);
537 if (driver_func
== NULL
)
539 WARN( "Function %s not supported by driver\n", name
);
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
;
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
);
566 static HGLRC
wrap_wglCreateContext( HDC hdc
)
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
);
584 static BOOL
wrap_wglMakeCurrent( TEB
*teb
, HDC hdc
, HGLRC hglrc
)
587 DWORD tid
= HandleToULong(teb
->ClientId
.UniqueThread
);
588 struct wgl_handle
*ptr
, *prev
= get_current_context_ptr( teb
);
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
);
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
;
608 RtlSetLastWin32Error( ERROR_BUSY
);
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
;
621 RtlSetLastWin32Error( ERROR_INVALID_HANDLE
);
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
);
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
);
647 static BOOL
wrap_wglShareLists( HGLRC hglrcSrc
, HGLRC hglrcDst
)
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
);
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
)
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
);
678 RtlSetLastWin32Error( ERROR_DC_NOT_FOUND
);
681 if (!funcs
->ext
.p_wglCreateContextAttribsARB
) return 0;
682 if (share
&& !(share_ptr
= get_handle_ptr( share
, HANDLE_CONTEXT
)))
684 RtlSetLastWin32Error( ERROR_INVALID_OPERATION
);
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
;
697 if (attribs
[0] == WGL_CONTEXT_MAJOR_VERSION_ARB
)
699 if (attribs
[1] >= 3) type
= HANDLE_CONTEXT_V3
;
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
);
715 static HPBUFFERARB
wrap_wglCreatePbufferARB( HDC hdc
, int format
, int width
, int height
, const int *attribs
)
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
);
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
);
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
)
748 DWORD tid
= HandleToULong(teb
->ClientId
.UniqueThread
);
749 struct wgl_handle
*ptr
, *prev
= get_current_context_ptr( teb
);
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
));
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
;
770 RtlSetLastWin32Error( ERROR_BUSY
);
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
;
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
=
820 .severity
= severity
,
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
, ¶ms
, 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
)
1058 teb
->glTable
= &null_opengl_funcs
;
1059 return STATUS_SUCCESS
;
1062 NTSTATUS
process_detach( void *args
)
1064 return STATUS_SUCCESS
;
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
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
)
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
;
1128 strcpy( UlongToPtr(wow64_str
), (char *)str
);
1129 wow64_strings
[i
].wow64_str
= wow64_str
;
1132 pthread_mutex_unlock( &wgl_lock
);
1137 static inline void update_teb32_context( TEB
*teb
)
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
)
1157 struct wglCreateContext_params params
=
1159 .teb
= get_teb64(params32
->teb
),
1160 .hDc
= ULongToPtr(params32
->hDc
),
1163 if ((status
= wgl_wglCreateContext( ¶ms
))) return status
;
1164 params32
->ret
= (UINT_PTR
)params
.ret
;
1165 return STATUS_SUCCESS
;
1168 NTSTATUS
wow64_ext_wglCreateContextAttribsARB( void *args
)
1174 PTR32 hShareContext
;
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
),
1186 if ((status
= ext_wglCreateContextAttribsARB( ¶ms
))) return status
;
1187 params32
->ret
= (UINT_PTR
)params
.ret
;
1188 return STATUS_SUCCESS
;
1191 NTSTATUS
wow64_ext_wglCreatePbufferARB( void *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
),
1213 if ((status
= ext_wglCreatePbufferARB( ¶ms
))) return status
;
1214 params32
->ret
= (UINT_PTR
)params
.ret
;
1215 return STATUS_SUCCESS
;
1218 NTSTATUS
wow64_wgl_wglDeleteContext( void *args
)
1226 struct wglDeleteContext_params params
=
1228 .teb
= get_teb64(params32
->teb
),
1229 .oldContext
= ULongToPtr(params32
->oldContext
),
1232 if (!(status
= wgl_wglDeleteContext( ¶ms
))) update_teb32_context( params
.teb
);
1233 params32
->ret
= params
.ret
;
1237 NTSTATUS
wow64_wgl_wglMakeCurrent( void *args
)
1246 struct wglMakeCurrent_params params
=
1248 .teb
= get_teb64(params32
->teb
),
1249 .hDc
= ULongToPtr(params32
->hDc
),
1250 .newContext
= ULongToPtr(params32
->newContext
),
1253 if (!(status
= wgl_wglMakeCurrent( ¶ms
))) update_teb32_context( params
.teb
);
1254 params32
->ret
= params
.ret
;
1258 NTSTATUS
wow64_ext_wglMakeContextCurrentARB( void *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
),
1276 if (!(status
= ext_wglMakeContextCurrentARB( ¶ms
))) update_teb32_context( params
.teb
);
1277 params32
->ret
= params
.ret
;
1281 NTSTATUS
wow64_ext_wglGetPbufferDCARB( void *args
)
1289 struct wglGetPbufferDCARB_params params
=
1291 .teb
= get_teb64(params32
->teb
),
1292 .hPbuffer
= (HPBUFFERARB
)ULongToPtr(params32
->hPbuffer
),
1295 if ((status
= ext_wglGetPbufferDCARB( ¶ms
))) return status
;
1296 params32
->ret
= (UINT_PTR
)params
.ret
;
1297 return STATUS_SUCCESS
;
1300 NTSTATUS
wow64_wgl_wglGetProcAddress( void *args
)
1308 struct wglGetProcAddress_params params
=
1310 .teb
= get_teb64(params32
->teb
),
1311 .lpszProc
= ULongToPtr(params32
->lpszProc
),
1314 if ((status
= wgl_wglGetProcAddress( ¶ms
))) return status
;
1315 params32
->ret
= (UINT_PTR
)params
.ret
;
1316 return STATUS_SUCCESS
;
1319 NTSTATUS
wow64_gl_glGetString( void *args
)
1327 struct glGetString_params params
=
1329 .teb
= get_teb64(params32
->teb
),
1330 .name
= params32
->name
,
1334 if ((status
= gl_glGetString( ¶ms
))) 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
)
1354 struct glGetStringi_params params
=
1356 .teb
= get_teb64(params32
->teb
),
1357 .name
= params32
->name
,
1358 .index
= params32
->index
,
1362 if ((status
= ext_glGetStringi( ¶ms
))) 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
)
1380 GLbitfield fontStyle
;
1381 GLuint pathParameterTemplate
;
1383 GLuint baseAndCount
[2];
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]},
1397 if ((status
= ext_glPathGlyphIndexRangeNV( ¶ms
))) return status
;
1398 params32
->ret
= params
.ret
;
1402 NTSTATUS
wow64_ext_wglGetExtensionsStringARB( void *args
)
1410 struct wglGetExtensionsStringARB_params params
=
1412 .teb
= get_teb64(params32
->teb
),
1413 .hdc
= ULongToPtr(params32
->hdc
),
1417 if ((status
= ext_wglGetExtensionsStringARB( ¶ms
))) 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
)
1435 struct wglGetExtensionsStringEXT_params params
=
1437 .teb
= get_teb64(params32
->teb
),
1441 if ((status
= ext_wglGetExtensionsStringEXT( ¶ms
))) 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
)
1460 struct wglQueryCurrentRendererStringWINE_params params
=
1462 .teb
= get_teb64(params32
->teb
),
1463 .attribute
= params32
->attribute
,
1467 if ((status
= ext_wglQueryCurrentRendererStringWINE( ¶ms
))) 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
)
1488 struct wglQueryRendererStringWINE_params params
=
1490 .teb
= get_teb64(params32
->teb
),
1491 .dc
= ULongToPtr(params32
->dc
),
1492 .renderer
= params32
->renderer
,
1493 .attribute
= params32
->attribute
,
1497 if ((status
= ext_wglQueryRendererStringWINE( ¶ms
))) 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
;
1521 pthread_mutex_lock( &wgl_lock
);
1523 if (!(handle
= get_handle_ptr( ULongToPtr(params32
->sync
), HANDLE_GLSYNC
)))
1524 status
= STATUS_INVALID_HANDLE
;
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( ¶ms
);
1535 params32
->ret
= params
.ret
;
1538 pthread_mutex_unlock( &wgl_lock
);
1542 NTSTATUS
wow64_ext_glDeleteSync( void *args
)
1544 struct wgl_handle
*handle
;
1552 pthread_mutex_lock( &wgl_lock
);
1554 if (!(handle
= get_handle_ptr( ULongToPtr(params32
->sync
), HANDLE_GLSYNC
)))
1555 status
= STATUS_INVALID_HANDLE
;
1558 struct glDeleteSync_params params
=
1560 .teb
= get_teb64(params32
->teb
),
1561 .sync
= (GLsync
)handle
->u
.context
,
1563 status
= ext_glDeleteSync( ¶ms
);
1564 free_handle_ptr( handle
);
1567 pthread_mutex_unlock( &wgl_lock
);
1571 NTSTATUS
wow64_ext_glFenceSync( void *args
)
1580 struct glFenceSync_params params
=
1582 .teb
= get_teb64(params32
->teb
),
1583 .condition
= params32
->condition
,
1584 .flags
= params32
->flags
,
1588 if ((status
= ext_glFenceSync( ¶ms
))) 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
=
1600 ext_glDeleteSync( &delete_params
);
1601 status
= STATUS_NO_MEMORY
;
1604 pthread_mutex_unlock( &wgl_lock
);
1608 NTSTATUS
wow64_ext_glGetSynciv( void *args
)
1610 struct wgl_handle
*handle
;
1622 pthread_mutex_lock( &wgl_lock
);
1624 if (!(handle
= get_handle_ptr( ULongToPtr(params32
->sync
), HANDLE_GLSYNC
)))
1625 status
= STATUS_INVALID_HANDLE
;
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( ¶ms
);
1640 pthread_mutex_unlock( &wgl_lock
);
1644 NTSTATUS
wow64_ext_glIsSync( void *args
)
1646 struct wgl_handle
*handle
;
1655 pthread_mutex_lock( &wgl_lock
);
1657 if (!(handle
= get_handle_ptr( ULongToPtr(params32
->sync
), HANDLE_GLSYNC
)))
1658 status
= STATUS_INVALID_HANDLE
;
1661 struct glIsSync_params params
=
1663 .teb
= get_teb64(params32
->teb
),
1664 .sync
= (GLsync
)handle
->u
.context
,
1666 status
= ext_glIsSync( ¶ms
);
1667 params32
->ret
= params
.ret
;
1670 pthread_mutex_unlock( &wgl_lock
);
1674 NTSTATUS
wow64_ext_glWaitSync( void *args
)
1676 struct wgl_handle
*handle
;
1686 pthread_mutex_lock( &wgl_lock
);
1688 if (!(handle
= get_handle_ptr( ULongToPtr(params32
->sync
), HANDLE_GLSYNC
)))
1689 status
= STATUS_INVALID_HANDLE
;
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( ¶ms
);
1702 pthread_mutex_unlock( &wgl_lock
);
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
;
1711 if (!(func
= funcs
->ext
.p_glGetBufferParameteriv
)) func
= (void *)funcs
->wgl
.p_wglGetProcAddress( "glGetBufferParameteriv" );
1712 if (func
) func( target
, param
, &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
;
1721 if (!(func
= funcs
->ext
.p_glGetBufferPointerv
)) func
= (void *)funcs
->wgl
.p_wglGetProcAddress( "glGetBufferPointerv" );
1722 if (func
) func( target
, GL_BUFFER_MAP_POINTER
, &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
;
1731 if (!(func
= funcs
->ext
.p_glGetNamedBufferParameteriv
)) func
= (void *)funcs
->wgl
.p_wglGetProcAddress( "glGetNamedBufferParameteriv" );
1732 if (func
) func( buffer
, param
, &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
;
1741 if (!(func
= funcs
->ext
.p_glGetNamedBufferPointerv
)) func
= (void *)funcs
->wgl
.p_wglGetProcAddress( "glGetNamedBufferPointerv" );
1742 if (func
) func( buffer
, GL_BUFFER_MAP_POINTER
, &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
;
1794 return STATUS_INVALID_ADDRESS
;
1797 static NTSTATUS
wow64_unmap_buffer( void *ptr
, SIZE_T size
, GLbitfield access
)
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 */
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
);
1833 if ((status
= get_buffer_pointer_v64( ¶ms
))) 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 */
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 */
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
);
1870 if ((status
= gl_get_named_buffer_pointer_v64( ¶ms
))) 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 */
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 *) )
1896 struct glMapBuffer_params params
=
1898 .teb
= get_teb64(params32
->teb
),
1899 .target
= params32
->target
,
1900 .access
= params32
->access
,
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( ¶ms
))) return status
;
1908 status
= wow64_map_buffer( params
.teb
, 0, params
.target
, params
.ret
, 0, params
.access
, ¶ms32
->ret
);
1909 if (!status
|| status
== STATUS_INVALID_ADDRESS
) return status
;
1911 unmap_buffer( params
.teb
, params
.target
);
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
)
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
,
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( ¶ms
))) return status
;
1950 status
= wow64_map_buffer( params
.teb
, 0, params
.target
, params
.ret
, params
.length
, params
.access
, ¶ms32
->ret
);
1951 if (!status
|| status
== STATUS_INVALID_ADDRESS
) return status
;
1953 unmap_buffer( params
.teb
, params
.target
);
1957 static NTSTATUS
wow64_gl_map_named_buffer( void *args
, NTSTATUS (*gl_map_named_buffer64
)(void *) )
1966 struct glMapNamedBuffer_params params
=
1968 .teb
= get_teb64(params32
->teb
),
1969 .buffer
= params32
->buffer
,
1970 .access
= params32
->access
,
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( ¶ms
))) return status
;
1978 status
= wow64_map_buffer( params
.teb
, params
.buffer
, 0, params
.ret
, 0, params
.access
, ¶ms32
->ret
);
1979 if (!status
|| status
== STATUS_INVALID_ADDRESS
) return status
;
1981 unmap_named_buffer( params
.teb
, params
.buffer
);
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 *) )
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
,
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( ¶ms
))) return status
;
2020 status
= wow64_map_buffer( params
.teb
, params
.buffer
, 0, params
.ret
, params
.length
, params
.access
, ¶ms32
->ret
);
2021 if (!status
|| status
== STATUS_INVALID_ADDRESS
) return status
;
2023 unmap_named_buffer( params
.teb
, params
.buffer
);
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 *) )
2046 struct glUnmapBuffer_params params
=
2048 .teb
= get_teb64(params32
->teb
),
2049 .target
= params32
->target
,
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( ¶ms
);
2059 params32
->ret
= params
.ret
;
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 *) )
2083 struct glUnmapNamedBuffer_params params
=
2085 .teb
= get_teb64(params32
->teb
),
2086 .buffer
= params32
->buffer
,
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( ¶ms
);
2096 params32
->ret
= params
.ret
;
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
)
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
;