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