Fix wrong use of the PFD_GENERIC_ACCELERATED flag. It indicates that
[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 (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
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   }
580
581   return TRUE;
582 }
583
584 /***********************************************************************
585  *              wglSwapLayerBuffers (OPENGL32.@)
586  */
587 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
588                                 UINT fuPlanes) {
589   TRACE("(%p, %08x)\n", hdc, fuPlanes);
590
591   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
592     if (!SwapBuffers(hdc)) return FALSE;
593     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
594   }
595
596   if (fuPlanes) {
597     WARN("Following layers unhandled : %08x\n", fuPlanes);
598   }
599
600   return TRUE;
601 }
602
603 static BOOL internal_wglUseFontBitmaps(HDC hdc,
604                                        DWORD first,
605                                        DWORD count,
606                                        DWORD listBase,
607                                        DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
608 {
609     /* We are running using client-side rendering fonts... */
610     GLYPHMETRICS gm;
611     unsigned int glyph;
612     int size = 0;
613     void *bitmap = NULL, *gl_bitmap = NULL;
614     int org_alignment;
615
616     ENTER_GL();
617     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
618     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
619     LEAVE_GL();
620
621     for (glyph = first; glyph < first + count; glyph++) {
622         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
623         int height, width_int;
624
625         TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
626         if (needed_size == GDI_ERROR) {
627             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
628             goto error;
629         } else {
630             TRACE("  - needed size : %d\n", needed_size);
631         }
632
633         if (needed_size > size) {
634             size = needed_size;
635             HeapFree(GetProcessHeap(), 0, bitmap);
636             HeapFree(GetProcessHeap(), 0, gl_bitmap);
637             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
638             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
639         }
640         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
641         if (TRACE_ON(opengl)) {
642             unsigned int height, width, bitmask;
643             unsigned char *bitmap_ = (unsigned char *) bitmap;
644             
645             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
646             TRACE("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
647             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
648             if (needed_size != 0) {
649                 TRACE("  - bitmap :\n");
650                 for (height = 0; height < gm.gmBlackBoxY; height++) {
651                     TRACE("      ");
652                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
653                         if (bitmask == 0) {
654                             bitmap_ += 1;
655                             bitmask = 0x80;
656                         }
657                         if (*bitmap_ & bitmask)
658                             TRACE("*");
659                         else
660                             TRACE(" ");
661                     }
662                     bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
663                     TRACE("\n");
664                 }
665             }
666         }
667         
668         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
669          * glyph for it to be drawn properly.
670          */
671         if (needed_size != 0) {
672             width_int = (gm.gmBlackBoxX + 31) / 32;
673             for (height = 0; height < gm.gmBlackBoxY; height++) {
674                 int width;
675                 for (width = 0; width < width_int; width++) {
676                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
677                         ((int *) bitmap)[height * width_int + width];
678                 }
679             }
680         }
681         
682         ENTER_GL();
683         glNewList(listBase++, GL_COMPILE);
684         if (needed_size != 0) {
685             glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
686                      0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
687                      gm.gmCellIncX, gm.gmCellIncY,
688                      gl_bitmap);
689         } else {
690             /* This is the case of 'empty' glyphs like the space character */
691             glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
692         }
693         glEndList();
694         LEAVE_GL();
695     }
696     
697     ENTER_GL();
698     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
699     LEAVE_GL();
700     
701     HeapFree(GetProcessHeap(), 0, bitmap);
702     HeapFree(GetProcessHeap(), 0, gl_bitmap);
703     return TRUE;
704
705   error:
706     ENTER_GL();
707     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
708     LEAVE_GL();
709
710     HeapFree(GetProcessHeap(), 0, bitmap);
711     HeapFree(GetProcessHeap(), 0, gl_bitmap);
712     return FALSE;    
713 }
714
715 /***********************************************************************
716  *              wglUseFontBitmapsA (OPENGL32.@)
717  */
718 BOOL WINAPI wglUseFontBitmapsA(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, GetGlyphOutlineA);
729   }
730
731   ENTER_GL();
732   /* I assume that the glyphs are at the same position for X and for Windows */
733   glXUseXFont(fid, first, count, listBase);
734   LEAVE_GL();
735   return TRUE;
736 }
737
738 /***********************************************************************
739  *              wglUseFontBitmapsW (OPENGL32.@)
740  */
741 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
742                                DWORD first,
743                                DWORD count,
744                                DWORD listBase)
745 {
746   Font fid = get_font( hdc );
747
748   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
749
750   if (fid == 0) {
751       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
752   }
753
754   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
755   
756   ENTER_GL();
757   /* I assume that the glyphs are at the same position for X and for Windows */
758   glXUseXFont(fid, first, count, listBase);
759   LEAVE_GL();
760   return TRUE;
761 }
762
763 /***********************************************************************
764  *              wglUseFontOutlinesA (OPENGL32.@)
765  */
766 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
767                                 DWORD first,
768                                 DWORD count,
769                                 DWORD listBase,
770                                 FLOAT deviation,
771                                 FLOAT extrusion,
772                                 int format,
773                                 LPGLYPHMETRICSFLOAT lpgmf) {
774   FIXME("(): stub !\n");
775
776   return FALSE;
777 }
778
779 const GLubyte * internal_glGetString(GLenum name) {
780   const char* GL_Extensions = NULL;
781   
782   if (GL_EXTENSIONS != name) {
783     return glGetString(name);
784   }
785
786   if (NULL == internal_gl_extensions) {
787     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
788
789     TRACE("GL_EXTENSIONS reported:\n");  
790     if (NULL == GL_Extensions) {
791       ERR("GL_EXTENSIONS returns NULL\n");      
792       return NULL;
793     } else {
794       size_t len = strlen(GL_Extensions);
795       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
796
797       while (*GL_Extensions != 0x00) {
798         const char* Start = GL_Extensions;
799         char        ThisExtn[256];
800          
801         memset(ThisExtn, 0x00, sizeof(ThisExtn));
802         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
803           GL_Extensions++;
804         }
805         memcpy(ThisExtn, Start, (GL_Extensions - Start));
806         TRACE("- %s:", ThisExtn);
807         
808         /* test if supported API is disabled by config */
809         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
810           strcat(internal_gl_extensions, " ");
811           strcat(internal_gl_extensions, ThisExtn);
812           TRACE(" active\n");
813         } else {
814           TRACE(" deactived (by config)\n");
815         }
816
817         if (*GL_Extensions == ' ') GL_Extensions++;
818       }
819     }
820   }
821   return (const GLubyte *) internal_gl_extensions;
822 }
823
824 void internal_glGetIntegerv(GLenum pname, GLint* params) {
825   glGetIntegerv(pname, params); 
826   if (pname == GL_ALPHA_BITS) {
827     GLint tmp;
828     GLXContext gl_ctx = glXGetCurrentContext();
829     Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
830     glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
831     TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
832     *params = tmp;
833   }
834 }
835
836
837 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
838    include all dependencies
839 */
840 #ifndef SONAME_LIBGL
841 #define SONAME_LIBGL "libGL.so"
842 #endif
843
844 /* This is for brain-dead applications that use OpenGL functions before even
845    creating a rendering context.... */
846 static BOOL process_attach(void)
847 {
848   XWindowAttributes win_attr;
849   Visual *rootVisual;
850   int num;
851   XVisualInfo template;
852   HDC hdc;
853   XVisualInfo *vis = NULL;
854   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
855   HMODULE mod = GetModuleHandleA( "winex11.drv" );
856   void *opengl_handle;
857   DWORD size = sizeof(internal_gl_disabled_extensions);
858   HKEY hkey = 0;
859
860   if (!root || !mod)
861   {
862       ERR("X11DRV not loaded. Cannot create default context.\n");
863       return FALSE;
864   }
865
866   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
867   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
868
869   hdc = GetDC(0);
870   default_display = get_display( hdc );
871   ReleaseDC( 0, hdc );
872   if (!default_display)
873   {
874       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
875       return FALSE;
876   }
877
878   ENTER_GL();
879
880   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
881      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
882      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
883      with mismatched visuals.  Note that the Root Window visual may not be double
884      buffered, so apps actually attempting to render this way may flicker */
885   if (XGetWindowAttributes( default_display, root, &win_attr ))
886   {
887     rootVisual = win_attr.visual;
888   }
889   else
890   {
891     /* Get the default visual, since we can't seem to get the attributes from the
892        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
893     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
894   }
895
896   template.visualid = XVisualIDFromVisual(rootVisual);
897   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
898   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
899   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
900   XFree(vis);
901   LEAVE_GL();
902
903   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
904   if (opengl_handle != NULL) {
905    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
906    wine_dlclose(opengl_handle, NULL, 0);
907    if (p_glXGetProcAddressARB == NULL)
908            TRACE("could not find glXGetProcAddressARB in libGL.\n");
909   }
910
911   internal_gl_disabled_extensions[0] = 0;
912   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
913     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
914       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
915     }
916     RegCloseKey(hkey);
917   }
918
919   if (default_cx == NULL) {
920     ERR("Could not create default context.\n");
921   }
922   else
923   {
924     /* After context initialize also the list of supported WGL extensions. */
925     wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
926   }
927   return TRUE;
928 }
929
930
931 /**********************************************************************/
932
933 static void process_detach(void)
934 {
935   glXDestroyContext(default_display, default_cx);
936
937   /* Do not leak memory... */
938   wgl_ext_finalize_extensions();
939   if (NULL != internal_gl_extensions) {
940     HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
941   }
942 }
943
944 /***********************************************************************
945  *           OpenGL initialisation routine
946  */
947 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
948 {
949     switch(reason)
950     {
951     case DLL_PROCESS_ATTACH:
952         opengl32_handle = hinst;
953         DisableThreadLibraryCalls(hinst);
954         return process_attach();
955     case DLL_PROCESS_DETACH:
956         process_detach();
957         break;
958     }
959     return TRUE;
960 }