Replaced the timer and its callback by a thread for receiving midi in
[wine] / dlls / opengl32 / wgl.c
1 /* Window-specific OpenGL functions implementation.
2  *
3  * Copyright (c) 1999 Lionel Ulmer
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winerror.h"
31
32 #include "wgl.h"
33 #include "wgl_ext.h"
34 #include "opengl_ext.h"
35 #include "wine/library.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
39
40 /* x11drv GDI escapes */
41 #define X11DRV_ESCAPE 6789
42 enum x11drv_escape_codes
43 {
44     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
45     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
46     X11DRV_GET_FONT,      /* get current X font for a DC */
47 };
48
49 void (*wine_tsx11_lock_ptr)(void) = NULL;
50 void (*wine_tsx11_unlock_ptr)(void) = NULL;
51
52 static GLXContext default_cx = NULL;
53 static Display *default_display;  /* display to use for default context */
54
55 static HMODULE opengl32_handle;
56
57 static void *(*p_glXGetProcAddressARB)(const GLubyte *);
58
59 typedef struct wine_glcontext {
60   HDC hdc;
61   Display *display;
62   GLXContext ctx;
63   XVisualInfo *vis;
64   struct wine_glcontext *next;
65   struct wine_glcontext *prev;
66 } Wine_GLContext;
67 static Wine_GLContext *context_list;
68
69 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
70 {
71     Wine_GLContext *ret;
72     for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
73     return ret;
74 }
75
76 static inline void free_context(Wine_GLContext *context)
77 {
78   if (context->next != NULL) context->next->prev = context->prev;
79   if (context->prev != NULL) context->prev->next = context->next;
80   else context_list = context->next;
81
82   HeapFree(GetProcessHeap(), 0, context);
83 }
84
85 static inline Wine_GLContext *alloc_context(void)
86 {
87   Wine_GLContext *ret;
88
89   if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
90   {
91       ret->next = context_list;
92       if (context_list) context_list->prev = ret;
93       context_list = ret;
94   }
95   return ret;
96 }
97
98 inline static BOOL is_valid_context( Wine_GLContext *ctx )
99 {
100     Wine_GLContext *ptr;
101     for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
102     return (ptr != NULL);
103 }
104
105 /* retrieve the X display to use on a given DC */
106 inline static Display *get_display( HDC hdc )
107 {
108     Display *display;
109     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
110
111     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
112                     sizeof(display), (LPSTR)&display )) display = NULL;
113     return display;
114 }
115
116
117 /* retrieve the X drawable to use on a given DC */
118 inline static Drawable get_drawable( HDC hdc )
119 {
120     Drawable drawable;
121     enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
122
123     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
124                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
125     return drawable;
126 }
127
128
129 /* retrieve the X drawable to use on a given DC */
130 inline static Font get_font( HDC hdc )
131 {
132     Font font;
133     enum x11drv_escape_codes escape = X11DRV_GET_FONT;
134
135     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
136                     sizeof(font), (LPSTR)&font )) font = 0;
137     return font;
138 }
139
140
141 /***********************************************************************
142  *              wglCreateContext (OPENGL32.@)
143  */
144 HGLRC WINAPI wglCreateContext(HDC hdc)
145 {
146   XVisualInfo *vis;
147   Wine_GLContext *ret;
148   int num;
149   XVisualInfo template;
150   Display *display = get_display( hdc );
151
152   TRACE("(%p)\n", hdc);
153
154   /* First, get the visual in use by the X11DRV */
155   if (!display) return 0;
156   template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
157   vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
158
159   if (vis == NULL) {
160     ERR("NULL visual !!!\n");
161     /* Need to set errors here */
162     return NULL;
163   }
164
165   /* The context will be allocated in the wglMakeCurrent call */
166   ENTER_GL();
167   ret = alloc_context();
168   LEAVE_GL();
169   ret->hdc = hdc;
170   ret->display = display;
171   ret->vis = vis;
172
173   TRACE(" creating context %p (GL context creation delayed)\n", ret);
174   return (HGLRC) ret;
175 }
176
177 /***********************************************************************
178  *              wglCreateLayerContext (OPENGL32.@)
179  */
180 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
181                                    int iLayerPlane) {
182   TRACE("(%p,%d)\n", hdc, iLayerPlane);
183
184   if (iLayerPlane == 0) {
185       return wglCreateContext(hdc);
186   }
187   FIXME(" no handler for layer %d\n", iLayerPlane);
188
189   return NULL;
190 }
191
192 /***********************************************************************
193  *              wglCopyContext (OPENGL32.@)
194  */
195 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
196                            HGLRC hglrcDst,
197                            UINT mask) {
198   FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
199
200   return FALSE;
201 }
202
203 /***********************************************************************
204  *              wglDeleteContext (OPENGL32.@)
205  */
206 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
207 {
208   Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
209   BOOL ret = TRUE;
210
211   TRACE("(%p)\n", hglrc);
212
213   ENTER_GL();
214   /* A game (Half Life not to name it) deletes twice the same context,
215    * so make sure it is valid first */
216   if (is_valid_context( ctx ))
217   {
218       if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
219       free_context(ctx);
220   }
221   else
222   {
223     WARN("Error deleting context !\n");
224     SetLastError(ERROR_INVALID_HANDLE);
225     ret = FALSE;
226   }
227   LEAVE_GL();
228
229   return ret;
230 }
231
232 /***********************************************************************
233  *              wglDescribeLayerPlane (OPENGL32.@)
234  */
235 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
236                                   int iPixelFormat,
237                                   int iLayerPlane,
238                                   UINT nBytes,
239                                   LPLAYERPLANEDESCRIPTOR plpd) {
240   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
241
242   return FALSE;
243 }
244
245 /***********************************************************************
246  *              wglGetCurrentContext (OPENGL32.@)
247  */
248 HGLRC WINAPI wglGetCurrentContext(void) {
249   GLXContext gl_ctx;
250   Wine_GLContext *ret;
251
252   TRACE("()\n");
253
254   ENTER_GL();
255   gl_ctx = glXGetCurrentContext();
256   ret = get_context_from_GLXContext(gl_ctx);
257   LEAVE_GL();
258
259   TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
260
261   return ret;
262 }
263
264 /***********************************************************************
265  *              wglGetCurrentDC (OPENGL32.@)
266  */
267 HDC WINAPI wglGetCurrentDC(void) {
268   GLXContext gl_ctx;
269   Wine_GLContext *ret;
270
271   TRACE("()\n");
272
273   ENTER_GL();
274   gl_ctx = glXGetCurrentContext();
275   ret = get_context_from_GLXContext(gl_ctx);
276   LEAVE_GL();
277
278   if (ret) {
279     TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
280     return ret->hdc;
281   } else {
282     TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
283     return 0;
284   }
285 }
286
287 /***********************************************************************
288  *              wglGetLayerPaletteEntries (OPENGL32.@)
289  */
290 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
291                                      int iLayerPlane,
292                                      int iStart,
293                                      int cEntries,
294                                      const COLORREF *pcr) {
295   FIXME("(): stub !\n");
296
297   return 0;
298 }
299
300 /***********************************************************************
301  *              wglGetProcAddress (OPENGL32.@)
302  */
303 static int compar(const void *elt_a, const void *elt_b) {
304   return strcmp(((OpenGL_extension *) elt_a)->name,
305                 ((OpenGL_extension *) elt_b)->name);
306 }
307
308 static int wgl_compar(const void *elt_a, const void *elt_b) {
309   return strcmp(((WGL_extension *) elt_a)->func_name,
310                 ((WGL_extension *) elt_b)->func_name);
311 }
312
313 void* WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
314   void *local_func;
315   OpenGL_extension  ext;
316   OpenGL_extension *ext_ret;
317
318   TRACE("(%s)\n", lpszProc);
319
320   /* First, look if it's not already defined in the 'standard' OpenGL functions */
321   if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
322     TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
323     return local_func;
324   }
325
326   if (p_glXGetProcAddressARB == NULL) {
327     ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
328     return NULL;
329   }
330   
331   /* After that, search in the thunks to find the real name of the extension */
332   ext.name = (char *) lpszProc;
333   ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
334                                          extension_registry_size, sizeof(OpenGL_extension), compar);
335
336   if (ext_ret == NULL) {
337     WGL_extension wgl_ext, *wgl_ext_ret;
338
339     /* Try to find the function in the WGL extensions ... */
340     wgl_ext.func_name = (char *) lpszProc;
341     wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
342                                             wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
343
344     if (wgl_ext_ret == NULL) {
345       /* Some sanity checks :-) */
346       ENTER_GL();
347       local_func = p_glXGetProcAddressARB(lpszProc);
348       LEAVE_GL();
349       if (local_func != NULL) {
350         ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
351         return NULL;
352       }
353       
354       WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
355       return NULL;
356     } else {
357         void *ret = NULL;
358
359         if (wgl_ext_ret->func_init != NULL) {
360             const char *err_msg;
361             if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
362                                                   wgl_ext_ret->context)) == NULL) {
363                 ret = wgl_ext_ret->func_address;
364             } else {
365                 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
366                 return NULL;
367             }
368         } else {
369           ret = wgl_ext_ret->func_address;
370         }
371
372         if (ret)
373             TRACE(" returning WGL function  (%p)\n", ret);
374         return ret;
375     }
376   } else {
377     ENTER_GL();
378     local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
379     LEAVE_GL();
380     
381     /* After that, look at the extensions defined in the Linux OpenGL library */
382     if (local_func == NULL) {
383       char buf[256];
384       void *ret = NULL;
385
386       /* Remove the 3 last letters (EXT, ARB, ...).
387
388          I know that some extensions have more than 3 letters (MESA, NV,
389          INTEL, ...), but this is only a stop-gap measure to fix buggy
390          OpenGL drivers (moreover, it is only useful for old 1.0 apps
391          that query the glBindTextureEXT extension).
392       */
393       strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
394       buf[strlen(ext_ret->glx_name) - 3] = '\0';
395       TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
396
397       ret = GetProcAddress(opengl32_handle, buf);
398       if (ret != NULL) {
399         TRACE(" found function in main OpenGL library (%p) !\n", ret);
400       } else {
401         WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
402       }
403
404       return ret;
405     } else {
406       TRACE(" returning function  (%p)\n", ext_ret->func);
407       *(ext_ret->func_ptr) = local_func;
408
409       return ext_ret->func;
410     }
411   }
412 }
413
414 /***********************************************************************
415  *              wglMakeCurrent (OPENGL32.@)
416  */
417 BOOL WINAPI wglMakeCurrent(HDC hdc,
418                            HGLRC hglrc) {
419   BOOL ret;
420
421   TRACE("(%p,%p)\n", hdc, hglrc);
422
423   ENTER_GL();
424   if (hglrc == NULL) {
425       ret = glXMakeCurrent(default_display, None, NULL);
426   } else {
427       Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
428       Drawable drawable = get_drawable( hdc );
429
430       if (ctx->ctx == NULL) {
431         ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
432         TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
433       }
434       ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
435   }
436   LEAVE_GL();
437   TRACE(" returning %s\n", (ret ? "True" : "False"));
438   return ret;
439 }
440
441 /***********************************************************************
442  *              wglRealizeLayerPalette (OPENGL32.@)
443  */
444 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
445                                    int iLayerPlane,
446                                    BOOL bRealize) {
447   FIXME("()\n");
448
449   return FALSE;
450 }
451
452 /***********************************************************************
453  *              wglSetLayerPaletteEntries (OPENGL32.@)
454  */
455 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
456                                      int iLayerPlane,
457                                      int iStart,
458                                      int cEntries,
459                                      const COLORREF *pcr) {
460   FIXME("(): stub !\n");
461
462   return 0;
463 }
464
465 /***********************************************************************
466  *              wglShareLists (OPENGL32.@)
467  */
468 BOOL WINAPI wglShareLists(HGLRC hglrc1,
469                           HGLRC hglrc2) {
470   Wine_GLContext *org  = (Wine_GLContext *) hglrc1;
471   Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
472
473   TRACE("(%p, %p)\n", org, dest);
474
475   if (dest->ctx != NULL) {
476     ERR("Could not share display lists, context already created !\n");
477     return FALSE;
478   } else {
479     if (org->ctx == NULL) {
480       ENTER_GL();
481       org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
482       LEAVE_GL();
483       TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
484     }
485
486     ENTER_GL();
487     /* Create the destination context with display lists shared */
488     dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
489     LEAVE_GL();
490     TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
491   }
492
493   return TRUE;
494 }
495
496 /***********************************************************************
497  *              wglSwapLayerBuffers (OPENGL32.@)
498  */
499 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
500                                 UINT fuPlanes) {
501   TRACE("(%p, %08x)\n", hdc, fuPlanes);
502
503   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
504     if (!SwapBuffers(hdc)) return FALSE;
505     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
506   }
507
508   if (fuPlanes) {
509     WARN("Following layers unhandled : %08x\n", fuPlanes);
510   }
511
512   return TRUE;
513 }
514
515 static BOOL internal_wglUseFontBitmaps(HDC hdc,
516                                        DWORD first,
517                                        DWORD count,
518                                        DWORD listBase,
519                                        DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
520 {
521     /* We are running using client-side rendering fonts... */
522     GLYPHMETRICS gm;
523     static const MAT2 id = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
524     int glyph;
525     int size = 0;
526     void *bitmap = NULL, *gl_bitmap = NULL;
527     int org_alignment;
528
529     ENTER_GL();
530     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
531     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
532     LEAVE_GL();
533
534     for (glyph = first; glyph < first + count; glyph++) {
535         int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &id);
536         int height, width_int;
537         
538         if (needed_size == GDI_ERROR) goto error;
539         if (needed_size > size) {
540             size = needed_size;
541             if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
542             if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
543             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
544             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
545         }
546         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &id) == GDI_ERROR) goto error;
547         if (TRACE_ON(opengl)) {
548             unsigned int height, width, bitmask;
549             unsigned char *bitmap_ = (unsigned char *) bitmap;
550             
551             DPRINTF("Glyph : %d\n", glyph);
552             DPRINTF("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
553             DPRINTF("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
554             DPRINTF("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
555             DPRINTF("  - size : %d\n", needed_size);
556             DPRINTF("  - bitmap : \n");
557             for (height = 0; height < gm.gmBlackBoxY; height++) {
558                 DPRINTF("      ");
559                 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
560                     if (bitmask == 0) {
561                         bitmap_ += 1;
562                         bitmask = 0x80;
563                     }
564                     if (*bitmap_ & bitmask)
565                         DPRINTF("*");
566                     else
567                         DPRINTF(" ");
568                 }
569                 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
570                 DPRINTF("\n");
571             }
572         }
573         
574         /* For some obscure reasons, I seem to need to rotate the glyph for OpenGL to be happy.
575            As Wine does not seem to support the MAT2 field, I need to do it myself.... */
576         width_int = (gm.gmBlackBoxX + 31) / 32;
577         for (height = 0; height < gm.gmBlackBoxY; height++) {
578             int width;
579             for (width = 0; width < width_int; width++) {
580                 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
581                     ((int *) bitmap)[height * width_int + width];
582             }
583         }
584         
585         ENTER_GL();
586         glNewList(listBase++, GL_COMPILE);
587         glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmptGlyphOrigin.x,
588                  gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap);
589         glEndList();
590         LEAVE_GL();
591     }
592     
593     ENTER_GL();
594     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
595     LEAVE_GL();
596     
597     if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
598     if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
599     return TRUE;
600
601   error:
602     ENTER_GL();
603     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
604     LEAVE_GL();
605
606     if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
607     if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
608     return FALSE;    
609 }
610
611 /***********************************************************************
612  *              wglUseFontBitmapsA (OPENGL32.@)
613  */
614 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
615                                DWORD first,
616                                DWORD count,
617                                DWORD listBase)
618 {
619   Font fid = get_font( hdc );
620
621   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
622
623   if (fid == 0) {
624       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
625   }
626
627   ENTER_GL();
628   /* I assume that the glyphs are at the same position for X and for Windows */
629   glXUseXFont(fid, first, count, listBase);
630   LEAVE_GL();
631   return TRUE;
632 }
633
634 /***********************************************************************
635  *              wglUseFontBitmapsW (OPENGL32.@)
636  */
637 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
638                                DWORD first,
639                                DWORD count,
640                                DWORD listBase)
641 {
642   Font fid = get_font( hdc );
643
644   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
645
646   if (fid == 0) {
647       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
648   }
649
650   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
651   
652   ENTER_GL();
653   /* I assume that the glyphs are at the same position for X and for Windows */
654   glXUseXFont(fid, first, count, listBase);
655   LEAVE_GL();
656   return TRUE;
657 }
658
659 /***********************************************************************
660  *              wglUseFontOutlinesA (OPENGL32.@)
661  */
662 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
663                                 DWORD first,
664                                 DWORD count,
665                                 DWORD listBase,
666                                 FLOAT deviation,
667                                 FLOAT extrusion,
668                                 int format,
669                                 LPGLYPHMETRICSFLOAT lpgmf) {
670   FIXME("(): stub !\n");
671
672   return FALSE;
673 }
674
675 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
676    include all dependencies
677 */
678 #ifndef SONAME_LIBGL
679 #define SONAME_LIBGL "libGL.so"
680 #endif
681
682 /* This is for brain-dead applications that use OpenGL functions before even
683    creating a rendering context.... */
684 static BOOL process_attach(void)
685 {
686   XWindowAttributes win_attr;
687   Visual *rootVisual;
688   int num;
689   XVisualInfo template;
690   HDC hdc;
691   XVisualInfo *vis = NULL;
692   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
693   HMODULE mod = GetModuleHandleA( "x11drv.dll" );
694   void *opengl_handle;
695
696   if (!root || !mod)
697   {
698       ERR("X11DRV not loaded. Cannot create default context.\n");
699       return FALSE;
700   }
701
702   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
703   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
704
705   hdc = GetDC(0);
706   default_display = get_display( hdc );
707   ReleaseDC( 0, hdc );
708   if (!default_display)
709   {
710       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
711       return FALSE;
712   }
713
714   ENTER_GL();
715
716   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
717      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
718      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
719      with mismatched visuals.  Note that the Root Window visual may not be double
720      buffered, so apps actually attempting to render this way may flicker */
721   if (XGetWindowAttributes( default_display, root, &win_attr ))
722   {
723     rootVisual = win_attr.visual;
724   }
725   else
726   {
727     /* Get the default visual, since we can't seem to get the attributes from the
728        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
729     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
730   }
731
732   template.visualid = XVisualIDFromVisual(rootVisual);
733   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
734   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
735   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
736   XFree(vis);
737   LEAVE_GL();
738
739   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
740   if (opengl_handle != NULL) {
741    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
742    wine_dlclose(opengl_handle, NULL, 0);
743    if (p_glXGetProcAddressARB == NULL)
744            TRACE("could not find glXGetProcAddressARB in libGL.\n");
745   }
746
747   /* Initialize also the list of supported WGL extensions. */
748   wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display));
749   
750   if (default_cx == NULL) {
751     ERR("Could not create default context.\n");
752   }
753   return TRUE;
754 }
755
756
757 /**********************************************************************/
758
759 static void process_detach(void)
760 {
761   glXDestroyContext(default_display, default_cx);
762
763   /* Do not leak memory... */
764   wgl_ext_finalize_extensions();
765 }
766
767 /***********************************************************************
768  *           OpenGL initialisation routine
769  */
770 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
771 {
772     switch(reason)
773     {
774     case DLL_PROCESS_ATTACH:
775         opengl32_handle = hinst;
776         DisableThreadLibraryCalls(hinst);
777         return process_attach();
778     case DLL_PROCESS_DETACH:
779         process_detach();
780         break;
781     }
782     return TRUE;
783 }