mshtml: Added beginning OnDataAvailable implementation.
[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 "wgl_ext.h"
38 #include "opengl_ext.h"
39 #ifdef HAVE_GL_GLU_H
40 #undef far
41 #undef near
42 #include <GL/glu.h>
43 #endif
44 #include "wine/library.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
48 WINE_DECLARE_DEBUG_CHANNEL(opengl);
49
50 /** global glx object */
51 wine_glx_t wine_glx;
52
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
56 {
57     X11DRV_GET_DISPLAY,         /* get X11 display for a DC */
58     X11DRV_GET_DRAWABLE,        /* get current drawable for a DC */
59     X11DRV_GET_FONT,            /* get current X font for a DC */
60     X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
61     X11DRV_START_EXPOSURES,     /* start graphics exposures */
62     X11DRV_END_EXPOSURES,       /* end graphics exposures */
63     X11DRV_GET_DCE,             /* get the DCE pointer */
64     X11DRV_SET_DCE,             /* set the DCE pointer */
65     X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
66     X11DRV_SYNC_PIXMAP          /* sync the dibsection to its pixmap */
67 };
68
69 void (*wine_tsx11_lock_ptr)(void) = NULL;
70 void (*wine_tsx11_unlock_ptr)(void) = NULL;
71
72 static GLXContext default_cx = NULL;
73 static Display *default_display;  /* display to use for default context */
74
75 static HMODULE opengl32_handle;
76
77 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
78
79 static char  internal_gl_disabled_extensions[512];
80 static char* internal_gl_extensions = NULL;
81
82 typedef struct wine_glcontext {
83   HDC hdc;
84   Display *display;
85   XVisualInfo *vis;
86   GLXFBConfig fb_conf;
87   GLXContext ctx;
88   BOOL do_escape;
89   struct wine_glcontext *next;
90   struct wine_glcontext *prev;
91 } Wine_GLContext;
92 static Wine_GLContext *context_list;
93
94 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
95 {
96     Wine_GLContext *ret;
97     for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
98     return ret;
99 }
100
101 void enter_gl(void)
102 {
103     Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
104     
105     if (curctx && curctx->do_escape)
106     {
107         enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
108         ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
109     }
110
111     wine_tsx11_lock_ptr();
112     return;
113 }
114
115 static inline void free_context(Wine_GLContext *context)
116 {
117   if (context->next != NULL) context->next->prev = context->prev;
118   if (context->prev != NULL) context->prev->next = context->next;
119   else context_list = context->next;
120
121   HeapFree(GetProcessHeap(), 0, context);
122 }
123
124 static inline Wine_GLContext *alloc_context(void)
125 {
126   Wine_GLContext *ret;
127
128   if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
129   {
130       ret->next = context_list;
131       if (context_list) context_list->prev = ret;
132       context_list = ret;
133   }
134   return ret;
135 }
136
137 inline static BOOL is_valid_context( Wine_GLContext *ctx )
138 {
139     Wine_GLContext *ptr;
140     for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
141     return (ptr != NULL);
142 }
143
144 /* retrieve the X display to use on a given DC */
145 inline static Display *get_display( HDC hdc )
146 {
147     Display *display;
148     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
149
150     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
151                     sizeof(display), (LPSTR)&display )) display = NULL;
152     return display;
153 }
154
155
156 /* retrieve the GLX drawable to use on a given DC */
157 inline static Drawable get_drawable( HDC hdc )
158 {
159     GLXDrawable drawable;
160     enum x11drv_escape_codes escape = X11DRV_GET_GLX_DRAWABLE;
161
162     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
163                     sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
164     return drawable;
165 }
166
167 /** for use of wglGetCurrentReadDCARB */
168 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
169 {
170   Wine_GLContext *ret;
171   for (ret = context_list; ret; ret = ret->next) {  
172     if (d == get_drawable( ret->hdc )) {
173       return ret->hdc;
174     }
175   }
176   return NULL;
177 }
178
179 /* retrieve the X font to use on a given DC */
180 inline static Font get_font( HDC hdc )
181 {
182     Font font;
183     enum x11drv_escape_codes escape = X11DRV_GET_FONT;
184
185     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
186                     sizeof(font), (LPSTR)&font )) font = 0;
187     return font;
188 }
189
190
191 /***********************************************************************
192  *              wglCreateContext (OPENGL32.@)
193  */
194 HGLRC WINAPI wglCreateContext(HDC hdc)
195 {
196   Wine_GLContext *ret;
197   int num;
198   XVisualInfo template;
199   XVisualInfo *vis = NULL;
200   Display *display = get_display( hdc );
201   int hdcPF = GetPixelFormat(hdc);
202   GLXFBConfig cur_cfg;
203
204   TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);
205
206   /* First, get the visual in use by the X11DRV */
207   if (!display) return 0;
208   template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
209   vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
210
211   if (vis == NULL) {
212     ERR("NULL visual !!!\n");
213     /* Need to set errors here */
214     return NULL;
215   }
216   if (0 >= hdcPF) {
217     SetLastError(ERROR_INVALID_PIXEL_FORMAT);
218     return NULL;
219   }
220
221   {
222     int nCfgs_fmt = 0;
223     GLXFBConfig* cfgs_fmt = NULL;
224     int value;
225     int gl_test = 0;
226     cfgs_fmt = wine_glx.p_glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
227     if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
228       ERR("Cannot get FB Configs, expect problems.\n");
229       SetLastError(ERROR_INVALID_PIXEL_FORMAT);
230       return NULL;
231     }
232     if (nCfgs_fmt < hdcPF) {
233       ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, nCfgs_fmt);
234       SetLastError(ERROR_INVALID_PIXEL_FORMAT);
235       return NULL;
236     }
237     cur_cfg = cfgs_fmt[hdcPF - 1];
238     gl_test = wine_glx.p_glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
239     if (gl_test) {
240       ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
241       SetLastError(ERROR_INVALID_PIXEL_FORMAT);
242       return NULL;
243     }
244     XFree(cfgs_fmt);
245   }
246
247   /* The context will be allocated in the wglMakeCurrent call */
248   ENTER_GL();
249   ret = alloc_context();
250   LEAVE_GL();
251   ret->hdc = hdc;
252   ret->display = display;
253   ret->fb_conf = cur_cfg;
254   /*ret->vis = vis;*/
255   ret->vis = wine_glx.p_glXGetVisualFromFBConfig(display, cur_cfg);
256
257   TRACE(" creating context %p (GL context creation delayed)\n", ret);
258   return (HGLRC) ret;
259 }
260
261 /***********************************************************************
262  *              wglCreateLayerContext (OPENGL32.@)
263  */
264 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
265                                    int iLayerPlane) {
266   TRACE("(%p,%d)\n", hdc, iLayerPlane);
267
268   if (iLayerPlane == 0) {
269       return wglCreateContext(hdc);
270   }
271   FIXME(" no handler for layer %d\n", iLayerPlane);
272
273   return NULL;
274 }
275
276 /***********************************************************************
277  *              wglCopyContext (OPENGL32.@)
278  */
279 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
280                            HGLRC hglrcDst,
281                            UINT mask) {
282   FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
283
284   return FALSE;
285 }
286
287 /***********************************************************************
288  *              wglDeleteContext (OPENGL32.@)
289  */
290 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
291 {
292   Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
293   BOOL ret = TRUE;
294
295   TRACE("(%p)\n", hglrc);
296
297   ENTER_GL();
298   /* A game (Half Life not to name it) deletes twice the same context,
299    * so make sure it is valid first */
300   if (is_valid_context( ctx ))
301   {
302       if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
303       free_context(ctx);
304   }
305   else
306   {
307     WARN("Error deleting context !\n");
308     SetLastError(ERROR_INVALID_HANDLE);
309     ret = FALSE;
310   }
311   LEAVE_GL();
312
313   return ret;
314 }
315
316 /***********************************************************************
317  *              wglDescribeLayerPlane (OPENGL32.@)
318  */
319 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
320                                   int iPixelFormat,
321                                   int iLayerPlane,
322                                   UINT nBytes,
323                                   LPLAYERPLANEDESCRIPTOR plpd) {
324   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
325
326   return FALSE;
327 }
328
329 /***********************************************************************
330  *              wglGetCurrentContext (OPENGL32.@)
331  */
332 HGLRC WINAPI wglGetCurrentContext(void) {
333   GLXContext gl_ctx;
334   Wine_GLContext *ret;
335
336   TRACE("()\n");
337
338   ENTER_GL();
339   gl_ctx = glXGetCurrentContext();
340   ret = get_context_from_GLXContext(gl_ctx);
341   LEAVE_GL();
342
343   TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
344
345   return (HGLRC)ret;
346 }
347
348 /***********************************************************************
349  *              wglGetCurrentDC (OPENGL32.@)
350  */
351 HDC WINAPI wglGetCurrentDC(void) {
352   GLXContext gl_ctx;
353   Wine_GLContext *ret;
354
355   TRACE("()\n");
356
357   ENTER_GL();
358   gl_ctx = glXGetCurrentContext();
359   ret = get_context_from_GLXContext(gl_ctx);
360   LEAVE_GL();
361
362   if (ret) {
363     TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
364     return ret->hdc;
365   } else {
366     TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
367     return 0;
368   }
369 }
370
371 /***********************************************************************
372  *              wglGetLayerPaletteEntries (OPENGL32.@)
373  */
374 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
375                                      int iLayerPlane,
376                                      int iStart,
377                                      int cEntries,
378                                      const COLORREF *pcr) {
379   FIXME("(): stub !\n");
380
381   return 0;
382 }
383
384 /***********************************************************************
385  *              wglGetProcAddress (OPENGL32.@)
386  */
387 static int compar(const void *elt_a, const void *elt_b) {
388   return strcmp(((const OpenGL_extension *) elt_a)->name,
389                 ((const OpenGL_extension *) elt_b)->name);
390 }
391
392 static int wgl_compar(const void *elt_a, const void *elt_b) {
393   return strcmp(((const WGL_extension *) elt_a)->func_name,
394                 ((const WGL_extension *) elt_b)->func_name);
395 }
396
397 PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
398   void *local_func;
399   OpenGL_extension  ext;
400   OpenGL_extension *ext_ret;
401
402   TRACE("(%s)\n", lpszProc);
403
404   /* First, look if it's not already defined in the 'standard' OpenGL functions */
405   if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
406     TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
407     return local_func;
408   }
409
410   if (p_glXGetProcAddressARB == NULL) {
411     ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
412     return NULL;
413   }
414   
415   /* After that, search in the thunks to find the real name of the extension */
416   ext.name = (char *) lpszProc;
417   ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
418                                          extension_registry_size, sizeof(OpenGL_extension), compar);
419
420   if (ext_ret == NULL) {
421     WGL_extension wgl_ext, *wgl_ext_ret;
422
423     /* Try to find the function in the WGL extensions ... */
424     wgl_ext.func_name = (char *) lpszProc;
425     wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
426                                             wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
427
428     if (wgl_ext_ret == NULL) {
429       /* Some sanity checks :-) */
430       ENTER_GL();
431       local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
432       LEAVE_GL();
433       if (local_func != NULL) {
434         WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
435         return NULL;
436       }
437       
438       WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
439       return NULL;
440     } else {
441         void *ret = NULL;
442
443         if (wgl_ext_ret->func_init != NULL) {
444             const char *err_msg;
445             if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
446                                                   wgl_ext_ret->context)) == NULL) {
447                 ret = wgl_ext_ret->func_address;
448             } else {
449                 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
450                 return NULL;
451             }
452         } else {
453           ret = wgl_ext_ret->func_address;
454         }
455
456         if (ret)
457             TRACE(" returning WGL function  (%p)\n", ret);
458         return ret;
459     }
460   } else {
461     ENTER_GL();
462     local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
463     LEAVE_GL();
464     
465     /* After that, look at the extensions defined in the Linux OpenGL library */
466     if (local_func == NULL) {
467       char buf[256];
468       void *ret = NULL;
469
470       /* Remove the 3 last letters (EXT, ARB, ...).
471
472          I know that some extensions have more than 3 letters (MESA, NV,
473          INTEL, ...), but this is only a stop-gap measure to fix buggy
474          OpenGL drivers (moreover, it is only useful for old 1.0 apps
475          that query the glBindTextureEXT extension).
476       */
477       memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
478       buf[strlen(ext_ret->glx_name) - 3] = '\0';
479       TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
480
481       ret = GetProcAddress(opengl32_handle, buf);
482       if (ret != NULL) {
483         TRACE(" found function in main OpenGL library (%p) !\n", ret);
484       } else {
485         WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
486       }
487
488       return ret;
489     } else {
490       TRACE(" returning function  (%p)\n", ext_ret->func);
491       *(ext_ret->func_ptr) = local_func;
492
493       return ext_ret->func;
494     }
495   }
496 }
497
498 static int describeContext(Wine_GLContext* ctx) {
499   int tmp;
500   int ctx_vis_id;
501   TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis);
502   wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_FBCONFIG_ID, &tmp);
503   TRACE(" - FBCONFIG_ID 0x%x\n", tmp);
504   wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_VISUAL_ID, &tmp);
505   TRACE(" - VISUAL_ID 0x%x\n", tmp);
506   ctx_vis_id = tmp;
507   return ctx_vis_id;
508 }
509
510 static int describeDrawable(Wine_GLContext* ctx, Drawable drawable) {
511   int tmp;
512   int nElements;
513   int attribList[3] = { GLX_FBCONFIG_ID, 0, None };
514   GLXFBConfig *fbCfgs;
515
516   if (3 > wine_glx.version || NULL == wine_glx.p_glXQueryDrawable)  {
517     /** glXQueryDrawable not available so returns not supported */
518     return -1;
519   }
520
521   TRACE(" Drawable %p have :\n", (void*) drawable);
522   wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_WIDTH, (unsigned int*) &tmp);
523   TRACE(" - WIDTH as %d\n", tmp);
524   wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_HEIGHT, (unsigned int*) &tmp);
525   TRACE(" - HEIGHT as %d\n", tmp);
526   wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &tmp);
527   TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
528
529   attribList[1] = tmp;
530   fbCfgs = wine_glx.p_glXChooseFBConfig(ctx->display, DefaultScreen(ctx->display), attribList, &nElements);
531   if (fbCfgs == NULL) {
532     return -1;
533   }
534  
535   wine_glx.p_glXGetFBConfigAttrib(ctx->display, fbCfgs[0], GLX_VISUAL_ID, &tmp);
536   TRACE(" - VISUAL_ID as 0x%x\n", tmp);
537
538   XFree(fbCfgs);
539  
540   return tmp;
541 }
542
543 /***********************************************************************
544  *              wglMakeCurrent (OPENGL32.@)
545  */
546 BOOL WINAPI wglMakeCurrent(HDC hdc,
547                            HGLRC hglrc) {
548   BOOL ret;
549   DWORD type = GetObjectType(hdc);
550
551   TRACE("(%p,%p)\n", hdc, hglrc);
552
553   ENTER_GL();
554   if (hglrc == NULL) {
555       ret = glXMakeCurrent(default_display, None, NULL);
556       NtCurrentTeb()->glContext = NULL;
557   } else {
558       Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
559       Drawable drawable = get_drawable( hdc );
560       if (ctx->ctx == NULL) {
561         int draw_vis_id, ctx_vis_id;
562         VisualID visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
563         TRACE(" Wine desktop VISUAL_ID is 0x%x\n", (unsigned int) visualid);
564         draw_vis_id = describeDrawable(ctx, drawable);
565         ctx_vis_id = describeContext(ctx);
566
567         if (-1 == draw_vis_id || (draw_vis_id == visualid && draw_vis_id != ctx_vis_id)) {
568           /**
569            * Inherits from root window so reuse desktop visual
570            */
571           XVisualInfo template;
572           XVisualInfo *vis;
573           int num;
574           template.visualid = visualid;
575           vis = XGetVisualInfo(ctx->display, VisualIDMask, &template, &num);
576
577           TRACE(" Creating GLX Context\n");
578           ctx->ctx = glXCreateContext(ctx->display, vis, NULL, type == OBJ_MEMDC ? False : True);
579         } else {
580           TRACE(" Creating GLX Context\n");
581           ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True);
582         }
583         TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
584       }
585       TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
586       ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
587       NtCurrentTeb()->glContext = ctx;
588       if(ret && type == OBJ_MEMDC)
589       {
590           ctx->do_escape = TRUE;
591           glDrawBuffer(GL_FRONT_LEFT);
592       }
593   }
594   LEAVE_GL();
595   TRACE(" returning %s\n", (ret ? "True" : "False"));
596   return ret;
597 }
598
599 /***********************************************************************
600  *              wglMakeContextCurrentARB (OPENGL32.@)
601  */
602 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) 
603 {
604   BOOL ret;
605   TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
606
607   ENTER_GL();
608   if (hglrc == NULL) {
609     ret = glXMakeCurrent(default_display, None, NULL);
610   } else {
611     if (NULL == wine_glx.p_glXMakeContextCurrent) {
612       ret = FALSE;
613     } else {
614       Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
615       Drawable d_draw = get_drawable( hDrawDC );
616       Drawable d_read = get_drawable( hReadDC );
617       
618       if (ctx->ctx == NULL) {
619         ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, GetObjectType(hDrawDC) == OBJ_MEMDC ? False : True);
620         TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
621       }
622       ret = wine_glx.p_glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
623     }
624   }
625   LEAVE_GL();
626   
627   TRACE(" returning %s\n", (ret ? "True" : "False"));
628   return ret;
629 }
630
631 /***********************************************************************
632  *              wglGetCurrentReadDCARB (OPENGL32.@)
633  */
634 HDC WINAPI wglGetCurrentReadDCARB(void) 
635 {
636   GLXDrawable gl_d;
637   HDC ret;
638
639   TRACE("()\n");
640
641   ENTER_GL();
642   gl_d = glXGetCurrentReadDrawable();
643   ret = get_hdc_from_Drawable(gl_d);
644   LEAVE_GL();
645
646   TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
647   return ret;
648 }
649
650
651
652 /***********************************************************************
653  *              wglRealizeLayerPalette (OPENGL32.@)
654  */
655 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
656                                    int iLayerPlane,
657                                    BOOL bRealize) {
658   FIXME("()\n");
659
660   return FALSE;
661 }
662
663 /***********************************************************************
664  *              wglSetLayerPaletteEntries (OPENGL32.@)
665  */
666 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
667                                      int iLayerPlane,
668                                      int iStart,
669                                      int cEntries,
670                                      const COLORREF *pcr) {
671   FIXME("(): stub !\n");
672
673   return 0;
674 }
675
676 /***********************************************************************
677  *              wglShareLists (OPENGL32.@)
678  */
679 BOOL WINAPI wglShareLists(HGLRC hglrc1,
680                           HGLRC hglrc2) {
681   Wine_GLContext *org  = (Wine_GLContext *) hglrc1;
682   Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
683
684   TRACE("(%p, %p)\n", org, dest);
685
686   if (NULL != dest && dest->ctx != NULL) {
687     ERR("Could not share display lists, context already created !\n");
688     return FALSE;
689   } else {
690     if (org->ctx == NULL) {
691       ENTER_GL();
692       describeContext(org);
693       org->ctx = glXCreateContext(org->display, org->vis, NULL, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
694       LEAVE_GL();
695       TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
696     }
697     if (NULL != dest) {
698       ENTER_GL();
699       describeContext(dest);
700       /* Create the destination context with display lists shared */
701       dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
702       LEAVE_GL();
703       TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
704       return TRUE;
705     }
706   }
707   return FALSE;
708 }
709
710 /***********************************************************************
711  *              wglSwapLayerBuffers (OPENGL32.@)
712  */
713 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
714                                 UINT fuPlanes) {
715   TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
716
717   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
718     if (!SwapBuffers(hdc)) return FALSE;
719     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
720   }
721
722   if (fuPlanes) {
723     WARN("Following layers unhandled : %08x\n", fuPlanes);
724   }
725
726   return TRUE;
727 }
728
729 static BOOL internal_wglUseFontBitmaps(HDC hdc,
730                                        DWORD first,
731                                        DWORD count,
732                                        DWORD listBase,
733                                        DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
734 {
735     /* We are running using client-side rendering fonts... */
736     GLYPHMETRICS gm;
737     unsigned int glyph;
738     int size = 0;
739     void *bitmap = NULL, *gl_bitmap = NULL;
740     int org_alignment;
741
742     ENTER_GL();
743     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
744     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
745     LEAVE_GL();
746
747     for (glyph = first; glyph < first + count; glyph++) {
748         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
749         int height, width_int;
750
751         TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
752         if (needed_size == GDI_ERROR) {
753             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
754             goto error;
755         } else {
756             TRACE("  - needed size : %d\n", needed_size);
757         }
758
759         if (needed_size > size) {
760             size = needed_size;
761             HeapFree(GetProcessHeap(), 0, bitmap);
762             HeapFree(GetProcessHeap(), 0, gl_bitmap);
763             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
764             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
765         }
766         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
767         if (TRACE_ON(opengl)) {
768             unsigned int height, width, bitmask;
769             unsigned char *bitmap_ = (unsigned char *) bitmap;
770             
771             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
772             TRACE("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
773             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
774             if (needed_size != 0) {
775                 TRACE("  - bitmap :\n");
776                 for (height = 0; height < gm.gmBlackBoxY; height++) {
777                     TRACE("      ");
778                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
779                         if (bitmask == 0) {
780                             bitmap_ += 1;
781                             bitmask = 0x80;
782                         }
783                         if (*bitmap_ & bitmask)
784                             TRACE("*");
785                         else
786                             TRACE(" ");
787                     }
788                     bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
789                     TRACE("\n");
790                 }
791             }
792         }
793         
794         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
795          * glyph for it to be drawn properly.
796          */
797         if (needed_size != 0) {
798             width_int = (gm.gmBlackBoxX + 31) / 32;
799             for (height = 0; height < gm.gmBlackBoxY; height++) {
800                 int width;
801                 for (width = 0; width < width_int; width++) {
802                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
803                         ((int *) bitmap)[height * width_int + width];
804                 }
805             }
806         }
807         
808         ENTER_GL();
809         glNewList(listBase++, GL_COMPILE);
810         if (needed_size != 0) {
811             glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
812                      0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
813                      gm.gmCellIncX, gm.gmCellIncY,
814                      gl_bitmap);
815         } else {
816             /* This is the case of 'empty' glyphs like the space character */
817             glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
818         }
819         glEndList();
820         LEAVE_GL();
821     }
822     
823     ENTER_GL();
824     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
825     LEAVE_GL();
826     
827     HeapFree(GetProcessHeap(), 0, bitmap);
828     HeapFree(GetProcessHeap(), 0, gl_bitmap);
829     return TRUE;
830
831   error:
832     ENTER_GL();
833     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
834     LEAVE_GL();
835
836     HeapFree(GetProcessHeap(), 0, bitmap);
837     HeapFree(GetProcessHeap(), 0, gl_bitmap);
838     return FALSE;    
839 }
840
841 /***********************************************************************
842  *              wglUseFontBitmapsA (OPENGL32.@)
843  */
844 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
845                                DWORD first,
846                                DWORD count,
847                                DWORD listBase)
848 {
849   Font fid = get_font( hdc );
850
851   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
852
853   if (fid == 0) {
854       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
855   }
856
857   ENTER_GL();
858   /* I assume that the glyphs are at the same position for X and for Windows */
859   glXUseXFont(fid, first, count, listBase);
860   LEAVE_GL();
861   return TRUE;
862 }
863
864 /***********************************************************************
865  *              wglUseFontBitmapsW (OPENGL32.@)
866  */
867 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
868                                DWORD first,
869                                DWORD count,
870                                DWORD listBase)
871 {
872   Font fid = get_font( hdc );
873
874   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
875
876   if (fid == 0) {
877       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
878   }
879
880   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
881   
882   ENTER_GL();
883   /* I assume that the glyphs are at the same position for X and for Windows */
884   glXUseXFont(fid, first, count, listBase);
885   LEAVE_GL();
886   return TRUE;
887 }
888
889 #ifdef HAVE_GL_GLU_H
890
891 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
892 {
893     vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;  
894     vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;  
895     vertex[2] = 0.0;
896 }
897
898 static void tess_callback_vertex(GLvoid *vertex)
899 {
900     GLdouble *dbl = vertex;
901     TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
902     glVertex3dv(vertex);
903 }
904
905 static void tess_callback_begin(GLenum which)
906 {
907     TRACE("%d\n", which);
908     glBegin(which);
909 }
910
911 static void tess_callback_end(void)
912 {
913     TRACE("\n");
914     glEnd();
915 }
916
917 /***********************************************************************
918  *              wglUseFontOutlines_common
919  */
920 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
921                                       DWORD first,
922                                       DWORD count,
923                                       DWORD listBase,
924                                       FLOAT deviation,
925                                       FLOAT extrusion,
926                                       int format,
927                                       LPGLYPHMETRICSFLOAT lpgmf,
928                                       BOOL unicode)
929 {
930     UINT glyph;
931     const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
932     GLUtesselator *tess;
933     LOGFONTW lf;
934     HFONT old_font, unscaled_font;
935     UINT em_size = 1024;
936     RECT rc;
937
938     TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
939           listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
940
941
942     ENTER_GL();
943     tess = gluNewTess();
944     if(tess)
945     {
946         gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
947         gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
948         gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
949     }
950     LEAVE_GL();
951
952     if(!tess) return FALSE;
953
954     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
955     rc.left = rc.right = rc.bottom = 0;
956     rc.top = em_size;
957     DPtoLP(hdc, (POINT*)&rc, 2);
958     lf.lfHeight = -abs(rc.top - rc.bottom);
959     lf.lfOrientation = lf.lfEscapement = 0;
960     unscaled_font = CreateFontIndirectW(&lf);
961     old_font = SelectObject(hdc, unscaled_font);
962
963     for (glyph = first; glyph < first + count; glyph++)
964     {
965         DWORD needed;
966         GLYPHMETRICS gm;
967         BYTE *buf;
968         TTPOLYGONHEADER *pph;
969         TTPOLYCURVE *ppc;
970         GLdouble *vertices;
971
972         if(unicode)
973             needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
974         else
975             needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
976
977         if(needed == GDI_ERROR)
978             goto error;
979
980         buf = HeapAlloc(GetProcessHeap(), 0, needed);
981         vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
982
983         if(unicode)
984             GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
985         else
986             GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
987
988         TRACE("glyph %d\n", glyph);
989
990         if(lpgmf)
991         {
992             lpgmf->gmfBlackBoxX = gm.gmBlackBoxX / em_size;
993             lpgmf->gmfBlackBoxY = gm.gmBlackBoxY / em_size;
994             lpgmf->gmfptGlyphOrigin.x = gm.gmptGlyphOrigin.x / em_size;
995             lpgmf->gmfptGlyphOrigin.y = gm.gmptGlyphOrigin.y / em_size;
996             lpgmf->gmfCellIncX = gm.gmCellIncX / em_size;
997             lpgmf->gmfCellIncY = gm.gmCellIncY / em_size;
998             TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
999                   lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); 
1000             lpgmf++;
1001         }
1002
1003         ENTER_GL();
1004         glNewList(listBase++, GL_COMPILE);
1005         gluTessBeginPolygon(tess, NULL);
1006
1007         pph = (TTPOLYGONHEADER*)buf;
1008         while((BYTE*)pph < buf + needed)
1009         {
1010             TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
1011
1012             gluTessBeginContour(tess);
1013
1014             fixed_to_double(pph->pfxStart, em_size, vertices);
1015             gluTessVertex(tess, vertices, vertices);
1016             vertices += 3;
1017
1018             ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
1019             while((char*)ppc < (char*)pph + pph->cb)
1020             {
1021                 int i;
1022
1023                 switch(ppc->wType) {
1024                 case TT_PRIM_LINE:
1025                     for(i = 0; i < ppc->cpfx; i++)
1026                     {
1027                         TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
1028                         fixed_to_double(ppc->apfx[i], em_size, vertices); 
1029                         gluTessVertex(tess, vertices, vertices);
1030                         vertices += 3;
1031                     }
1032                     break;
1033
1034                 case TT_PRIM_QSPLINE:
1035                     for(i = 0; i < ppc->cpfx/2; i++)
1036                     {
1037                         /* FIXME just connecting the control points for now */
1038                         TRACE("\t\tcurve  %d,%d %d,%d\n",
1039                               ppc->apfx[i * 2].x.value,     ppc->apfx[i * 3].y.value,
1040                               ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
1041                         fixed_to_double(ppc->apfx[i * 2], em_size, vertices); 
1042                         gluTessVertex(tess, vertices, vertices);
1043                         vertices += 3;
1044                         fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); 
1045                         gluTessVertex(tess, vertices, vertices);
1046                         vertices += 3;
1047                     }
1048                     break;
1049                 default:
1050                     ERR("\t\tcurve type = %d\n", ppc->wType);
1051                     gluTessEndContour(tess);
1052                     goto error_in_list;
1053                 }
1054
1055                 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
1056                                      (ppc->cpfx - 1) * sizeof(POINTFX));
1057             }
1058             gluTessEndContour(tess);
1059             pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
1060         }
1061
1062 error_in_list:
1063         gluTessEndPolygon(tess);
1064         glEndList();
1065         LEAVE_GL();
1066         HeapFree(GetProcessHeap(), 0, buf);
1067         HeapFree(GetProcessHeap(), 0, vertices);
1068     }
1069
1070  error:
1071     DeleteObject(SelectObject(hdc, old_font));
1072     gluDeleteTess(tess);
1073     return TRUE;
1074
1075 }
1076
1077 #else /* HAVE_GL_GLU_H */
1078
1079 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
1080                                       DWORD first,
1081                                       DWORD count,
1082                                       DWORD listBase,
1083                                       FLOAT deviation,
1084                                       FLOAT extrusion,
1085                                       int format,
1086                                       LPGLYPHMETRICSFLOAT lpgmf,
1087                                       BOOL unicode)
1088 {
1089     FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
1090     return FALSE;
1091 }
1092
1093 #endif /* HAVE_GL_GLU_H */
1094
1095 /***********************************************************************
1096  *              wglUseFontOutlinesA (OPENGL32.@)
1097  */
1098 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
1099                                 DWORD first,
1100                                 DWORD count,
1101                                 DWORD listBase,
1102                                 FLOAT deviation,
1103                                 FLOAT extrusion,
1104                                 int format,
1105                                 LPGLYPHMETRICSFLOAT lpgmf)
1106 {
1107     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
1108 }
1109
1110 /***********************************************************************
1111  *              wglUseFontOutlinesW (OPENGL32.@)
1112  */
1113 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
1114                                 DWORD first,
1115                                 DWORD count,
1116                                 DWORD listBase,
1117                                 FLOAT deviation,
1118                                 FLOAT extrusion,
1119                                 int format,
1120                                 LPGLYPHMETRICSFLOAT lpgmf)
1121 {
1122     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
1123 }
1124
1125 const GLubyte * internal_glGetString(GLenum name) {
1126   const char* GL_Extensions = NULL;
1127   
1128   if (GL_EXTENSIONS != name) {
1129     return glGetString(name);
1130   }
1131
1132   if (NULL == internal_gl_extensions) {
1133     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
1134
1135     TRACE("GL_EXTENSIONS reported:\n");  
1136     if (NULL == GL_Extensions) {
1137       ERR("GL_EXTENSIONS returns NULL\n");      
1138       return NULL;
1139     } else {
1140       size_t len = strlen(GL_Extensions);
1141       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
1142
1143       while (*GL_Extensions != 0x00) {
1144         const char* Start = GL_Extensions;
1145         char        ThisExtn[256];
1146          
1147         memset(ThisExtn, 0x00, sizeof(ThisExtn));
1148         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
1149           GL_Extensions++;
1150         }
1151         memcpy(ThisExtn, Start, (GL_Extensions - Start));
1152         TRACE("- %s:", ThisExtn);
1153         
1154         /* test if supported API is disabled by config */
1155         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
1156           strcat(internal_gl_extensions, " ");
1157           strcat(internal_gl_extensions, ThisExtn);
1158           TRACE(" active\n");
1159         } else {
1160           TRACE(" deactived (by config)\n");
1161         }
1162
1163         if (*GL_Extensions == ' ') GL_Extensions++;
1164       }
1165     }
1166   }
1167   return (const GLubyte *) internal_gl_extensions;
1168 }
1169
1170 void internal_glGetIntegerv(GLenum pname, GLint* params) {
1171   glGetIntegerv(pname, params);
1172   if (pname == GL_DEPTH_BITS) { 
1173     GLXContext gl_ctx = glXGetCurrentContext();
1174     Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
1175     /*TRACE("returns Wine Ctx as %p\n", ret);*/
1176     /** 
1177      * if we cannot find a Wine Context
1178      * we only have the default wine desktop context, 
1179      * so if we have only a 24 depth say we have 32
1180      */
1181     if (NULL == ret && 24 == *params) { 
1182       *params = 32;
1183     }
1184     TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
1185   }
1186   if (pname == GL_ALPHA_BITS) {
1187     GLint tmp;
1188     GLXContext gl_ctx = glXGetCurrentContext();
1189     Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
1190     glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
1191     TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
1192     *params = tmp;
1193   }
1194 }
1195
1196
1197 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
1198    include all dependencies
1199 */
1200 #ifndef SONAME_LIBGL
1201 #define SONAME_LIBGL "libGL.so"
1202 #endif
1203
1204 static void wgl_initialize_glx(Display *display, int screen, glXGetProcAddressARB_t proc) 
1205 {
1206   const char *server_glx_version = glXQueryServerString(display, screen, GLX_VERSION);
1207   const char *server_glx_extensions = glXQueryServerString(display, screen, GLX_EXTENSIONS);
1208   /*
1209   const char *client_glx_version = glXGetClientString(display, GLX_VERSION);
1210   const char *client_glx_extensions = glXGetClientString(display, GLX_EXTENSIONS);
1211   const char *glx_extensions = glXQueryExtensionsString(display, screen);
1212   */
1213
1214   memset(&wine_glx, 0, sizeof(wine_glx));
1215
1216   if (!strcmp("1.2", server_glx_version)) {
1217     wine_glx.version = 2;
1218   } else {
1219     wine_glx.version = 3;
1220   }
1221
1222   if (2 < wine_glx.version) {
1223     wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfig");
1224     wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttrib");
1225     wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfig");
1226
1227     /*wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");*/
1228     wine_glx.p_glXQueryDrawable = proc( (const GLubyte *) "glXQueryDrawable");
1229   } else {
1230     if (NULL != strstr(server_glx_extensions, "GLX_SGIX_fbconfig")) {
1231       wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfigSGIX");
1232       wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttribSGIX");
1233       wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfigSGIX");
1234     } else {
1235       ERR(" glx_version as %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", server_glx_version);
1236     }
1237   }
1238   /** try anyway to retrieve that calls, maybe they works using glx client tricks */
1239   wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");
1240   wine_glx.p_glXMakeContextCurrent = proc( (const GLubyte *) "glXMakeContextCurrent");
1241 }
1242
1243 /* This is for brain-dead applications that use OpenGL functions before even
1244    creating a rendering context.... */
1245 static BOOL process_attach(void)
1246 {
1247   XWindowAttributes win_attr;
1248   Visual *rootVisual;
1249   int num;
1250   XVisualInfo template;
1251   HDC hdc;
1252   XVisualInfo *vis = NULL;
1253   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
1254   HMODULE mod = GetModuleHandleA( "winex11.drv" );
1255   void *opengl_handle;
1256   DWORD size = sizeof(internal_gl_disabled_extensions);
1257   HKEY hkey = 0;
1258
1259   if (!root || !mod)
1260   {
1261       ERR("X11DRV not loaded. Cannot create default context.\n");
1262       return FALSE;
1263   }
1264
1265   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
1266   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
1267
1268   hdc = GetDC(0);
1269   default_display = get_display( hdc );
1270   ReleaseDC( 0, hdc );
1271   if (!default_display)
1272   {
1273       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
1274       return FALSE;
1275   }
1276
1277   ENTER_GL();
1278
1279   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
1280      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
1281      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
1282      with mismatched visuals.  Note that the Root Window visual may not be double
1283      buffered, so apps actually attempting to render this way may flicker */
1284   if (XGetWindowAttributes( default_display, root, &win_attr ))
1285   {
1286     rootVisual = win_attr.visual;
1287   }
1288   else
1289   {
1290     /* Get the default visual, since we can't seem to get the attributes from the
1291        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
1292     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
1293   }
1294
1295   template.visualid = XVisualIDFromVisual(rootVisual);
1296   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
1297   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
1298   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
1299   XFree(vis);
1300   LEAVE_GL();
1301
1302   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
1303   if (opengl_handle != NULL) {
1304    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
1305    wine_dlclose(opengl_handle, NULL, 0);
1306    if (p_glXGetProcAddressARB == NULL)
1307            TRACE("could not find glXGetProcAddressARB in libGL.\n");
1308   }
1309
1310   internal_gl_disabled_extensions[0] = 0;
1311   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
1312     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
1313       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
1314     }
1315     RegCloseKey(hkey);
1316   }
1317
1318   if (default_cx == NULL) {
1319     ERR("Could not create default context.\n");
1320   }
1321   else
1322   {
1323     /* After context initialize also the list of supported WGL extensions. */
1324     wgl_initialize_glx(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB);
1325     wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
1326   }
1327   return TRUE;
1328 }
1329
1330
1331 /**********************************************************************/
1332
1333 static void process_detach(void)
1334 {
1335   glXDestroyContext(default_display, default_cx);
1336
1337   /* Do not leak memory... */
1338   wgl_ext_finalize_extensions();
1339   HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
1340 }
1341
1342 /***********************************************************************
1343  *           OpenGL initialisation routine
1344  */
1345 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1346 {
1347     switch(reason)
1348     {
1349     case DLL_PROCESS_ATTACH:
1350         opengl32_handle = hinst;
1351         DisableThreadLibraryCalls(hinst);
1352         return process_attach();
1353     case DLL_PROCESS_DETACH:
1354         process_detach();
1355         break;
1356     }
1357     return TRUE;
1358 }