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