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