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