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