opengl32: Move the wgl functions to the main OpenGL function table.
[wine] / dlls / opengl32 / wgl.c
1 /* Window-specific OpenGL functions implementation.
2  *
3  * Copyright (c) 1999 Lionel Ulmer
4  * Copyright (c) 2005 Raphael Junqueira
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #include "wingdi.h"
33 #include "winternl.h"
34 #include "winnt.h"
35
36 #include "opengl_ext.h"
37 #ifdef HAVE_GL_GLU_H
38 #undef far
39 #undef near
40 #include <GL/glu.h>
41 #endif
42 #include "wine/gdi_driver.h"
43 #include "wine/wgl_driver.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
48 WINE_DECLARE_DEBUG_CHANNEL(opengl);
49
50 #ifdef SONAME_LIBGLU
51 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
52 MAKE_FUNCPTR(gluNewTess)
53 MAKE_FUNCPTR(gluDeleteTess)
54 MAKE_FUNCPTR(gluTessBeginContour)
55 MAKE_FUNCPTR(gluTessBeginPolygon)
56 MAKE_FUNCPTR(gluTessCallback)
57 MAKE_FUNCPTR(gluTessEndContour)
58 MAKE_FUNCPTR(gluTessEndPolygon)
59 MAKE_FUNCPTR(gluTessVertex)
60 #undef MAKE_FUNCPTR
61 #endif /* SONAME_LIBGLU */
62
63 static HMODULE opengl32_handle;
64 static void* libglu_handle = NULL;
65
66 extern struct opengl_funcs null_opengl_funcs;
67
68 const GLubyte * WINAPI wine_glGetString( GLenum name );
69
70 /* internal GDI functions */
71 extern INT WINAPI GdiDescribePixelFormat( HDC hdc, INT fmt, UINT size, PIXELFORMATDESCRIPTOR *pfd );
72 extern BOOL WINAPI GdiSetPixelFormat( HDC hdc, INT fmt, const PIXELFORMATDESCRIPTOR *pfd );
73 extern BOOL WINAPI GdiSwapBuffers( HDC hdc );
74
75 /* handle management */
76
77 #define MAX_WGL_HANDLES 1024
78
79 struct wgl_handle
80 {
81     UINT                 handle;
82     DWORD                tid;
83     struct wgl_context  *context;
84     struct opengl_funcs *funcs;
85 };
86
87 static struct wgl_handle wgl_handles[MAX_WGL_HANDLES];
88 static struct wgl_handle *next_free;
89 static unsigned int handle_count;
90
91 static CRITICAL_SECTION wgl_section;
92 static CRITICAL_SECTION_DEBUG critsect_debug =
93 {
94     0, 0, &wgl_section,
95     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
96       0, 0, { (DWORD_PTR)(__FILE__ ": wgl_section") }
97 };
98 static CRITICAL_SECTION wgl_section = { &critsect_debug, -1, 0, 0, 0, 0 };
99
100 static inline struct opengl_funcs *get_dc_funcs( HDC hdc )
101 {
102     struct opengl_funcs *funcs = __wine_get_wgl_driver( hdc, WINE_WGL_DRIVER_VERSION );
103     if (funcs == (void *)-1) funcs = &null_opengl_funcs;
104     return funcs;
105 }
106
107 static inline HGLRC next_handle( struct wgl_handle *ptr )
108 {
109     WORD generation = HIWORD( ptr->handle ) + 1;
110     if (!generation) generation++;
111     ptr->handle = MAKELONG( ptr - wgl_handles, generation );
112     return ULongToHandle( ptr->handle );
113 }
114
115 /* the current handle is assumed valid and doesn't need locking */
116 static inline struct wgl_handle *get_current_handle_ptr(void)
117 {
118     if (!NtCurrentTeb()->glCurrentRC) return NULL;
119     return &wgl_handles[LOWORD(NtCurrentTeb()->glCurrentRC)];
120 }
121
122 static struct wgl_handle *get_handle_ptr( HGLRC handle )
123 {
124     unsigned int index = LOWORD( handle );
125
126     EnterCriticalSection( &wgl_section );
127     if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle)
128         return &wgl_handles[index];
129
130     LeaveCriticalSection( &wgl_section );
131     SetLastError( ERROR_INVALID_HANDLE );
132     return NULL;
133 }
134
135 static void release_handle_ptr( struct wgl_handle *ptr )
136 {
137     if (ptr) LeaveCriticalSection( &wgl_section );
138 }
139
140 static HGLRC alloc_handle( struct wgl_context *context, struct opengl_funcs *funcs )
141 {
142     HGLRC handle = 0;
143     struct wgl_handle *ptr = NULL;
144
145     EnterCriticalSection( &wgl_section );
146     if ((ptr = next_free))
147         next_free = (struct wgl_handle *)next_free->context;
148     else if (handle_count < MAX_WGL_HANDLES)
149         ptr = &wgl_handles[handle_count++];
150
151     if (ptr)
152     {
153         ptr->context = context;
154         ptr->funcs = funcs;
155         handle = next_handle( ptr );
156     }
157     else SetLastError( ERROR_NOT_ENOUGH_MEMORY );
158     LeaveCriticalSection( &wgl_section );
159     return handle;
160 }
161
162 static void free_handle_ptr( struct wgl_handle *ptr )
163 {
164     ptr->handle |= 0xffff;
165     ptr->context = (struct wgl_context *)next_free;
166     ptr->funcs = NULL;
167     next_free = ptr;
168     LeaveCriticalSection( &wgl_section );
169 }
170
171 /***********************************************************************
172  *               wglSetPixelFormat(OPENGL32.@)
173  */
174 BOOL WINAPI wglSetPixelFormat( HDC hdc, INT iPixelFormat,
175                                const PIXELFORMATDESCRIPTOR *ppfd)
176 {
177     return GdiSetPixelFormat(hdc, iPixelFormat, ppfd);
178 }
179
180 /***********************************************************************
181  *              wglCopyContext (OPENGL32.@)
182  */
183 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
184 {
185     struct wgl_handle *src, *dst;
186     BOOL ret = FALSE;
187
188     if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE;
189     if ((dst = get_handle_ptr( hglrcDst )))
190     {
191         if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE );
192         else ret = src->funcs->wgl.p_wglCopyContext( src->context, dst->context, mask );
193     }
194     release_handle_ptr( dst );
195     release_handle_ptr( src );
196     return ret;
197 }
198
199 /***********************************************************************
200  *              wglDeleteContext (OPENGL32.@)
201  */
202 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
203 {
204     struct wgl_handle *ptr = get_handle_ptr( hglrc );
205
206     if (!ptr) return FALSE;
207
208     if (ptr->tid && ptr->tid != GetCurrentThreadId())
209     {
210         SetLastError( ERROR_BUSY );
211         release_handle_ptr( ptr );
212         return FALSE;
213     }
214     if (hglrc == NtCurrentTeb()->glCurrentRC) wglMakeCurrent( 0, 0 );
215     ptr->funcs->wgl.p_wglDeleteContext( ptr->context );
216     free_handle_ptr( ptr );
217     return TRUE;
218 }
219
220 /***********************************************************************
221  *              wglMakeCurrent (OPENGL32.@)
222  */
223 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
224 {
225     BOOL ret = TRUE;
226     struct wgl_handle *ptr, *prev = get_current_handle_ptr();
227
228     if (hglrc)
229     {
230         if (!(ptr = get_handle_ptr( hglrc ))) return FALSE;
231         if (!ptr->tid || ptr->tid == GetCurrentThreadId())
232         {
233             ret = ptr->funcs->wgl.p_wglMakeCurrent( hdc, ptr->context );
234             if (ret)
235             {
236                 if (prev) prev->tid = 0;
237                 ptr->tid = GetCurrentThreadId();
238                 NtCurrentTeb()->glCurrentRC = hglrc;
239                 NtCurrentTeb()->glTable = ptr->funcs;
240             }
241         }
242         else
243         {
244             SetLastError( ERROR_BUSY );
245             ret = FALSE;
246         }
247         release_handle_ptr( ptr );
248     }
249     else if (prev)
250     {
251         if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
252         prev->tid = 0;
253         NtCurrentTeb()->glCurrentRC = 0;
254         NtCurrentTeb()->glTable = &null_opengl_funcs;
255     }
256     else if (!hdc)
257     {
258         SetLastError( ERROR_INVALID_HANDLE );
259         ret = FALSE;
260     }
261     return ret;
262 }
263
264 /***********************************************************************
265  *              wglCreateContextAttribsARB  (wrapper for the extension function returned by the driver)
266  */
267 static HGLRC WINAPI wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *attribs )
268 {
269     HGLRC ret = 0;
270     struct wgl_context *context;
271     struct wgl_handle *share_ptr = NULL;
272     struct opengl_funcs *funcs = get_dc_funcs( hdc );
273
274     if (!funcs) return 0;
275     if (share && !(share_ptr = get_handle_ptr( share ))) return 0;
276     if ((context = funcs->wgl.p_wglCreateContextAttribsARB( hdc, share_ptr ? share_ptr->context : NULL,
277                                                             attribs )))
278     {
279         ret = alloc_handle( context, funcs );
280         if (!ret) funcs->wgl.p_wglDeleteContext( context );
281     }
282     release_handle_ptr( share_ptr );
283     return ret;
284
285 }
286
287 /***********************************************************************
288  *              wglMakeContextCurrentARB  (wrapper for the extension function returned by the driver)
289  */
290 static BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC hglrc )
291 {
292     BOOL ret = TRUE;
293     struct wgl_handle *ptr, *prev = get_current_handle_ptr();
294
295     if (hglrc)
296     {
297         if (!(ptr = get_handle_ptr( hglrc ))) return FALSE;
298         if (!ptr->tid || ptr->tid == GetCurrentThreadId())
299         {
300             ret = ptr->funcs->wgl.p_wglMakeContextCurrentARB( draw_hdc, read_hdc, ptr->context );
301             if (ret)
302             {
303                 if (prev) prev->tid = 0;
304                 ptr->tid = GetCurrentThreadId();
305                 NtCurrentTeb()->glCurrentRC = hglrc;
306                 NtCurrentTeb()->glTable = ptr->funcs;
307             }
308         }
309         else
310         {
311             SetLastError( ERROR_BUSY );
312             ret = FALSE;
313         }
314         release_handle_ptr( ptr );
315     }
316     else if (prev)
317     {
318         if (!prev->funcs->wgl.p_wglMakeCurrent( 0, NULL )) return FALSE;
319         prev->tid = 0;
320         NtCurrentTeb()->glCurrentRC = 0;
321         NtCurrentTeb()->glTable = &null_opengl_funcs;
322     }
323     return ret;
324 }
325
326 /***********************************************************************
327  *              wglShareLists (OPENGL32.@)
328  */
329 BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst)
330 {
331     BOOL ret = FALSE;
332     struct wgl_handle *src, *dst;
333
334     if (!(src = get_handle_ptr( hglrcSrc ))) return FALSE;
335     if ((dst = get_handle_ptr( hglrcDst )))
336     {
337         if (src->funcs != dst->funcs) SetLastError( ERROR_INVALID_HANDLE );
338         else ret = src->funcs->wgl.p_wglShareLists( src->context, dst->context );
339     }
340     release_handle_ptr( dst );
341     release_handle_ptr( src );
342     return ret;
343 }
344
345 /***********************************************************************
346  *              wglGetCurrentDC (OPENGL32.@)
347  */
348 HDC WINAPI wglGetCurrentDC(void)
349 {
350     struct wgl_handle *context = get_current_handle_ptr();
351     if (!context) return 0;
352     return context->funcs->wgl.p_wglGetCurrentDC( context->context );
353 }
354
355 /***********************************************************************
356  *              wglCreateContext (OPENGL32.@)
357  */
358 HGLRC WINAPI wglCreateContext(HDC hdc)
359 {
360     HGLRC ret = 0;
361     struct wgl_context *context;
362     struct opengl_funcs *funcs = get_dc_funcs( hdc );
363
364     if (!funcs) return 0;
365     if (!(context = funcs->wgl.p_wglCreateContext( hdc ))) return 0;
366     ret = alloc_handle( context, funcs );
367     if (!ret) funcs->wgl.p_wglDeleteContext( context );
368     return ret;
369 }
370
371 /***********************************************************************
372  *              wglGetCurrentContext (OPENGL32.@)
373  */
374 HGLRC WINAPI wglGetCurrentContext(void)
375 {
376     return NtCurrentTeb()->glCurrentRC;
377 }
378
379 /***********************************************************************
380  *              wglChoosePixelFormat (OPENGL32.@)
381  */
382 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
383 {
384     PIXELFORMATDESCRIPTOR format, best;
385     int i, count, best_format;
386     int bestDBuffer = -1, bestStereo = -1;
387
388     TRACE_(wgl)( "%p %p: size %u version %u flags %u type %u color %u %u,%u,%u,%u "
389                  "accum %u depth %u stencil %u aux %u\n",
390                  hdc, ppfd, ppfd->nSize, ppfd->nVersion, ppfd->dwFlags, ppfd->iPixelType,
391                  ppfd->cColorBits, ppfd->cRedBits, ppfd->cGreenBits, ppfd->cBlueBits, ppfd->cAlphaBits,
392                  ppfd->cAccumBits, ppfd->cDepthBits, ppfd->cStencilBits, ppfd->cAuxBuffers );
393
394     count = GdiDescribePixelFormat( hdc, 0, 0, NULL );
395     if (!count) return 0;
396
397     best_format = 0;
398     best.dwFlags = 0;
399     best.cAlphaBits = -1;
400     best.cColorBits = -1;
401     best.cDepthBits = -1;
402     best.cStencilBits = -1;
403     best.cAuxBuffers = -1;
404
405     for (i = 1; i <= count; i++)
406     {
407         if (!GdiDescribePixelFormat( hdc, i, sizeof(format), &format )) continue;
408
409         if (ppfd->iPixelType != format.iPixelType)
410         {
411             TRACE( "pixel type mismatch for iPixelFormat=%d\n", i );
412             continue;
413         }
414
415         /* only use bitmap capable for formats for bitmap rendering */
416         if( (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) != (format.dwFlags & PFD_DRAW_TO_BITMAP))
417         {
418             TRACE( "PFD_DRAW_TO_BITMAP mismatch for iPixelFormat=%d\n", i );
419             continue;
420         }
421
422         /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE
423          * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats
424          * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match
425          * formats without the given flag set.
426          * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo)
427          * has indicated that a format without stereo is returned when stereo is unavailable.
428          * So in case PFD_STEREO is set, formats that support it should have priority above formats
429          * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored.
430          *
431          * To summarize the following is most likely the correct behavior:
432          * stereo not set -> prefer non-stereo formats, but also accept stereo formats
433          * stereo set -> prefer stereo formats, but also accept non-stereo formats
434          * stereo don't care -> it doesn't matter whether we get stereo or not
435          *
436          * In Wine we will treat non-stereo the same way as don't care because it makes
437          * format selection even more complicated and second drivers with Stereo advertise
438          * each format twice anyway.
439          */
440
441         /* Doublebuffer, see the comments above */
442         if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE))
443         {
444             if (((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) &&
445                 ((format.dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER)))
446                 goto found;
447
448             if (bestDBuffer != -1 && (format.dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) continue;
449         }
450
451         /* Stereo, see the comments above. */
452         if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE))
453         {
454             if (((ppfd->dwFlags & PFD_STEREO) != bestStereo) &&
455                 ((format.dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO)))
456                 goto found;
457
458             if (bestStereo != -1 && (format.dwFlags & PFD_STEREO) != bestStereo) continue;
459         }
460
461         /* Below we will do a number of checks to select the 'best' pixelformat.
462          * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers.
463          * The code works by trying to match the most important options as close as possible.
464          * When a reasonable format is found, we will try to match more options.
465          * It appears (see the opengl32 test) that Windows opengl drivers ignore options
466          * like cColorBits, cAlphaBits and friends if they are set to 0, so they are considered
467          * as DONTCARE. At least Serious Sam TSE relies on this behavior. */
468
469         if (ppfd->cColorBits)
470         {
471             if (((ppfd->cColorBits > best.cColorBits) && (format.cColorBits > best.cColorBits)) ||
472                 ((format.cColorBits >= ppfd->cColorBits) && (format.cColorBits < best.cColorBits)))
473                 goto found;
474
475             if (best.cColorBits != format.cColorBits)  /* Do further checks if the format is compatible */
476             {
477                 TRACE( "color mismatch for iPixelFormat=%d\n", i );
478                 continue;
479             }
480         }
481         if (ppfd->cAlphaBits)
482         {
483             if (((ppfd->cAlphaBits > best.cAlphaBits) && (format.cAlphaBits > best.cAlphaBits)) ||
484                 ((format.cAlphaBits >= ppfd->cAlphaBits) && (format.cAlphaBits < best.cAlphaBits)))
485                 goto found;
486
487             if (best.cAlphaBits != format.cAlphaBits)
488             {
489                 TRACE( "alpha mismatch for iPixelFormat=%d\n", i );
490                 continue;
491             }
492         }
493         if (ppfd->cDepthBits)
494         {
495             if (((ppfd->cDepthBits > best.cDepthBits) && (format.cDepthBits > best.cDepthBits)) ||
496                 ((format.cDepthBits >= ppfd->cDepthBits) && (format.cDepthBits < best.cDepthBits)))
497                 goto found;
498
499             if (best.cDepthBits != format.cDepthBits)
500             {
501                 TRACE( "depth mismatch for iPixelFormat=%d\n", i );
502                 continue;
503             }
504         }
505         if (ppfd->cStencilBits)
506         {
507             if (((ppfd->cStencilBits > best.cStencilBits) && (format.cStencilBits > best.cStencilBits)) ||
508                 ((format.cStencilBits >= ppfd->cStencilBits) && (format.cStencilBits < best.cStencilBits)))
509                 goto found;
510
511             if (best.cStencilBits != format.cStencilBits)
512             {
513                 TRACE( "stencil mismatch for iPixelFormat=%d\n", i );
514                 continue;
515             }
516         }
517         if (ppfd->cAuxBuffers)
518         {
519             if (((ppfd->cAuxBuffers > best.cAuxBuffers) && (format.cAuxBuffers > best.cAuxBuffers)) ||
520                 ((format.cAuxBuffers >= ppfd->cAuxBuffers) && (format.cAuxBuffers < best.cAuxBuffers)))
521                 goto found;
522
523             if (best.cAuxBuffers != format.cAuxBuffers)
524             {
525                 TRACE( "aux mismatch for iPixelFormat=%d\n", i );
526                 continue;
527             }
528         }
529         continue;
530
531     found:
532         best_format = i;
533         best = format;
534         bestDBuffer = format.dwFlags & PFD_DOUBLEBUFFER;
535         bestStereo = format.dwFlags & PFD_STEREO;
536     }
537
538     TRACE( "returning %u\n", best_format );
539     return best_format;
540 }
541
542 /***********************************************************************
543  *              wglDescribePixelFormat (OPENGL32.@)
544  */
545 INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
546                                 LPPIXELFORMATDESCRIPTOR ppfd)
547 {
548   return GdiDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
549 }
550
551 /***********************************************************************
552  *              wglGetPixelFormat (OPENGL32.@)
553  */
554 INT WINAPI wglGetPixelFormat(HDC hdc)
555 {
556     struct opengl_funcs *funcs = get_dc_funcs( hdc );
557     if (!funcs) return 0;
558     return funcs->wgl.p_wglGetPixelFormat( hdc );
559 }
560
561 /***********************************************************************
562  *              wglCreateLayerContext (OPENGL32.@)
563  */
564 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
565                                    int iLayerPlane) {
566   TRACE("(%p,%d)\n", hdc, iLayerPlane);
567
568   if (iLayerPlane == 0) {
569       return wglCreateContext(hdc);
570   }
571   FIXME("no handler for layer %d\n", iLayerPlane);
572
573   return NULL;
574 }
575
576 /***********************************************************************
577  *              wglDescribeLayerPlane (OPENGL32.@)
578  */
579 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
580                                   int iPixelFormat,
581                                   int iLayerPlane,
582                                   UINT nBytes,
583                                   LPLAYERPLANEDESCRIPTOR plpd) {
584   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
585
586   return FALSE;
587 }
588
589 /***********************************************************************
590  *              wglGetLayerPaletteEntries (OPENGL32.@)
591  */
592 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
593                                      int iLayerPlane,
594                                      int iStart,
595                                      int cEntries,
596                                      const COLORREF *pcr) {
597   FIXME("(): stub!\n");
598
599   return 0;
600 }
601
602 /* check if the extension is present in the list */
603 static BOOL has_extension( const char *list, const char *ext )
604 {
605     size_t len = strlen( ext );
606
607     while (list)
608     {
609         while (*list == ' ') list++;
610         if (!strncmp( list, ext, len ) && (!list[len] || list[len] == ' ')) return TRUE;
611         list = strchr( list, ' ' );
612     }
613     return FALSE;
614 }
615
616 static int compar(const void *elt_a, const void *elt_b) {
617   return strcmp(((const OpenGL_extension *) elt_a)->name,
618                 ((const OpenGL_extension *) elt_b)->name);
619 }
620
621 /* Check if a GL extension is supported */
622 static BOOL is_extension_supported(const char* extension)
623 {
624     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
625     const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
626
627     TRACE("Checking for extension '%s'\n", extension);
628
629     if(!gl_ext_string) {
630         ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
631         return FALSE;
632     }
633
634     /* We use the GetProcAddress function from the display driver to retrieve function pointers
635      * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
636      * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
637      * require the function to return NULL when an extension isn't found. For this reason we check
638      * if the OpenGL extension required for the function we are looking up is supported. */
639
640     /* Check if the extension is part of the GL extension string to see if it is supported. */
641     if (has_extension(gl_ext_string, extension))
642         return TRUE;
643
644     /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
645      * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
646      * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
647      * Check if we are searching for a core GL function */
648     if(strncmp(extension, "GL_VERSION_", 11) == 0)
649     {
650         const GLubyte *gl_version = funcs->gl.p_glGetString(GL_VERSION);
651         const char *version = extension + 11; /* Move past 'GL_VERSION_' */
652
653         if(!gl_version) {
654             ERR("No OpenGL version found!\n");
655             return FALSE;
656         }
657
658         /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
659          * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
660         if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
661             return TRUE;
662         }
663         WARN("The function requires OpenGL version '%c.%c' while your drivers only provide '%c.%c'\n", version[0], version[2], gl_version[0], gl_version[2]);
664     }
665
666     return FALSE;
667 }
668
669 static const OpenGL_extension wgl_extensions[] =
670 {
671     { "wglCreateContextAttribsARB", "WGL_ARB_create_context", wglCreateContextAttribsARB },
672     { "wglMakeContextCurrentARB", "WGL_ARB_make_current_read", wglMakeContextCurrentARB },
673 };
674
675 /***********************************************************************
676  *              wglGetProcAddress (OPENGL32.@)
677  */
678 PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
679   void *local_func;
680   OpenGL_extension  ext;
681   const OpenGL_extension *ext_ret;
682   struct wgl_handle *context = get_current_handle_ptr();
683
684   TRACE("(%s)\n", lpszProc);
685
686   if (lpszProc == NULL)
687     return NULL;
688
689   /* Without an active context opengl32 doesn't know to what
690    * driver it has to dispatch wglGetProcAddress.
691    */
692   if (!context)
693   {
694     WARN("No active WGL context found\n");
695     return NULL;
696   }
697
698   /* Search in the thunks to find the real name of the extension */
699   ext.name = lpszProc;
700   ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
701                     sizeof(OpenGL_extension), compar);
702
703   /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
704   if (ext_ret == NULL) {
705     /* If the function name starts with a 'w', it is a WGL extension */
706     if(lpszProc[0] == 'w')
707     {
708         local_func = context->funcs->wgl.p_wglGetProcAddress( lpszProc );
709         if (local_func == (void *)1)  /* special function that needs a wrapper */
710         {
711             ext_ret = bsearch( &ext, wgl_extensions, sizeof(wgl_extensions)/sizeof(wgl_extensions[0]),
712                                sizeof(OpenGL_extension), compar );
713             if (ext_ret) return ext_ret->func;
714
715             FIXME( "wrapper missing for %s\n", lpszProc );
716             return NULL;
717         }
718         return local_func;
719     }
720
721     /* We are dealing with an unknown GL extension */
722     WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
723     return NULL;
724   } else { /* We are looking for an OpenGL extension */
725
726     /* Check if the GL extension required by the function is available */
727     if(!is_extension_supported(ext_ret->extension)) {
728         WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
729     }
730
731     local_func = context->funcs->wgl.p_wglGetProcAddress( ext_ret->name );
732
733     /* After that, look at the extensions defined in the Linux OpenGL library */
734     if (local_func == NULL) {
735       char buf[256];
736       void *ret = NULL;
737
738       /* Remove the last 3 letters (EXT, ARB, ...).
739
740          I know that some extensions have more than 3 letters (MESA, NV,
741          INTEL, ...), but this is only a stop-gap measure to fix buggy
742          OpenGL drivers (moreover, it is only useful for old 1.0 apps
743          that query the glBindTextureEXT extension).
744       */
745       memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
746       buf[strlen(ext_ret->name) - 3] = '\0';
747       TRACE("Extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
748
749       ret = GetProcAddress(opengl32_handle, buf);
750       if (ret != NULL) {
751         TRACE("Found function in main OpenGL library (%p)!\n", ret);
752       } else {
753         WARN("Did not find function %s (%s) in your OpenGL library!\n", lpszProc, ext_ret->name);
754       }
755
756       return ret;
757     } else {
758       struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
759       *((void **)&funcs->ext + (ext_ret - extension_registry)) = local_func;
760       TRACE("returning function (%p)\n", ext_ret->func);
761       return ext_ret->func;
762     }
763   }
764 }
765
766 /***********************************************************************
767  *              wglRealizeLayerPalette (OPENGL32.@)
768  */
769 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
770                                    int iLayerPlane,
771                                    BOOL bRealize) {
772   FIXME("()\n");
773
774   return FALSE;
775 }
776
777 /***********************************************************************
778  *              wglSetLayerPaletteEntries (OPENGL32.@)
779  */
780 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
781                                      int iLayerPlane,
782                                      int iStart,
783                                      int cEntries,
784                                      const COLORREF *pcr) {
785   FIXME("(): stub!\n");
786
787   return 0;
788 }
789
790 /***********************************************************************
791  *              wglSwapLayerBuffers (OPENGL32.@)
792  */
793 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
794                                 UINT fuPlanes) {
795   TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
796
797   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
798     if (!GdiSwapBuffers(hdc)) return FALSE;
799     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
800   }
801
802   if (fuPlanes) {
803     WARN("Following layers unhandled: %08x\n", fuPlanes);
804   }
805
806   return TRUE;
807 }
808
809 /***********************************************************************
810  *              wglUseFontBitmaps_common
811  */
812 static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD listBase, BOOL unicode )
813 {
814     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
815      GLYPHMETRICS gm;
816      unsigned int glyph, size = 0;
817      void *bitmap = NULL, *gl_bitmap = NULL;
818      int org_alignment;
819      BOOL ret = TRUE;
820
821      funcs->gl.p_glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
822      funcs->gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
823
824      for (glyph = first; glyph < first + count; glyph++) {
825          static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
826          unsigned int needed_size, height, width, width_int;
827
828          if (unicode)
829              needed_size = GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
830          else
831              needed_size = GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
832
833          TRACE("Glyph: %3d / List: %d size %d\n", glyph, listBase, needed_size);
834          if (needed_size == GDI_ERROR) {
835              ret = FALSE;
836              break;
837          }
838
839          if (needed_size > size) {
840              size = needed_size;
841              HeapFree(GetProcessHeap(), 0, bitmap);
842              HeapFree(GetProcessHeap(), 0, gl_bitmap);
843              bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
844              gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
845          }
846          if (unicode)
847              ret = (GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
848          else
849              ret = (GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
850          if (!ret) break;
851
852          if (TRACE_ON(wgl)) {
853              unsigned int bitmask;
854              unsigned char *bitmap_ = bitmap;
855
856              TRACE("  - bbox: %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
857              TRACE("  - origin: (%d, %d)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
858              TRACE("  - increment: %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
859              if (needed_size != 0) {
860                  TRACE("  - bitmap:\n");
861                  for (height = 0; height < gm.gmBlackBoxY; height++) {
862                      TRACE("      ");
863                      for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
864                          if (bitmask == 0) {
865                              bitmap_ += 1;
866                              bitmask = 0x80;
867                          }
868                          if (*bitmap_ & bitmask)
869                              TRACE("*");
870                          else
871                              TRACE(" ");
872                      }
873                      bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
874                      TRACE("\n");
875                  }
876              }
877          }
878
879          /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
880          * glyph for it to be drawn properly.
881          */
882          if (needed_size != 0) {
883              width_int = (gm.gmBlackBoxX + 31) / 32;
884              for (height = 0; height < gm.gmBlackBoxY; height++) {
885                  for (width = 0; width < width_int; width++) {
886                      ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
887                      ((int *) bitmap)[height * width_int + width];
888                  }
889              }
890          }
891
892          funcs->gl.p_glNewList(listBase++, GL_COMPILE);
893          if (needed_size != 0) {
894              funcs->gl.p_glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
895                      0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y,
896                      gm.gmCellIncX, gm.gmCellIncY,
897                      gl_bitmap);
898          } else {
899              /* This is the case of 'empty' glyphs like the space character */
900              funcs->gl.p_glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
901          }
902          funcs->gl.p_glEndList();
903      }
904
905      funcs->gl.p_glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
906      HeapFree(GetProcessHeap(), 0, bitmap);
907      HeapFree(GetProcessHeap(), 0, gl_bitmap);
908      return ret;
909 }
910
911 /***********************************************************************
912  *              wglUseFontBitmapsA (OPENGL32.@)
913  */
914 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
915 {
916     return wglUseFontBitmaps_common( hdc, first, count, listBase, FALSE );
917 }
918
919 /***********************************************************************
920  *              wglUseFontBitmapsW (OPENGL32.@)
921  */
922 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
923 {
924     return wglUseFontBitmaps_common( hdc, first, count, listBase, TRUE );
925 }
926
927 #ifdef SONAME_LIBGLU
928
929 static void *load_libglu(void)
930 {
931     static int already_loaded;
932     void *handle;
933
934     if (already_loaded) return libglu_handle;
935     already_loaded = 1;
936
937     TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
938     handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
939     if (!handle)
940     {
941         WARN("Failed to load %s\n", SONAME_LIBGLU);
942         return NULL;
943     }
944
945 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
946 LOAD_FUNCPTR(gluNewTess)
947 LOAD_FUNCPTR(gluDeleteTess)
948 LOAD_FUNCPTR(gluTessBeginContour)
949 LOAD_FUNCPTR(gluTessBeginPolygon)
950 LOAD_FUNCPTR(gluTessCallback)
951 LOAD_FUNCPTR(gluTessEndContour)
952 LOAD_FUNCPTR(gluTessEndPolygon)
953 LOAD_FUNCPTR(gluTessVertex)
954 #undef LOAD_FUNCPTR
955     libglu_handle = handle;
956     return handle;
957
958 sym_not_found:
959     WARN("Unable to load function ptrs from libGLU\n");
960     /* Close the library as we won't use it */
961     wine_dlclose(handle, NULL, 0);
962     return NULL;
963 }
964
965 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
966 {
967     vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;  
968     vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;  
969     vertex[2] = 0.0;
970 }
971
972 static void tess_callback_vertex(GLvoid *vertex)
973 {
974     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
975     GLdouble *dbl = vertex;
976     TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
977     funcs->gl.p_glVertex3dv(vertex);
978 }
979
980 static void tess_callback_begin(GLenum which)
981 {
982     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
983     TRACE("%d\n", which);
984     funcs->gl.p_glBegin(which);
985 }
986
987 static void tess_callback_end(void)
988 {
989     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
990     TRACE("\n");
991     funcs->gl.p_glEnd();
992 }
993
994 /***********************************************************************
995  *              wglUseFontOutlines_common
996  */
997 static BOOL wglUseFontOutlines_common(HDC hdc,
998                                       DWORD first,
999                                       DWORD count,
1000                                       DWORD listBase,
1001                                       FLOAT deviation,
1002                                       FLOAT extrusion,
1003                                       int format,
1004                                       LPGLYPHMETRICSFLOAT lpgmf,
1005                                       BOOL unicode)
1006 {
1007     const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
1008     UINT glyph;
1009     const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
1010     GLUtesselator *tess;
1011     LOGFONTW lf;
1012     HFONT old_font, unscaled_font;
1013     UINT em_size = 1024;
1014     RECT rc;
1015
1016     TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
1017           listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
1018
1019     if (!load_libglu())
1020     {
1021         ERR("libGLU is required for this function but isn't loaded\n");
1022         return FALSE;
1023     }
1024
1025     tess = pgluNewTess();
1026     if(!tess) return FALSE;
1027     pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
1028     pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
1029     pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
1030
1031     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1032     rc.left = rc.right = rc.bottom = 0;
1033     rc.top = em_size;
1034     DPtoLP(hdc, (POINT*)&rc, 2);
1035     lf.lfHeight = -abs(rc.top - rc.bottom);
1036     lf.lfOrientation = lf.lfEscapement = 0;
1037     unscaled_font = CreateFontIndirectW(&lf);
1038     old_font = SelectObject(hdc, unscaled_font);
1039
1040     for (glyph = first; glyph < first + count; glyph++)
1041     {
1042         DWORD needed;
1043         GLYPHMETRICS gm;
1044         BYTE *buf;
1045         TTPOLYGONHEADER *pph;
1046         TTPOLYCURVE *ppc;
1047         GLdouble *vertices;
1048
1049         if(unicode)
1050             needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
1051         else
1052             needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
1053
1054         if(needed == GDI_ERROR)
1055             goto error;
1056
1057         buf = HeapAlloc(GetProcessHeap(), 0, needed);
1058         vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
1059
1060         if(unicode)
1061             GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
1062         else
1063             GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
1064
1065         TRACE("glyph %d\n", glyph);
1066
1067         if(lpgmf)
1068         {
1069             lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
1070             lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
1071             lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
1072             lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
1073             lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
1074             lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
1075
1076             TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
1077                   lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); 
1078             lpgmf++;
1079         }
1080
1081         funcs->gl.p_glNewList(listBase++, GL_COMPILE);
1082         pgluTessBeginPolygon(tess, NULL);
1083
1084         pph = (TTPOLYGONHEADER*)buf;
1085         while((BYTE*)pph < buf + needed)
1086         {
1087             TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
1088
1089             pgluTessBeginContour(tess);
1090
1091             fixed_to_double(pph->pfxStart, em_size, vertices);
1092             pgluTessVertex(tess, vertices, vertices);
1093             vertices += 3;
1094
1095             ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
1096             while((char*)ppc < (char*)pph + pph->cb)
1097             {
1098                 int i;
1099
1100                 switch(ppc->wType) {
1101                 case TT_PRIM_LINE:
1102                     for(i = 0; i < ppc->cpfx; i++)
1103                     {
1104                         TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
1105                         fixed_to_double(ppc->apfx[i], em_size, vertices); 
1106                         pgluTessVertex(tess, vertices, vertices);
1107                         vertices += 3;
1108                     }
1109                     break;
1110
1111                 case TT_PRIM_QSPLINE:
1112                     for(i = 0; i < ppc->cpfx/2; i++)
1113                     {
1114                         /* FIXME: just connecting the control points for now */
1115                         TRACE("\t\tcurve  %d,%d %d,%d\n",
1116                               ppc->apfx[i * 2].x.value,     ppc->apfx[i * 3].y.value,
1117                               ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
1118                         fixed_to_double(ppc->apfx[i * 2], em_size, vertices); 
1119                         pgluTessVertex(tess, vertices, vertices);
1120                         vertices += 3;
1121                         fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); 
1122                         pgluTessVertex(tess, vertices, vertices);
1123                         vertices += 3;
1124                     }
1125                     break;
1126                 default:
1127                     ERR("\t\tcurve type = %d\n", ppc->wType);
1128                     pgluTessEndContour(tess);
1129                     goto error_in_list;
1130                 }
1131
1132                 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
1133                                      (ppc->cpfx - 1) * sizeof(POINTFX));
1134             }
1135             pgluTessEndContour(tess);
1136             pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
1137         }
1138
1139 error_in_list:
1140         pgluTessEndPolygon(tess);
1141         funcs->gl.p_glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
1142         funcs->gl.p_glEndList();
1143         HeapFree(GetProcessHeap(), 0, buf);
1144         HeapFree(GetProcessHeap(), 0, vertices);
1145     }
1146
1147  error:
1148     DeleteObject(SelectObject(hdc, old_font));
1149     pgluDeleteTess(tess);
1150     return TRUE;
1151
1152 }
1153
1154 #else /* SONAME_LIBGLU */
1155
1156 static BOOL wglUseFontOutlines_common(HDC hdc,
1157                                       DWORD first,
1158                                       DWORD count,
1159                                       DWORD listBase,
1160                                       FLOAT deviation,
1161                                       FLOAT extrusion,
1162                                       int format,
1163                                       LPGLYPHMETRICSFLOAT lpgmf,
1164                                       BOOL unicode)
1165 {
1166     FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
1167     return FALSE;
1168 }
1169
1170 #endif /* SONAME_LIBGLU */
1171
1172 /***********************************************************************
1173  *              wglUseFontOutlinesA (OPENGL32.@)
1174  */
1175 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
1176                                 DWORD first,
1177                                 DWORD count,
1178                                 DWORD listBase,
1179                                 FLOAT deviation,
1180                                 FLOAT extrusion,
1181                                 int format,
1182                                 LPGLYPHMETRICSFLOAT lpgmf)
1183 {
1184     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
1185 }
1186
1187 /***********************************************************************
1188  *              wglUseFontOutlinesW (OPENGL32.@)
1189  */
1190 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
1191                                 DWORD first,
1192                                 DWORD count,
1193                                 DWORD listBase,
1194                                 FLOAT deviation,
1195                                 FLOAT extrusion,
1196                                 int format,
1197                                 LPGLYPHMETRICSFLOAT lpgmf)
1198 {
1199     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
1200 }
1201
1202 /***********************************************************************
1203  *              glDebugEntry (OPENGL32.@)
1204  */
1205 GLint WINAPI wine_glDebugEntry( GLint unknown1, GLint unknown2 )
1206 {
1207     return 0;
1208 }
1209
1210 /* build the extension string by filtering out the disabled extensions */
1211 static char *build_gl_extensions( const char *extensions )
1212 {
1213     char *p, *str, *disabled = NULL;
1214     const char *end;
1215     HKEY hkey;
1216
1217     TRACE( "GL_EXTENSIONS:\n" );
1218
1219     if (!extensions) extensions = "";
1220
1221     /* @@ Wine registry key: HKCU\Software\Wine\OpenGL */
1222     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey ))
1223     {
1224         DWORD size, ret = RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size );
1225         if (!ret && (disabled = HeapAlloc( GetProcessHeap(), 0, size )))
1226             ret = RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (BYTE *)disabled, &size );
1227         RegCloseKey( hkey );
1228         if (ret) *disabled = 0;
1229     }
1230
1231     if ((str = HeapAlloc( GetProcessHeap(), 0, strlen(extensions) + 2 )))
1232     {
1233         p = str;
1234         for (;;)
1235         {
1236             while (*extensions == ' ') extensions++;
1237             if (!*extensions) break;
1238             if (!(end = strchr( extensions, ' ' ))) end = extensions + strlen( extensions );
1239             memcpy( p, extensions, end - extensions );
1240             p[end - extensions] = 0;
1241             if (!has_extension( disabled, p ))
1242             {
1243                 TRACE("++ %s\n", p );
1244                 p += end - extensions;
1245                 *p++ = ' ';
1246             }
1247             else TRACE("-- %s (disabled by config)\n", p );
1248             extensions = end;
1249         }
1250         *p = 0;
1251     }
1252     HeapFree( GetProcessHeap(), 0, disabled );
1253     return str;
1254 }
1255
1256 /***********************************************************************
1257  *              glGetString (OPENGL32.@)
1258  */
1259 const GLubyte * WINAPI wine_glGetString( GLenum name )
1260 {
1261   const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
1262   static const GLubyte *gl_extensions;
1263
1264   /* this is for buggy nvidia driver, crashing if called from a different
1265      thread with no context */
1266   if(wglGetCurrentContext() == NULL)
1267     return NULL;
1268
1269   if (name != GL_EXTENSIONS) return funcs->gl.p_glGetString(name);
1270
1271   if (!gl_extensions)
1272   {
1273       const char *orig_ext = (const char *)funcs->gl.p_glGetString(GL_EXTENSIONS);
1274       char *new_ext = build_gl_extensions( orig_ext );
1275       if (InterlockedCompareExchangePointer( (void **)&gl_extensions, new_ext, NULL ))
1276           HeapFree( GetProcessHeap(), 0, new_ext );
1277   }
1278   return gl_extensions;
1279 }
1280
1281 /***********************************************************************
1282  *              wglSwapBuffers (OPENGL32.@)
1283  */
1284 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
1285 {
1286     return GdiSwapBuffers(hdc);
1287 }
1288
1289 /**********************************************************************/
1290
1291 static void process_detach(void)
1292 {
1293   if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
1294 }
1295
1296 /***********************************************************************
1297  *           OpenGL initialisation routine
1298  */
1299 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1300 {
1301     switch(reason)
1302     {
1303     case DLL_PROCESS_ATTACH:
1304         opengl32_handle = hinst;
1305         DisableThreadLibraryCalls(hinst);
1306         NtCurrentTeb()->glTable = &null_opengl_funcs;
1307         break;
1308     case DLL_THREAD_ATTACH:
1309         NtCurrentTeb()->glTable = &null_opengl_funcs;
1310         break;
1311     case DLL_PROCESS_DETACH:
1312         process_detach();
1313         break;
1314     }
1315     return TRUE;
1316 }