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