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