crypt32: Test decoding a big CRL.
[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 "winerror.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winternl.h"
35 #include "winnt.h"
36
37 #include "opengl_ext.h"
38 #ifdef HAVE_GL_GLU_H
39 #undef far
40 #undef near
41 #include <GL/glu.h>
42 #endif
43 #include "wine/library.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
47 WINE_DECLARE_DEBUG_CHANNEL(opengl);
48
49 typedef struct wine_wgl_s {
50     HGLRC WINAPI (*p_wglCreateContext)(HDC hdc);
51     BOOL WINAPI  (*p_wglDeleteContext)(HGLRC hglrc);
52     HGLRC WINAPI (*p_wglGetCurrentContext)(void);
53     HDC WINAPI   (*p_wglGetCurrentDC)(void);
54     HDC WINAPI   (*p_wglGetCurrentReadDCARB)(void);
55     PROC WINAPI  (*p_wglGetProcAddress)(LPCSTR  lpszProc);
56     BOOL WINAPI  (*p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
57     BOOL WINAPI  (*p_wglMakeContextCurrentARB)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 
58     BOOL WINAPI  (*p_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
59
60     void WINAPI  (*p_wglGetIntegerv)(GLenum pname, GLint* params);
61 } wine_wgl_t;
62
63 /** global wgl object */
64 static wine_wgl_t wine_wgl;
65
66 /* x11drv GDI escapes */
67 #define X11DRV_ESCAPE 6789
68 enum x11drv_escape_codes
69 {
70     X11DRV_GET_DISPLAY,         /* get X11 display for a DC */
71     X11DRV_GET_DRAWABLE,        /* get current drawable for a DC */
72     X11DRV_GET_FONT,            /* get current X font for a DC */
73     X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
74     X11DRV_START_EXPOSURES,     /* start graphics exposures */
75     X11DRV_END_EXPOSURES,       /* end graphics exposures */
76     X11DRV_GET_DCE,             /* get the DCE pointer */
77     X11DRV_SET_DCE,             /* set the DCE pointer */
78     X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
79     X11DRV_SYNC_PIXMAP          /* sync the dibsection to its pixmap */
80 };
81
82 void (*wine_tsx11_lock_ptr)(void) = NULL;
83 void (*wine_tsx11_unlock_ptr)(void) = NULL;
84
85 static GLXContext default_cx = NULL;
86 static Display *default_display;  /* display to use for default context */
87
88 static HMODULE opengl32_handle;
89
90 static void* (*p_glXGetProcAddressARB)(const GLubyte *);
91
92 static char  internal_gl_disabled_extensions[512];
93 static char* internal_gl_extensions = NULL;
94
95 typedef struct wine_glcontext {
96   HDC hdc;
97   Display *display;
98   XVisualInfo *vis;
99   GLXFBConfig fb_conf;
100   GLXContext ctx;
101   BOOL do_escape;
102   struct wine_glcontext *next;
103   struct wine_glcontext *prev;
104 } Wine_GLContext;
105
106 void enter_gl(void)
107 {
108     Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
109     
110     if (curctx && curctx->do_escape)
111     {
112         enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
113         ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
114     }
115
116     wine_tsx11_lock_ptr();
117     return;
118 }
119
120 /* retrieve the X display to use on a given DC */
121 inline static Display *get_display( HDC hdc )
122 {
123     Display *display;
124     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
125
126     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
127                     sizeof(display), (LPSTR)&display )) display = NULL;
128     return display;
129 }
130
131 /* retrieve the X font to use on a given DC */
132 inline static Font get_font( HDC hdc )
133 {
134     Font font;
135     enum x11drv_escape_codes escape = X11DRV_GET_FONT;
136
137     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
138                     sizeof(font), (LPSTR)&font )) font = 0;
139     return font;
140 }
141
142 /***********************************************************************
143  *              wglCreateContext (OPENGL32.@)
144  */
145 HGLRC WINAPI wglCreateContext(HDC hdc)
146 {
147     TRACE("(%p)\n", hdc);
148     return wine_wgl.p_wglCreateContext(hdc);
149 }
150
151 /***********************************************************************
152  *              wglCreateLayerContext (OPENGL32.@)
153  */
154 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
155                                    int iLayerPlane) {
156   TRACE("(%p,%d)\n", hdc, iLayerPlane);
157
158   if (iLayerPlane == 0) {
159       return wglCreateContext(hdc);
160   }
161   FIXME(" no handler for layer %d\n", iLayerPlane);
162
163   return NULL;
164 }
165
166 /***********************************************************************
167  *              wglCopyContext (OPENGL32.@)
168  */
169 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
170                            HGLRC hglrcDst,
171                            UINT mask) {
172   FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
173
174   return FALSE;
175 }
176
177 /***********************************************************************
178  *              wglDeleteContext (OPENGL32.@)
179  */
180 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
181 {
182     TRACE("(%p)\n", hglrc);
183     return wine_wgl.p_wglDeleteContext(hglrc);
184 }
185
186 /***********************************************************************
187  *              wglDescribeLayerPlane (OPENGL32.@)
188  */
189 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
190                                   int iPixelFormat,
191                                   int iLayerPlane,
192                                   UINT nBytes,
193                                   LPLAYERPLANEDESCRIPTOR plpd) {
194   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
195
196   return FALSE;
197 }
198
199 /***********************************************************************
200  *              wglGetCurrentContext (OPENGL32.@)
201  */
202 HGLRC WINAPI wglGetCurrentContext(void) {
203     TRACE("\n");
204     return wine_wgl.p_wglGetCurrentContext();
205 }
206
207 /***********************************************************************
208  *              wglGetCurrentDC (OPENGL32.@)
209  */
210 HDC WINAPI wglGetCurrentDC(void) {
211     TRACE("\n");
212     return wine_wgl.p_wglGetCurrentDC();
213 }
214
215 /***********************************************************************
216  *              wglGetLayerPaletteEntries (OPENGL32.@)
217  */
218 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
219                                      int iLayerPlane,
220                                      int iStart,
221                                      int cEntries,
222                                      const COLORREF *pcr) {
223   FIXME("(): stub !\n");
224
225   return 0;
226 }
227
228 /***********************************************************************
229  *              wglGetProcAddress (OPENGL32.@)
230  */
231 static int compar(const void *elt_a, const void *elt_b) {
232   return strcmp(((const OpenGL_extension *) elt_a)->name,
233                 ((const OpenGL_extension *) elt_b)->name);
234 }
235
236 PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
237   void *local_func;
238   OpenGL_extension  ext;
239   const OpenGL_extension *ext_ret;
240
241   TRACE("(%s)\n", lpszProc);
242
243   /* First, look if it's not already defined in the 'standard' OpenGL functions */
244   if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
245     TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
246     return local_func;
247   }
248
249   if (p_glXGetProcAddressARB == NULL) {
250     ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
251     return NULL;
252   }
253   
254   /* After that, search in the thunks to find the real name of the extension */
255   ext.name = lpszProc;
256   ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
257                                          extension_registry_size, sizeof(OpenGL_extension), compar);
258
259   /* If nothing was found, we are looking for a WGL extension */
260   if (ext_ret == NULL) {
261     return wine_wgl.p_wglGetProcAddress(lpszProc);
262   } else { /* We are looking for an OpenGL extension */
263     const char *glx_name = ext_ret->glx_name ? ext_ret->glx_name : ext_ret->name;
264     ENTER_GL();
265     local_func = p_glXGetProcAddressARB( (const GLubyte*)glx_name);
266     LEAVE_GL();
267     
268     /* After that, look at the extensions defined in the Linux OpenGL library */
269     if (local_func == NULL) {
270       char buf[256];
271       void *ret = NULL;
272
273       /* Remove the 3 last letters (EXT, ARB, ...).
274
275          I know that some extensions have more than 3 letters (MESA, NV,
276          INTEL, ...), but this is only a stop-gap measure to fix buggy
277          OpenGL drivers (moreover, it is only useful for old 1.0 apps
278          that query the glBindTextureEXT extension).
279       */
280       memcpy(buf, glx_name, strlen(glx_name) - 3);
281       buf[strlen(glx_name) - 3] = '\0';
282       TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
283
284       ret = GetProcAddress(opengl32_handle, buf);
285       if (ret != NULL) {
286         TRACE(" found function in main OpenGL library (%p) !\n", ret);
287       } else {
288         WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, glx_name);
289       }
290
291       return ret;
292     } else {
293       TRACE(" returning function  (%p)\n", ext_ret->func);
294       extension_funcs[ext_ret - extension_registry] = local_func;
295
296       return ext_ret->func;
297     }
298   }
299 }
300
301 /***********************************************************************
302  *              wglMakeCurrent (OPENGL32.@)
303  */
304 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc) {
305     TRACE("hdc: (%p), hglrc: (%p)\n", hdc, hglrc);
306     return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
307 }
308
309 /***********************************************************************
310  *              wglMakeContextCurrentARB (OPENGL32.@)
311  */
312 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) 
313 {
314     TRACE("hDrawDC: (%p), hReadDC: (%p), hglrc: (%p)\n", hDrawDC, hReadDC, hglrc);
315     return wine_wgl.p_wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc);
316 }
317
318 /***********************************************************************
319  *              wglGetCurrentReadDCARB (OPENGL32.@)
320  */
321 HDC WINAPI wglGetCurrentReadDCARB(void) 
322 {
323     TRACE("\n");
324     return wine_wgl.p_wglGetCurrentReadDCARB();
325 }
326
327 /***********************************************************************
328  *              wglRealizeLayerPalette (OPENGL32.@)
329  */
330 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
331                                    int iLayerPlane,
332                                    BOOL bRealize) {
333   FIXME("()\n");
334
335   return FALSE;
336 }
337
338 /***********************************************************************
339  *              wglSetLayerPaletteEntries (OPENGL32.@)
340  */
341 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
342                                      int iLayerPlane,
343                                      int iStart,
344                                      int cEntries,
345                                      const COLORREF *pcr) {
346   FIXME("(): stub !\n");
347
348   return 0;
349 }
350
351 /***********************************************************************
352  *              wglShareLists (OPENGL32.@)
353  */
354 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
355     TRACE("(%p, %p)\n", hglrc1, hglrc2);
356     return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
357 }
358
359 /***********************************************************************
360  *              wglSwapLayerBuffers (OPENGL32.@)
361  */
362 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
363                                 UINT fuPlanes) {
364   TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
365
366   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
367     if (!SwapBuffers(hdc)) return FALSE;
368     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
369   }
370
371   if (fuPlanes) {
372     WARN("Following layers unhandled : %08x\n", fuPlanes);
373   }
374
375   return TRUE;
376 }
377
378 static BOOL internal_wglUseFontBitmaps(HDC hdc,
379                                        DWORD first,
380                                        DWORD count,
381                                        DWORD listBase,
382                                        DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
383 {
384     /* We are running using client-side rendering fonts... */
385     GLYPHMETRICS gm;
386     unsigned int glyph;
387     int size = 0;
388     void *bitmap = NULL, *gl_bitmap = NULL;
389     int org_alignment;
390
391     ENTER_GL();
392     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
393     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
394     LEAVE_GL();
395
396     for (glyph = first; glyph < first + count; glyph++) {
397         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
398         int height, width_int;
399
400         TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
401         if (needed_size == GDI_ERROR) {
402             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
403             goto error;
404         } else {
405             TRACE("  - needed size : %d\n", needed_size);
406         }
407
408         if (needed_size > size) {
409             size = needed_size;
410             HeapFree(GetProcessHeap(), 0, bitmap);
411             HeapFree(GetProcessHeap(), 0, gl_bitmap);
412             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
413             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
414         }
415         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
416         if (TRACE_ON(opengl)) {
417             unsigned int height, width, bitmask;
418             unsigned char *bitmap_ = (unsigned char *) bitmap;
419             
420             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
421             TRACE("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
422             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
423             if (needed_size != 0) {
424                 TRACE("  - bitmap :\n");
425                 for (height = 0; height < gm.gmBlackBoxY; height++) {
426                     TRACE("      ");
427                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
428                         if (bitmask == 0) {
429                             bitmap_ += 1;
430                             bitmask = 0x80;
431                         }
432                         if (*bitmap_ & bitmask)
433                             TRACE("*");
434                         else
435                             TRACE(" ");
436                     }
437                     bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
438                     TRACE("\n");
439                 }
440             }
441         }
442         
443         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
444          * glyph for it to be drawn properly.
445          */
446         if (needed_size != 0) {
447             width_int = (gm.gmBlackBoxX + 31) / 32;
448             for (height = 0; height < gm.gmBlackBoxY; height++) {
449                 int width;
450                 for (width = 0; width < width_int; width++) {
451                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
452                         ((int *) bitmap)[height * width_int + width];
453                 }
454             }
455         }
456         
457         ENTER_GL();
458         glNewList(listBase++, GL_COMPILE);
459         if (needed_size != 0) {
460             glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
461                      0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
462                      gm.gmCellIncX, gm.gmCellIncY,
463                      gl_bitmap);
464         } else {
465             /* This is the case of 'empty' glyphs like the space character */
466             glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
467         }
468         glEndList();
469         LEAVE_GL();
470     }
471     
472     ENTER_GL();
473     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
474     LEAVE_GL();
475     
476     HeapFree(GetProcessHeap(), 0, bitmap);
477     HeapFree(GetProcessHeap(), 0, gl_bitmap);
478     return TRUE;
479
480   error:
481     ENTER_GL();
482     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
483     LEAVE_GL();
484
485     HeapFree(GetProcessHeap(), 0, bitmap);
486     HeapFree(GetProcessHeap(), 0, gl_bitmap);
487     return FALSE;    
488 }
489
490 /***********************************************************************
491  *              wglUseFontBitmapsA (OPENGL32.@)
492  */
493 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
494                                DWORD first,
495                                DWORD count,
496                                DWORD listBase)
497 {
498   Font fid = get_font( hdc );
499
500   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
501
502   if (fid == 0) {
503       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
504   }
505
506   ENTER_GL();
507   /* I assume that the glyphs are at the same position for X and for Windows */
508   glXUseXFont(fid, first, count, listBase);
509   LEAVE_GL();
510   return TRUE;
511 }
512
513 /***********************************************************************
514  *              wglUseFontBitmapsW (OPENGL32.@)
515  */
516 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
517                                DWORD first,
518                                DWORD count,
519                                DWORD listBase)
520 {
521   Font fid = get_font( hdc );
522
523   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
524
525   if (fid == 0) {
526       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
527   }
528
529   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
530   
531   ENTER_GL();
532   /* I assume that the glyphs are at the same position for X and for Windows */
533   glXUseXFont(fid, first, count, listBase);
534   LEAVE_GL();
535   return TRUE;
536 }
537
538 #ifdef HAVE_GL_GLU_H
539
540 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
541 {
542     vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;  
543     vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;  
544     vertex[2] = 0.0;
545 }
546
547 static void tess_callback_vertex(GLvoid *vertex)
548 {
549     GLdouble *dbl = vertex;
550     TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
551     glVertex3dv(vertex);
552 }
553
554 static void tess_callback_begin(GLenum which)
555 {
556     TRACE("%d\n", which);
557     glBegin(which);
558 }
559
560 static void tess_callback_end(void)
561 {
562     TRACE("\n");
563     glEnd();
564 }
565
566 /***********************************************************************
567  *              wglUseFontOutlines_common
568  */
569 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
570                                       DWORD first,
571                                       DWORD count,
572                                       DWORD listBase,
573                                       FLOAT deviation,
574                                       FLOAT extrusion,
575                                       int format,
576                                       LPGLYPHMETRICSFLOAT lpgmf,
577                                       BOOL unicode)
578 {
579     UINT glyph;
580     const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
581     GLUtesselator *tess;
582     LOGFONTW lf;
583     HFONT old_font, unscaled_font;
584     UINT em_size = 1024;
585     RECT rc;
586
587     TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
588           listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
589
590
591     ENTER_GL();
592     tess = gluNewTess();
593     if(tess)
594     {
595         gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
596         gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
597         gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
598     }
599     LEAVE_GL();
600
601     if(!tess) return FALSE;
602
603     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
604     rc.left = rc.right = rc.bottom = 0;
605     rc.top = em_size;
606     DPtoLP(hdc, (POINT*)&rc, 2);
607     lf.lfHeight = -abs(rc.top - rc.bottom);
608     lf.lfOrientation = lf.lfEscapement = 0;
609     unscaled_font = CreateFontIndirectW(&lf);
610     old_font = SelectObject(hdc, unscaled_font);
611
612     for (glyph = first; glyph < first + count; glyph++)
613     {
614         DWORD needed;
615         GLYPHMETRICS gm;
616         BYTE *buf;
617         TTPOLYGONHEADER *pph;
618         TTPOLYCURVE *ppc;
619         GLdouble *vertices;
620
621         if(unicode)
622             needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
623         else
624             needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
625
626         if(needed == GDI_ERROR)
627             goto error;
628
629         buf = HeapAlloc(GetProcessHeap(), 0, needed);
630         vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
631
632         if(unicode)
633             GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
634         else
635             GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
636
637         TRACE("glyph %d\n", glyph);
638
639         if(lpgmf)
640         {
641             lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
642             lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
643             lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
644             lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
645             lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
646             lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
647
648             TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
649                   lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); 
650             lpgmf++;
651         }
652
653         ENTER_GL();
654         glNewList(listBase++, GL_COMPILE);
655         gluTessBeginPolygon(tess, NULL);
656
657         pph = (TTPOLYGONHEADER*)buf;
658         while((BYTE*)pph < buf + needed)
659         {
660             TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
661
662             gluTessBeginContour(tess);
663
664             fixed_to_double(pph->pfxStart, em_size, vertices);
665             gluTessVertex(tess, vertices, vertices);
666             vertices += 3;
667
668             ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
669             while((char*)ppc < (char*)pph + pph->cb)
670             {
671                 int i;
672
673                 switch(ppc->wType) {
674                 case TT_PRIM_LINE:
675                     for(i = 0; i < ppc->cpfx; i++)
676                     {
677                         TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
678                         fixed_to_double(ppc->apfx[i], em_size, vertices); 
679                         gluTessVertex(tess, vertices, vertices);
680                         vertices += 3;
681                     }
682                     break;
683
684                 case TT_PRIM_QSPLINE:
685                     for(i = 0; i < ppc->cpfx/2; i++)
686                     {
687                         /* FIXME just connecting the control points for now */
688                         TRACE("\t\tcurve  %d,%d %d,%d\n",
689                               ppc->apfx[i * 2].x.value,     ppc->apfx[i * 3].y.value,
690                               ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
691                         fixed_to_double(ppc->apfx[i * 2], em_size, vertices); 
692                         gluTessVertex(tess, vertices, vertices);
693                         vertices += 3;
694                         fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); 
695                         gluTessVertex(tess, vertices, vertices);
696                         vertices += 3;
697                     }
698                     break;
699                 default:
700                     ERR("\t\tcurve type = %d\n", ppc->wType);
701                     gluTessEndContour(tess);
702                     goto error_in_list;
703                 }
704
705                 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
706                                      (ppc->cpfx - 1) * sizeof(POINTFX));
707             }
708             gluTessEndContour(tess);
709             pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
710         }
711
712 error_in_list:
713         gluTessEndPolygon(tess);
714         glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
715         glEndList();
716         LEAVE_GL();
717         HeapFree(GetProcessHeap(), 0, buf);
718         HeapFree(GetProcessHeap(), 0, vertices);
719     }
720
721  error:
722     DeleteObject(SelectObject(hdc, old_font));
723     gluDeleteTess(tess);
724     return TRUE;
725
726 }
727
728 #else /* HAVE_GL_GLU_H */
729
730 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
731                                       DWORD first,
732                                       DWORD count,
733                                       DWORD listBase,
734                                       FLOAT deviation,
735                                       FLOAT extrusion,
736                                       int format,
737                                       LPGLYPHMETRICSFLOAT lpgmf,
738                                       BOOL unicode)
739 {
740     FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
741     return FALSE;
742 }
743
744 #endif /* HAVE_GL_GLU_H */
745
746 /***********************************************************************
747  *              wglUseFontOutlinesA (OPENGL32.@)
748  */
749 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
750                                 DWORD first,
751                                 DWORD count,
752                                 DWORD listBase,
753                                 FLOAT deviation,
754                                 FLOAT extrusion,
755                                 int format,
756                                 LPGLYPHMETRICSFLOAT lpgmf)
757 {
758     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
759 }
760
761 /***********************************************************************
762  *              wglUseFontOutlinesW (OPENGL32.@)
763  */
764 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
765                                 DWORD first,
766                                 DWORD count,
767                                 DWORD listBase,
768                                 FLOAT deviation,
769                                 FLOAT extrusion,
770                                 int format,
771                                 LPGLYPHMETRICSFLOAT lpgmf)
772 {
773     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
774 }
775
776 const GLubyte * internal_glGetString(GLenum name) {
777   const char* GL_Extensions = NULL;
778   
779   if (GL_EXTENSIONS != name) {
780     return glGetString(name);
781   }
782
783   if (NULL == internal_gl_extensions) {
784     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
785
786     TRACE("GL_EXTENSIONS reported:\n");  
787     if (NULL == GL_Extensions) {
788       ERR("GL_EXTENSIONS returns NULL\n");      
789       return NULL;
790     } else {
791       size_t len = strlen(GL_Extensions);
792       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
793
794       while (*GL_Extensions != 0x00) {
795         const char* Start = GL_Extensions;
796         char        ThisExtn[256];
797          
798         memset(ThisExtn, 0x00, sizeof(ThisExtn));
799         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
800           GL_Extensions++;
801         }
802         memcpy(ThisExtn, Start, (GL_Extensions - Start));
803         TRACE("- %s:", ThisExtn);
804         
805         /* test if supported API is disabled by config */
806         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
807           strcat(internal_gl_extensions, " ");
808           strcat(internal_gl_extensions, ThisExtn);
809           TRACE(" active\n");
810         } else {
811           TRACE(" deactived (by config)\n");
812         }
813
814         if (*GL_Extensions == ' ') GL_Extensions++;
815       }
816     }
817   }
818   return (const GLubyte *) internal_gl_extensions;
819 }
820
821 void internal_glGetIntegerv(GLenum pname, GLint* params) {
822   TRACE("pname: 0x%x, params %p\n", pname, params);
823   glGetIntegerv(pname, params);
824   /* A few parameters like GL_DEPTH_BITS differ between WGL and GLX, the wglGetIntegerv helper function handles those */
825   wine_wgl.p_wglGetIntegerv(pname, params);
826 }
827
828
829 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
830    include all dependencies
831 */
832 #ifndef SONAME_LIBGL
833 #define SONAME_LIBGL "libGL.so"
834 #endif
835
836 /* This is for brain-dead applications that use OpenGL functions before even
837    creating a rendering context.... */
838 static BOOL process_attach(void)
839 {
840   XWindowAttributes win_attr;
841   Visual *rootVisual;
842   int num;
843   XVisualInfo template;
844   HDC hdc;
845   XVisualInfo *vis = NULL;
846   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
847   HMODULE mod = GetModuleHandleA( "winex11.drv" );
848   void *opengl_handle;
849   DWORD size = sizeof(internal_gl_disabled_extensions);
850   HKEY hkey = 0;
851
852   if (!root || !mod)
853   {
854       ERR("X11DRV not loaded. Cannot create default context.\n");
855       return FALSE;
856   }
857
858   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
859   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
860
861   /* Load WGL function pointers from winex11.drv */
862   wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod, "wglCreateContext");
863   wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod, "wglDeleteContext");
864   wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod, "wglGetCurrentContext");
865   wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod, "wglGetCurrentDC");
866   wine_wgl.p_wglGetCurrentReadDCARB = (void *)GetProcAddress(mod, "wglGetCurrentReadDCARB");
867   wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod, "wglGetProcAddress");
868   wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod, "wglMakeCurrent");
869   wine_wgl.p_wglMakeContextCurrentARB = (void *)GetProcAddress(mod, "wglMakeContextCurrentARB");
870   wine_wgl.p_wglShareLists = (void *)GetProcAddress(mod, "wglShareLists");
871   /* Interal WGL function */
872   wine_wgl.p_wglGetIntegerv = (void *)GetProcAddress(mod, "wglGetIntegerv");
873
874   hdc = GetDC(0);
875   default_display = get_display( hdc );
876   ReleaseDC( 0, hdc );
877   if (!default_display)
878   {
879       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
880       return FALSE;
881   }
882
883   ENTER_GL();
884
885   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
886      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
887      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
888      with mismatched visuals.  Note that the Root Window visual may not be double
889      buffered, so apps actually attempting to render this way may flicker */
890   if (XGetWindowAttributes( default_display, root, &win_attr ))
891   {
892     rootVisual = win_attr.visual;
893   }
894   else
895   {
896     /* Get the default visual, since we can't seem to get the attributes from the
897        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
898     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
899   }
900
901   template.visualid = XVisualIDFromVisual(rootVisual);
902   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
903   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
904   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
905   XFree(vis);
906   LEAVE_GL();
907
908   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
909   if (opengl_handle != NULL) {
910    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
911    wine_dlclose(opengl_handle, NULL, 0);
912    if (p_glXGetProcAddressARB == NULL)
913            TRACE("could not find glXGetProcAddressARB in libGL.\n");
914   }
915
916   internal_gl_disabled_extensions[0] = 0;
917   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
918     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
919       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
920     }
921     RegCloseKey(hkey);
922   }
923
924   if (default_cx == NULL) {
925     ERR("Could not create default context.\n");
926   }
927   return TRUE;
928 }
929
930
931 /**********************************************************************/
932
933 static void process_detach(void)
934 {
935   glXDestroyContext(default_display, default_cx);
936
937   HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
938 }
939
940 /***********************************************************************
941  *           OpenGL initialisation routine
942  */
943 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
944 {
945     switch(reason)
946     {
947     case DLL_PROCESS_ATTACH:
948         opengl32_handle = hinst;
949         DisableThreadLibraryCalls(hinst);
950         return process_attach();
951     case DLL_PROCESS_DETACH:
952         process_detach();
953         break;
954     }
955     return TRUE;
956 }