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