wgl: Move wglDeleteContext to gdi32.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #include "wingdi.h"
34 #include "winternl.h"
35 #include "winnt.h"
36
37 #include "opengl_ext.h"
38 #ifdef HAVE_GL_GLU_H
39 #undef far
40 #undef near
41 #include <GL/glu.h>
42 #endif
43 #include "wine/library.h"
44 #include "wine/debug.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
47 WINE_DECLARE_DEBUG_CHANNEL(opengl);
48
49 typedef struct wine_wgl_s {
50     PROC WINAPI  (*p_wglGetProcAddress)(LPCSTR  lpszProc);
51
52     void WINAPI  (*p_wglGetIntegerv)(GLenum pname, GLint* params);
53 } wine_wgl_t;
54
55 /** global wgl object */
56 static wine_wgl_t wine_wgl;
57
58 /* x11drv GDI escapes */
59 #define X11DRV_ESCAPE 6789
60 enum x11drv_escape_codes
61 {
62     X11DRV_GET_DISPLAY,         /* get X11 display for a DC */
63     X11DRV_GET_DRAWABLE,        /* get current drawable for a DC */
64     X11DRV_GET_FONT,            /* get current X font for a DC */
65     X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
66     X11DRV_START_EXPOSURES,     /* start graphics exposures */
67     X11DRV_END_EXPOSURES,       /* end graphics exposures */
68     X11DRV_GET_DCE,             /* get the DCE pointer */
69     X11DRV_SET_DCE,             /* set the DCE pointer */
70     X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
71     X11DRV_SYNC_PIXMAP          /* sync the dibsection to its pixmap */
72 };
73
74 void (*wine_tsx11_lock_ptr)(void) = NULL;
75 void (*wine_tsx11_unlock_ptr)(void) = NULL;
76
77 static GLXContext default_cx = NULL;
78 static Display *default_display;  /* display to use for default context */
79
80 static HMODULE opengl32_handle;
81
82 static void* (*p_glXGetProcAddressARB)(const GLubyte *);
83
84 static char  internal_gl_disabled_extensions[512];
85 static char* internal_gl_extensions = NULL;
86
87 typedef struct wine_glcontext {
88   HDC hdc;
89   Display *display;
90   XVisualInfo *vis;
91   GLXFBConfig fb_conf;
92   GLXContext ctx;
93   BOOL do_escape;
94   struct wine_glcontext *next;
95   struct wine_glcontext *prev;
96 } Wine_GLContext;
97
98 void enter_gl(void)
99 {
100     Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
101     
102     if (curctx && curctx->do_escape)
103     {
104         enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
105         ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
106     }
107
108     wine_tsx11_lock_ptr();
109     return;
110 }
111
112 /* retrieve the X display to use on a given DC */
113 inline static Display *get_display( HDC hdc )
114 {
115     Display *display;
116     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
117
118     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
119                     sizeof(display), (LPSTR)&display )) display = NULL;
120     return display;
121 }
122
123 /***********************************************************************
124  *              wglCreateLayerContext (OPENGL32.@)
125  */
126 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
127                                    int iLayerPlane) {
128   TRACE("(%p,%d)\n", hdc, iLayerPlane);
129
130   if (iLayerPlane == 0) {
131       return wglCreateContext(hdc);
132   }
133   FIXME(" no handler for layer %d\n", iLayerPlane);
134
135   return NULL;
136 }
137
138 /***********************************************************************
139  *              wglCopyContext (OPENGL32.@)
140  */
141 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
142                            HGLRC hglrcDst,
143                            UINT mask) {
144   FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
145
146   return FALSE;
147 }
148
149 /***********************************************************************
150  *              wglDescribeLayerPlane (OPENGL32.@)
151  */
152 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
153                                   int iPixelFormat,
154                                   int iLayerPlane,
155                                   UINT nBytes,
156                                   LPLAYERPLANEDESCRIPTOR plpd) {
157   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
158
159   return FALSE;
160 }
161
162 /***********************************************************************
163  *              wglGetLayerPaletteEntries (OPENGL32.@)
164  */
165 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
166                                      int iLayerPlane,
167                                      int iStart,
168                                      int cEntries,
169                                      const COLORREF *pcr) {
170   FIXME("(): stub !\n");
171
172   return 0;
173 }
174
175 /***********************************************************************
176  *              wglGetProcAddress (OPENGL32.@)
177  */
178 static int compar(const void *elt_a, const void *elt_b) {
179   return strcmp(((const OpenGL_extension *) elt_a)->name,
180                 ((const OpenGL_extension *) elt_b)->name);
181 }
182
183 PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
184   void *local_func;
185   OpenGL_extension  ext;
186   const OpenGL_extension *ext_ret;
187
188   TRACE("(%s)\n", lpszProc);
189
190   /* First, look if it's not already defined in the 'standard' OpenGL functions */
191   if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
192     TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
193     return local_func;
194   }
195
196   if (p_glXGetProcAddressARB == NULL) {
197     ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
198     return NULL;
199   }
200   
201   /* After that, search in the thunks to find the real name of the extension */
202   ext.name = lpszProc;
203   ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
204                                          extension_registry_size, sizeof(OpenGL_extension), compar);
205
206   /* If nothing was found, we are looking for a WGL extension */
207   if (ext_ret == NULL) {
208     return wine_wgl.p_wglGetProcAddress(lpszProc);
209   } else { /* We are looking for an OpenGL extension */
210     const char *glx_name = ext_ret->glx_name ? ext_ret->glx_name : ext_ret->name;
211     ENTER_GL();
212     local_func = p_glXGetProcAddressARB( (const GLubyte*)glx_name);
213     LEAVE_GL();
214     
215     /* After that, look at the extensions defined in the Linux OpenGL library */
216     if (local_func == NULL) {
217       char buf[256];
218       void *ret = NULL;
219
220       /* Remove the 3 last letters (EXT, ARB, ...).
221
222          I know that some extensions have more than 3 letters (MESA, NV,
223          INTEL, ...), but this is only a stop-gap measure to fix buggy
224          OpenGL drivers (moreover, it is only useful for old 1.0 apps
225          that query the glBindTextureEXT extension).
226       */
227       memcpy(buf, glx_name, strlen(glx_name) - 3);
228       buf[strlen(glx_name) - 3] = '\0';
229       TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
230
231       ret = GetProcAddress(opengl32_handle, buf);
232       if (ret != NULL) {
233         TRACE(" found function in main OpenGL library (%p) !\n", ret);
234       } else {
235         WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, glx_name);
236       }
237
238       return ret;
239     } else {
240       TRACE(" returning function  (%p)\n", ext_ret->func);
241       extension_funcs[ext_ret - extension_registry] = local_func;
242
243       return ext_ret->func;
244     }
245   }
246 }
247
248 /***********************************************************************
249  *              wglRealizeLayerPalette (OPENGL32.@)
250  */
251 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
252                                    int iLayerPlane,
253                                    BOOL bRealize) {
254   FIXME("()\n");
255
256   return FALSE;
257 }
258
259 /***********************************************************************
260  *              wglSetLayerPaletteEntries (OPENGL32.@)
261  */
262 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
263                                      int iLayerPlane,
264                                      int iStart,
265                                      int cEntries,
266                                      const COLORREF *pcr) {
267   FIXME("(): stub !\n");
268
269   return 0;
270 }
271
272 /***********************************************************************
273  *              wglSwapLayerBuffers (OPENGL32.@)
274  */
275 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
276                                 UINT fuPlanes) {
277   TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
278
279   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
280     if (!SwapBuffers(hdc)) return FALSE;
281     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
282   }
283
284   if (fuPlanes) {
285     WARN("Following layers unhandled : %08x\n", fuPlanes);
286   }
287
288   return TRUE;
289 }
290
291 #ifdef HAVE_GL_GLU_H
292
293 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
294 {
295     vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;  
296     vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;  
297     vertex[2] = 0.0;
298 }
299
300 static void tess_callback_vertex(GLvoid *vertex)
301 {
302     GLdouble *dbl = vertex;
303     TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
304     glVertex3dv(vertex);
305 }
306
307 static void tess_callback_begin(GLenum which)
308 {
309     TRACE("%d\n", which);
310     glBegin(which);
311 }
312
313 static void tess_callback_end(void)
314 {
315     TRACE("\n");
316     glEnd();
317 }
318
319 /***********************************************************************
320  *              wglUseFontOutlines_common
321  */
322 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
323                                       DWORD first,
324                                       DWORD count,
325                                       DWORD listBase,
326                                       FLOAT deviation,
327                                       FLOAT extrusion,
328                                       int format,
329                                       LPGLYPHMETRICSFLOAT lpgmf,
330                                       BOOL unicode)
331 {
332     UINT glyph;
333     const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
334     GLUtesselator *tess;
335     LOGFONTW lf;
336     HFONT old_font, unscaled_font;
337     UINT em_size = 1024;
338     RECT rc;
339
340     TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
341           listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
342
343
344     ENTER_GL();
345     tess = gluNewTess();
346     if(tess)
347     {
348         gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
349         gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
350         gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
351     }
352     LEAVE_GL();
353
354     if(!tess) return FALSE;
355
356     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
357     rc.left = rc.right = rc.bottom = 0;
358     rc.top = em_size;
359     DPtoLP(hdc, (POINT*)&rc, 2);
360     lf.lfHeight = -abs(rc.top - rc.bottom);
361     lf.lfOrientation = lf.lfEscapement = 0;
362     unscaled_font = CreateFontIndirectW(&lf);
363     old_font = SelectObject(hdc, unscaled_font);
364
365     for (glyph = first; glyph < first + count; glyph++)
366     {
367         DWORD needed;
368         GLYPHMETRICS gm;
369         BYTE *buf;
370         TTPOLYGONHEADER *pph;
371         TTPOLYCURVE *ppc;
372         GLdouble *vertices;
373
374         if(unicode)
375             needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
376         else
377             needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
378
379         if(needed == GDI_ERROR)
380             goto error;
381
382         buf = HeapAlloc(GetProcessHeap(), 0, needed);
383         vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
384
385         if(unicode)
386             GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
387         else
388             GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
389
390         TRACE("glyph %d\n", glyph);
391
392         if(lpgmf)
393         {
394             lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
395             lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
396             lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
397             lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
398             lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
399             lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
400
401             TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
402                   lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); 
403             lpgmf++;
404         }
405
406         ENTER_GL();
407         glNewList(listBase++, GL_COMPILE);
408         gluTessBeginPolygon(tess, NULL);
409
410         pph = (TTPOLYGONHEADER*)buf;
411         while((BYTE*)pph < buf + needed)
412         {
413             TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
414
415             gluTessBeginContour(tess);
416
417             fixed_to_double(pph->pfxStart, em_size, vertices);
418             gluTessVertex(tess, vertices, vertices);
419             vertices += 3;
420
421             ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
422             while((char*)ppc < (char*)pph + pph->cb)
423             {
424                 int i;
425
426                 switch(ppc->wType) {
427                 case TT_PRIM_LINE:
428                     for(i = 0; i < ppc->cpfx; i++)
429                     {
430                         TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
431                         fixed_to_double(ppc->apfx[i], em_size, vertices); 
432                         gluTessVertex(tess, vertices, vertices);
433                         vertices += 3;
434                     }
435                     break;
436
437                 case TT_PRIM_QSPLINE:
438                     for(i = 0; i < ppc->cpfx/2; i++)
439                     {
440                         /* FIXME just connecting the control points for now */
441                         TRACE("\t\tcurve  %d,%d %d,%d\n",
442                               ppc->apfx[i * 2].x.value,     ppc->apfx[i * 3].y.value,
443                               ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
444                         fixed_to_double(ppc->apfx[i * 2], em_size, vertices); 
445                         gluTessVertex(tess, vertices, vertices);
446                         vertices += 3;
447                         fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); 
448                         gluTessVertex(tess, vertices, vertices);
449                         vertices += 3;
450                     }
451                     break;
452                 default:
453                     ERR("\t\tcurve type = %d\n", ppc->wType);
454                     gluTessEndContour(tess);
455                     goto error_in_list;
456                 }
457
458                 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
459                                      (ppc->cpfx - 1) * sizeof(POINTFX));
460             }
461             gluTessEndContour(tess);
462             pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
463         }
464
465 error_in_list:
466         gluTessEndPolygon(tess);
467         glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
468         glEndList();
469         LEAVE_GL();
470         HeapFree(GetProcessHeap(), 0, buf);
471         HeapFree(GetProcessHeap(), 0, vertices);
472     }
473
474  error:
475     DeleteObject(SelectObject(hdc, old_font));
476     gluDeleteTess(tess);
477     return TRUE;
478
479 }
480
481 #else /* HAVE_GL_GLU_H */
482
483 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
484                                       DWORD first,
485                                       DWORD count,
486                                       DWORD listBase,
487                                       FLOAT deviation,
488                                       FLOAT extrusion,
489                                       int format,
490                                       LPGLYPHMETRICSFLOAT lpgmf,
491                                       BOOL unicode)
492 {
493     FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
494     return FALSE;
495 }
496
497 #endif /* HAVE_GL_GLU_H */
498
499 /***********************************************************************
500  *              wglUseFontOutlinesA (OPENGL32.@)
501  */
502 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
503                                 DWORD first,
504                                 DWORD count,
505                                 DWORD listBase,
506                                 FLOAT deviation,
507                                 FLOAT extrusion,
508                                 int format,
509                                 LPGLYPHMETRICSFLOAT lpgmf)
510 {
511     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
512 }
513
514 /***********************************************************************
515  *              wglUseFontOutlinesW (OPENGL32.@)
516  */
517 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
518                                 DWORD first,
519                                 DWORD count,
520                                 DWORD listBase,
521                                 FLOAT deviation,
522                                 FLOAT extrusion,
523                                 int format,
524                                 LPGLYPHMETRICSFLOAT lpgmf)
525 {
526     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
527 }
528
529 const GLubyte * internal_glGetString(GLenum name) {
530   const char* GL_Extensions = NULL;
531   
532   if (GL_EXTENSIONS != name) {
533     return glGetString(name);
534   }
535
536   if (NULL == internal_gl_extensions) {
537     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
538
539     TRACE("GL_EXTENSIONS reported:\n");  
540     if (NULL == GL_Extensions) {
541       ERR("GL_EXTENSIONS returns NULL\n");      
542       return NULL;
543     } else {
544       size_t len = strlen(GL_Extensions);
545       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
546
547       while (*GL_Extensions != 0x00) {
548         const char* Start = GL_Extensions;
549         char        ThisExtn[256];
550          
551         memset(ThisExtn, 0x00, sizeof(ThisExtn));
552         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
553           GL_Extensions++;
554         }
555         memcpy(ThisExtn, Start, (GL_Extensions - Start));
556         TRACE("- %s:", ThisExtn);
557         
558         /* test if supported API is disabled by config */
559         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
560           strcat(internal_gl_extensions, " ");
561           strcat(internal_gl_extensions, ThisExtn);
562           TRACE(" active\n");
563         } else {
564           TRACE(" deactived (by config)\n");
565         }
566
567         if (*GL_Extensions == ' ') GL_Extensions++;
568       }
569     }
570   }
571   return (const GLubyte *) internal_gl_extensions;
572 }
573
574 void internal_glGetIntegerv(GLenum pname, GLint* params) {
575   TRACE("pname: 0x%x, params %p\n", pname, params);
576   glGetIntegerv(pname, params);
577   /* A few parameters like GL_DEPTH_BITS differ between WGL and GLX, the wglGetIntegerv helper function handles those */
578   wine_wgl.p_wglGetIntegerv(pname, params);
579 }
580
581
582 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
583    include all dependencies
584 */
585 #ifndef SONAME_LIBGL
586 #define SONAME_LIBGL "libGL.so"
587 #endif
588
589 /* This is for brain-dead applications that use OpenGL functions before even
590    creating a rendering context.... */
591 static BOOL process_attach(void)
592 {
593   XWindowAttributes win_attr;
594   Visual *rootVisual;
595   int num;
596   XVisualInfo template;
597   HDC hdc;
598   XVisualInfo *vis = NULL;
599   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
600   HMODULE mod = GetModuleHandleA( "winex11.drv" );
601   void *opengl_handle;
602   DWORD size = sizeof(internal_gl_disabled_extensions);
603   HKEY hkey = 0;
604
605   if (!root || !mod)
606   {
607       ERR("X11DRV not loaded. Cannot create default context.\n");
608       return FALSE;
609   }
610
611   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
612   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
613
614   /* Load WGL function pointers from winex11.drv */
615   wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod, "wglGetProcAddress");
616
617   /* Interal WGL function */
618   wine_wgl.p_wglGetIntegerv = (void *)GetProcAddress(mod, "wglGetIntegerv");
619
620   hdc = GetDC(0);
621   default_display = get_display( hdc );
622   ReleaseDC( 0, hdc );
623   if (!default_display)
624   {
625       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
626       return FALSE;
627   }
628
629   ENTER_GL();
630
631   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
632      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
633      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
634      with mismatched visuals.  Note that the Root Window visual may not be double
635      buffered, so apps actually attempting to render this way may flicker */
636   if (XGetWindowAttributes( default_display, root, &win_attr ))
637   {
638     rootVisual = win_attr.visual;
639   }
640   else
641   {
642     /* Get the default visual, since we can't seem to get the attributes from the
643        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
644     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
645   }
646
647   template.visualid = XVisualIDFromVisual(rootVisual);
648   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
649   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
650   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
651   XFree(vis);
652   LEAVE_GL();
653
654   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
655   if (opengl_handle != NULL) {
656    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
657    wine_dlclose(opengl_handle, NULL, 0);
658    if (p_glXGetProcAddressARB == NULL)
659            TRACE("could not find glXGetProcAddressARB in libGL.\n");
660   }
661
662   internal_gl_disabled_extensions[0] = 0;
663   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
664     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
665       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
666     }
667     RegCloseKey(hkey);
668   }
669
670   if (default_cx == NULL) {
671     ERR("Could not create default context.\n");
672   }
673   return TRUE;
674 }
675
676
677 /**********************************************************************/
678
679 static void process_detach(void)
680 {
681   glXDestroyContext(default_display, default_cx);
682
683   HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
684 }
685
686 /***********************************************************************
687  *           OpenGL initialisation routine
688  */
689 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
690 {
691     switch(reason)
692     {
693     case DLL_PROCESS_ATTACH:
694         opengl32_handle = hinst;
695         DisableThreadLibraryCalls(hinst);
696         return process_attach();
697     case DLL_PROCESS_DETACH:
698         process_detach();
699         break;
700     }
701     return TRUE;
702 }