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