Better computations to have uniformly sized parts scaled in both
[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( (const GLubyte *) 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( (const GLubyte*) 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) for %p\n", ctx->ctx, ctx->vis);
449       }
450       TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
451       ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
452   }
453   LEAVE_GL();
454   TRACE(" returning %s\n", (ret ? "True" : "False"));
455   return ret;
456 }
457
458 /***********************************************************************
459  *              wglMakeContextCurrentARB (OPENGL32.@)
460  */
461 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) 
462 {
463   BOOL ret;
464   TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
465
466   ENTER_GL();
467   if (hglrc == NULL) {
468       ret = glXMakeCurrent(default_display, None, NULL);
469   } else {
470     Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
471     Drawable d_draw = get_drawable( hDrawDC );
472     Drawable d_read = get_drawable( hReadDC );
473
474     if (ctx->ctx == NULL) {
475       ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
476       TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
477     }
478     ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
479   }
480   LEAVE_GL();
481   
482   TRACE(" returning %s\n", (ret ? "True" : "False"));
483   return ret;
484 }
485
486 /***********************************************************************
487  *              wglGetCurrentReadDCARB (OPENGL32.@)
488  */
489 HDC WINAPI wglGetCurrentReadDCARB(void) 
490 {
491   GLXDrawable gl_d;
492   HDC ret;
493
494   TRACE("()\n");
495
496   ENTER_GL();
497   gl_d = glXGetCurrentReadDrawable();
498   ret = get_hdc_from_Drawable(gl_d);
499   LEAVE_GL();
500
501   TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
502   return ret;
503 }
504
505
506
507 /***********************************************************************
508  *              wglRealizeLayerPalette (OPENGL32.@)
509  */
510 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
511                                    int iLayerPlane,
512                                    BOOL bRealize) {
513   FIXME("()\n");
514
515   return FALSE;
516 }
517
518 /***********************************************************************
519  *              wglSetLayerPaletteEntries (OPENGL32.@)
520  */
521 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
522                                      int iLayerPlane,
523                                      int iStart,
524                                      int cEntries,
525                                      const COLORREF *pcr) {
526   FIXME("(): stub !\n");
527
528   return 0;
529 }
530
531 /***********************************************************************
532  *              wglShareLists (OPENGL32.@)
533  */
534 BOOL WINAPI wglShareLists(HGLRC hglrc1,
535                           HGLRC hglrc2) {
536   Wine_GLContext *org  = (Wine_GLContext *) hglrc1;
537   Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
538
539   TRACE("(%p, %p)\n", org, dest);
540
541   if (dest->ctx != NULL) {
542     ERR("Could not share display lists, context already created !\n");
543     return FALSE;
544   } else {
545     if (org->ctx == NULL) {
546       ENTER_GL();
547       org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
548       LEAVE_GL();
549       TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
550     }
551
552     ENTER_GL();
553     /* Create the destination context with display lists shared */
554     dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
555     LEAVE_GL();
556     TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
557   }
558
559   return TRUE;
560 }
561
562 /***********************************************************************
563  *              wglSwapLayerBuffers (OPENGL32.@)
564  */
565 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
566                                 UINT fuPlanes) {
567   TRACE("(%p, %08x)\n", hdc, fuPlanes);
568
569   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
570     if (!SwapBuffers(hdc)) return FALSE;
571     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
572   }
573
574   if (fuPlanes) {
575     WARN("Following layers unhandled : %08x\n", fuPlanes);
576   }
577
578   return TRUE;
579 }
580
581 static BOOL internal_wglUseFontBitmaps(HDC hdc,
582                                        DWORD first,
583                                        DWORD count,
584                                        DWORD listBase,
585                                        DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
586 {
587     /* We are running using client-side rendering fonts... */
588     GLYPHMETRICS gm;
589     unsigned int glyph;
590     int size = 0;
591     void *bitmap = NULL, *gl_bitmap = NULL;
592     int org_alignment;
593
594     ENTER_GL();
595     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
596     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
597     LEAVE_GL();
598
599     for (glyph = first; glyph < first + count; glyph++) {
600         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
601         int height, width_int;
602
603         TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
604         if (needed_size == GDI_ERROR) {
605             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
606             goto error;
607         } else {
608             TRACE("  - needed size : %d\n", needed_size);
609         }
610
611         if (needed_size > size) {
612             size = needed_size;
613             HeapFree(GetProcessHeap(), 0, bitmap);
614             HeapFree(GetProcessHeap(), 0, gl_bitmap);
615             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
616             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
617         }
618         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
619         if (TRACE_ON(opengl)) {
620             unsigned int height, width, bitmask;
621             unsigned char *bitmap_ = (unsigned char *) bitmap;
622             
623             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
624             TRACE("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
625             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
626             if (needed_size != 0) {
627                 TRACE("  - bitmap : \n");
628                 for (height = 0; height < gm.gmBlackBoxY; height++) {
629                     TRACE("      ");
630                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
631                         if (bitmask == 0) {
632                             bitmap_ += 1;
633                             bitmask = 0x80;
634                         }
635                         if (*bitmap_ & bitmask)
636                             DPRINTF("*");
637                         else
638                             DPRINTF(" ");
639                     }
640                     bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
641                     DPRINTF("\n");
642                 }
643             }
644         }
645         
646         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
647          * glyph for it to be drawn properly.
648          */
649         if (needed_size != 0) {
650             width_int = (gm.gmBlackBoxX + 31) / 32;
651             for (height = 0; height < gm.gmBlackBoxY; height++) {
652                 int width;
653                 for (width = 0; width < width_int; width++) {
654                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
655                         ((int *) bitmap)[height * width_int + width];
656                 }
657             }
658         }
659         
660         ENTER_GL();
661         glNewList(listBase++, GL_COMPILE);
662         if (needed_size != 0) {
663             glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
664                      0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
665                      gm.gmCellIncX, gm.gmCellIncY,
666                      gl_bitmap);
667         } else {
668             /* This is the case of 'empty' glyphs like the space character */
669             glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
670         }
671         glEndList();
672         LEAVE_GL();
673     }
674     
675     ENTER_GL();
676     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
677     LEAVE_GL();
678     
679     HeapFree(GetProcessHeap(), 0, bitmap);
680     HeapFree(GetProcessHeap(), 0, gl_bitmap);
681     return TRUE;
682
683   error:
684     ENTER_GL();
685     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
686     LEAVE_GL();
687
688     HeapFree(GetProcessHeap(), 0, bitmap);
689     HeapFree(GetProcessHeap(), 0, gl_bitmap);
690     return FALSE;    
691 }
692
693 /***********************************************************************
694  *              wglUseFontBitmapsA (OPENGL32.@)
695  */
696 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
697                                DWORD first,
698                                DWORD count,
699                                DWORD listBase)
700 {
701   Font fid = get_font( hdc );
702
703   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
704
705   if (fid == 0) {
706       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
707   }
708
709   ENTER_GL();
710   /* I assume that the glyphs are at the same position for X and for Windows */
711   glXUseXFont(fid, first, count, listBase);
712   LEAVE_GL();
713   return TRUE;
714 }
715
716 /***********************************************************************
717  *              wglUseFontBitmapsW (OPENGL32.@)
718  */
719 BOOL WINAPI wglUseFontBitmapsW(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, GetGlyphOutlineW);
730   }
731
732   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
733   
734   ENTER_GL();
735   /* I assume that the glyphs are at the same position for X and for Windows */
736   glXUseXFont(fid, first, count, listBase);
737   LEAVE_GL();
738   return TRUE;
739 }
740
741 /***********************************************************************
742  *              wglUseFontOutlinesA (OPENGL32.@)
743  */
744 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
745                                 DWORD first,
746                                 DWORD count,
747                                 DWORD listBase,
748                                 FLOAT deviation,
749                                 FLOAT extrusion,
750                                 int format,
751                                 LPGLYPHMETRICSFLOAT lpgmf) {
752   FIXME("(): stub !\n");
753
754   return FALSE;
755 }
756
757 const GLubyte * internal_glGetString(GLenum name) {
758   const char* GL_Extensions = NULL;
759   
760   if (GL_EXTENSIONS != name) {
761     return glGetString(name);
762   }
763
764   if (NULL == internal_gl_extensions) {
765     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
766
767     TRACE("GL_EXTENSIONS reported:\n");  
768     if (NULL == GL_Extensions) {
769       ERR("GL_EXTENSIONS returns NULL\n");      
770       return NULL;
771     } else {
772       size_t len = strlen(GL_Extensions);
773       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
774
775       while (*GL_Extensions != 0x00) {
776         const char* Start = GL_Extensions;
777         char        ThisExtn[256];
778          
779         memset(ThisExtn, 0x00, sizeof(ThisExtn));
780         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
781           GL_Extensions++;
782         }
783         memcpy(ThisExtn, Start, (GL_Extensions - Start));
784         TRACE("- %s:", ThisExtn);
785         
786         /* test if supported API is disabled by config */
787         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
788           strcat(internal_gl_extensions, " ");
789           strcat(internal_gl_extensions, ThisExtn);
790           TRACE(" active\n");
791         } else {
792           TRACE(" deactived (by config)\n");
793         }
794
795         if (*GL_Extensions == ' ') GL_Extensions++;
796       }
797     }
798   }
799   return (const GLubyte *) internal_gl_extensions;
800 }
801
802
803 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
804    include all dependencies
805 */
806 #ifndef SONAME_LIBGL
807 #define SONAME_LIBGL "libGL.so"
808 #endif
809
810 /* This is for brain-dead applications that use OpenGL functions before even
811    creating a rendering context.... */
812 static BOOL process_attach(void)
813 {
814   XWindowAttributes win_attr;
815   Visual *rootVisual;
816   int num;
817   XVisualInfo template;
818   HDC hdc;
819   XVisualInfo *vis = NULL;
820   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
821   HMODULE mod = GetModuleHandleA( "winex11.drv" );
822   void *opengl_handle;
823   DWORD size = sizeof(internal_gl_disabled_extensions);
824   HKEY hkey = 0;
825
826   if (!root || !mod)
827   {
828       ERR("X11DRV not loaded. Cannot create default context.\n");
829       return FALSE;
830   }
831
832   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
833   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
834
835   hdc = GetDC(0);
836   default_display = get_display( hdc );
837   ReleaseDC( 0, hdc );
838   if (!default_display)
839   {
840       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
841       return FALSE;
842   }
843
844   ENTER_GL();
845
846   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
847      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
848      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
849      with mismatched visuals.  Note that the Root Window visual may not be double
850      buffered, so apps actually attempting to render this way may flicker */
851   if (XGetWindowAttributes( default_display, root, &win_attr ))
852   {
853     rootVisual = win_attr.visual;
854   }
855   else
856   {
857     /* Get the default visual, since we can't seem to get the attributes from the
858        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
859     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
860   }
861
862   template.visualid = XVisualIDFromVisual(rootVisual);
863   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
864   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
865   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
866   XFree(vis);
867   LEAVE_GL();
868
869   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
870   if (opengl_handle != NULL) {
871    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
872    wine_dlclose(opengl_handle, NULL, 0);
873    if (p_glXGetProcAddressARB == NULL)
874            TRACE("could not find glXGetProcAddressARB in libGL.\n");
875   }
876
877   internal_gl_disabled_extensions[0] = 0;
878   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
879     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
880       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
881     }
882     RegCloseKey(hkey);
883   }
884
885   if (default_cx == NULL) {
886     ERR("Could not create default context.\n");
887   }
888   else
889   {
890     /* After context initialize also the list of supported WGL extensions. */
891     wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
892   }
893   return TRUE;
894 }
895
896
897 /**********************************************************************/
898
899 static void process_detach(void)
900 {
901   glXDestroyContext(default_display, default_cx);
902
903   /* Do not leak memory... */
904   wgl_ext_finalize_extensions();
905   if (NULL != internal_gl_extensions) {
906     HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
907   }
908 }
909
910 /***********************************************************************
911  *           OpenGL initialisation routine
912  */
913 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
914 {
915     switch(reason)
916     {
917     case DLL_PROCESS_ATTACH:
918         opengl32_handle = hinst;
919         DisableThreadLibraryCalls(hinst);
920         return process_attach();
921     case DLL_PROCESS_DETACH:
922         process_detach();
923         break;
924     }
925     return TRUE;
926 }