push 421a6d0d1068c98851feb4eb01bb0e754f615ce9
[wine/hacks.git] / dlls / opengl32 / wgl.c
blob029f3614bfc480afcc3fcb6649096cae030b9253
1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
4 * Copyright (c) 2005 Raphael Junqueira
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #include "wingdi.h"
33 #include "winternl.h"
34 #include "winnt.h"
36 #include "opengl_ext.h"
37 #ifdef HAVE_GL_GLU_H
38 #undef far
39 #undef near
40 #include <GL/glu.h>
41 #endif
42 #include "wine/library.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 WINE_DECLARE_DEBUG_CHANNEL(opengl);
48 typedef struct wine_wgl_s {
49 PROC WINAPI (*p_wglGetProcAddress)(LPCSTR lpszProc);
51 void WINAPI (*p_wglDisable)(GLenum cap);
52 void WINAPI (*p_wglEnable)(GLenum cap);
53 void WINAPI (*p_wglGetIntegerv)(GLenum pname, GLint* params);
54 GLboolean WINAPI (*p_wglIsEnabled)(GLenum cap);
55 void WINAPI (*p_wglScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
56 void WINAPI (*p_wglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
57 } wine_wgl_t;
59 /** global wgl object */
60 static wine_wgl_t wine_wgl;
62 /* x11drv GDI escapes */
63 #define X11DRV_ESCAPE 6789
64 enum x11drv_escape_codes
66 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
67 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
68 X11DRV_GET_FONT, /* get current X font for a DC */
69 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
70 X11DRV_START_EXPOSURES, /* start graphics exposures */
71 X11DRV_END_EXPOSURES, /* end graphics exposures */
72 X11DRV_GET_DCE, /* get the DCE pointer */
73 X11DRV_SET_DCE, /* set the DCE pointer */
74 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
75 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
78 void (*wine_tsx11_lock_ptr)(void) = NULL;
79 void (*wine_tsx11_unlock_ptr)(void) = NULL;
81 static HMODULE opengl32_handle;
83 static char internal_gl_disabled_extensions[512];
84 static char* internal_gl_extensions = NULL;
86 typedef struct wine_glcontext {
87 HDC hdc;
88 XVisualInfo *vis;
89 GLXFBConfig fb_conf;
90 GLXContext ctx;
91 BOOL do_escape;
92 /* ... more stuff here */
93 } Wine_GLContext;
95 void enter_gl(void)
97 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
99 if (curctx && curctx->do_escape)
101 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
102 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
105 wine_tsx11_lock_ptr();
106 return;
109 const GLubyte * WINAPI wine_glGetString( GLenum name );
111 /***********************************************************************
112 * wglCreateLayerContext (OPENGL32.@)
114 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
115 int iLayerPlane) {
116 TRACE("(%p,%d)\n", hdc, iLayerPlane);
118 if (iLayerPlane == 0) {
119 return wglCreateContext(hdc);
121 FIXME(" no handler for layer %d\n", iLayerPlane);
123 return NULL;
126 /***********************************************************************
127 * wglCopyContext (OPENGL32.@)
129 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
130 HGLRC hglrcDst,
131 UINT mask) {
132 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
134 return FALSE;
137 /***********************************************************************
138 * wglDescribeLayerPlane (OPENGL32.@)
140 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
141 int iPixelFormat,
142 int iLayerPlane,
143 UINT nBytes,
144 LPLAYERPLANEDESCRIPTOR plpd) {
145 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
147 return FALSE;
150 /***********************************************************************
151 * wglGetLayerPaletteEntries (OPENGL32.@)
153 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
154 int iLayerPlane,
155 int iStart,
156 int cEntries,
157 const COLORREF *pcr) {
158 FIXME("(): stub !\n");
160 return 0;
163 static int compar(const void *elt_a, const void *elt_b) {
164 return strcmp(((const OpenGL_extension *) elt_a)->name,
165 ((const OpenGL_extension *) elt_b)->name);
168 /* Check if a GL extension is supported */
169 static BOOL is_extension_supported(const char* extension)
171 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
173 TRACE("Checking for extension '%s'\n", extension);
175 if(!gl_ext_string) {
176 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
177 return FALSE;
180 /* We use the GetProcAddress function from the display driver to retrieve function pointers
181 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
182 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
183 * require the function to return NULL when a extension isn't found. For this reason we check
184 * if the OpenGL extension required for the function we are looking up is supported. */
186 /* Check if the extension is part of the GL extension string to see if it is supported. */
187 if(strstr(gl_ext_string, extension) != NULL)
188 return TRUE;
190 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
191 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
192 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
193 * Check if we are searching for a core GL function */
194 if(strncmp(extension, "GL_VERSION_", 11) == 0)
196 const GLubyte *gl_version = glGetString(GL_VERSION);
197 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
199 if(!gl_version) {
200 ERR("Error no OpenGL version found,\n");
201 return FALSE;
204 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
205 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
206 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
207 return TRUE;
209 WARN("The function requires OpenGL version '%c.%c' while your drivers only provide '%c.%c'\n", version[0], version[2], gl_version[0], gl_version[2]);
212 return FALSE;
215 /***********************************************************************
216 * wglGetProcAddress (OPENGL32.@)
218 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
219 void *local_func;
220 OpenGL_extension ext;
221 const OpenGL_extension *ext_ret;
223 TRACE("(%s)\n", lpszProc);
225 if(lpszProc == NULL)
226 return NULL;
228 /* First, look if it's not already defined in the 'standard' OpenGL functions */
229 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
230 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
231 return local_func;
234 /* After that, search in the thunks to find the real name of the extension */
235 ext.name = lpszProc;
236 ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
237 extension_registry_size, sizeof(OpenGL_extension), compar);
239 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
240 if (ext_ret == NULL) {
241 /* If the function name starts with a w it is a WGL extension */
242 if(lpszProc[0] == 'w')
243 return wine_wgl.p_wglGetProcAddress(lpszProc);
245 /* We are dealing with an unknown GL extension. */
246 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
247 return NULL;
248 } else { /* We are looking for an OpenGL extension */
250 /* Check if the GL extension required by the function is available */
251 if(!is_extension_supported(ext_ret->extension)) {
252 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
255 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
257 /* After that, look at the extensions defined in the Linux OpenGL library */
258 if (local_func == NULL) {
259 char buf[256];
260 void *ret = NULL;
262 /* Remove the 3 last letters (EXT, ARB, ...).
264 I know that some extensions have more than 3 letters (MESA, NV,
265 INTEL, ...), but this is only a stop-gap measure to fix buggy
266 OpenGL drivers (moreover, it is only useful for old 1.0 apps
267 that query the glBindTextureEXT extension).
269 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
270 buf[strlen(ext_ret->name) - 3] = '\0';
271 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
273 ret = GetProcAddress(opengl32_handle, buf);
274 if (ret != NULL) {
275 TRACE(" found function in main OpenGL library (%p) !\n", ret);
276 } else {
277 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
280 return ret;
281 } else {
282 TRACE(" returning function (%p)\n", ext_ret->func);
283 extension_funcs[ext_ret - extension_registry] = local_func;
285 return ext_ret->func;
290 /***********************************************************************
291 * wglRealizeLayerPalette (OPENGL32.@)
293 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
294 int iLayerPlane,
295 BOOL bRealize) {
296 FIXME("()\n");
298 return FALSE;
301 /***********************************************************************
302 * wglSetLayerPaletteEntries (OPENGL32.@)
304 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
305 int iLayerPlane,
306 int iStart,
307 int cEntries,
308 const COLORREF *pcr) {
309 FIXME("(): stub !\n");
311 return 0;
314 /***********************************************************************
315 * wglSwapLayerBuffers (OPENGL32.@)
317 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
318 UINT fuPlanes) {
319 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
321 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
322 if (!SwapBuffers(hdc)) return FALSE;
323 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
326 if (fuPlanes) {
327 WARN("Following layers unhandled : %08x\n", fuPlanes);
330 return TRUE;
333 #ifdef HAVE_GL_GLU_H
335 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
337 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
338 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
339 vertex[2] = 0.0;
342 static void tess_callback_vertex(GLvoid *vertex)
344 GLdouble *dbl = vertex;
345 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
346 glVertex3dv(vertex);
349 static void tess_callback_begin(GLenum which)
351 TRACE("%d\n", which);
352 glBegin(which);
355 static void tess_callback_end(void)
357 TRACE("\n");
358 glEnd();
361 /***********************************************************************
362 * wglUseFontOutlines_common
364 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
365 DWORD first,
366 DWORD count,
367 DWORD listBase,
368 FLOAT deviation,
369 FLOAT extrusion,
370 int format,
371 LPGLYPHMETRICSFLOAT lpgmf,
372 BOOL unicode)
374 UINT glyph;
375 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
376 GLUtesselator *tess;
377 LOGFONTW lf;
378 HFONT old_font, unscaled_font;
379 UINT em_size = 1024;
380 RECT rc;
382 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
383 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
386 ENTER_GL();
387 tess = gluNewTess();
388 if(tess)
390 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
391 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
392 gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
394 LEAVE_GL();
396 if(!tess) return FALSE;
398 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
399 rc.left = rc.right = rc.bottom = 0;
400 rc.top = em_size;
401 DPtoLP(hdc, (POINT*)&rc, 2);
402 lf.lfHeight = -abs(rc.top - rc.bottom);
403 lf.lfOrientation = lf.lfEscapement = 0;
404 unscaled_font = CreateFontIndirectW(&lf);
405 old_font = SelectObject(hdc, unscaled_font);
407 for (glyph = first; glyph < first + count; glyph++)
409 DWORD needed;
410 GLYPHMETRICS gm;
411 BYTE *buf;
412 TTPOLYGONHEADER *pph;
413 TTPOLYCURVE *ppc;
414 GLdouble *vertices;
416 if(unicode)
417 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
418 else
419 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
421 if(needed == GDI_ERROR)
422 goto error;
424 buf = HeapAlloc(GetProcessHeap(), 0, needed);
425 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
427 if(unicode)
428 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
429 else
430 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
432 TRACE("glyph %d\n", glyph);
434 if(lpgmf)
436 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
437 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
438 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
439 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
440 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
441 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
443 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
444 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
445 lpgmf++;
448 ENTER_GL();
449 glNewList(listBase++, GL_COMPILE);
450 gluTessBeginPolygon(tess, NULL);
452 pph = (TTPOLYGONHEADER*)buf;
453 while((BYTE*)pph < buf + needed)
455 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
457 gluTessBeginContour(tess);
459 fixed_to_double(pph->pfxStart, em_size, vertices);
460 gluTessVertex(tess, vertices, vertices);
461 vertices += 3;
463 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
464 while((char*)ppc < (char*)pph + pph->cb)
466 int i;
468 switch(ppc->wType) {
469 case TT_PRIM_LINE:
470 for(i = 0; i < ppc->cpfx; i++)
472 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
473 fixed_to_double(ppc->apfx[i], em_size, vertices);
474 gluTessVertex(tess, vertices, vertices);
475 vertices += 3;
477 break;
479 case TT_PRIM_QSPLINE:
480 for(i = 0; i < ppc->cpfx/2; i++)
482 /* FIXME just connecting the control points for now */
483 TRACE("\t\tcurve %d,%d %d,%d\n",
484 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
485 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
486 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
487 gluTessVertex(tess, vertices, vertices);
488 vertices += 3;
489 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
490 gluTessVertex(tess, vertices, vertices);
491 vertices += 3;
493 break;
494 default:
495 ERR("\t\tcurve type = %d\n", ppc->wType);
496 gluTessEndContour(tess);
497 goto error_in_list;
500 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
501 (ppc->cpfx - 1) * sizeof(POINTFX));
503 gluTessEndContour(tess);
504 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
507 error_in_list:
508 gluTessEndPolygon(tess);
509 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
510 glEndList();
511 LEAVE_GL();
512 HeapFree(GetProcessHeap(), 0, buf);
513 HeapFree(GetProcessHeap(), 0, vertices);
516 error:
517 DeleteObject(SelectObject(hdc, old_font));
518 gluDeleteTess(tess);
519 return TRUE;
523 #else /* HAVE_GL_GLU_H */
525 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
526 DWORD first,
527 DWORD count,
528 DWORD listBase,
529 FLOAT deviation,
530 FLOAT extrusion,
531 int format,
532 LPGLYPHMETRICSFLOAT lpgmf,
533 BOOL unicode)
535 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
536 return FALSE;
539 #endif /* HAVE_GL_GLU_H */
541 /***********************************************************************
542 * wglUseFontOutlinesA (OPENGL32.@)
544 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
545 DWORD first,
546 DWORD count,
547 DWORD listBase,
548 FLOAT deviation,
549 FLOAT extrusion,
550 int format,
551 LPGLYPHMETRICSFLOAT lpgmf)
553 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
556 /***********************************************************************
557 * wglUseFontOutlinesW (OPENGL32.@)
559 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
560 DWORD first,
561 DWORD count,
562 DWORD listBase,
563 FLOAT deviation,
564 FLOAT extrusion,
565 int format,
566 LPGLYPHMETRICSFLOAT lpgmf)
568 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
571 /***********************************************************************
572 * glEnable (OPENGL32.@)
574 void WINAPI wine_glEnable( GLenum cap )
576 TRACE("(%d)\n", cap );
577 wine_wgl.p_wglEnable(cap);
580 /***********************************************************************
581 * glIsEnabled (OPENGL32.@)
583 GLboolean WINAPI wine_glIsEnabled( GLenum cap )
585 TRACE("(%d)\n", cap );
586 return wine_wgl.p_wglIsEnabled(cap);
589 /***********************************************************************
590 * glDisable (OPENGL32.@)
592 void WINAPI wine_glDisable( GLenum cap )
594 TRACE("(%d)\n", cap );
595 wine_wgl.p_wglDisable(cap);
598 /***********************************************************************
599 * glScissor (OPENGL32.@)
601 void WINAPI wine_glScissor( GLint x, GLint y, GLsizei width, GLsizei height )
603 TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
604 wine_wgl.p_wglScissor(x, y, width, height);
607 /***********************************************************************
608 * glViewport (OPENGL32.@)
610 void WINAPI wine_glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
612 TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
613 wine_wgl.p_wglViewport(x, y, width, height);
616 /***********************************************************************
617 * glGetString (OPENGL32.@)
619 const GLubyte * WINAPI wine_glGetString( GLenum name )
621 const GLubyte *ret;
622 const char* GL_Extensions = NULL;
624 if (GL_EXTENSIONS != name) {
625 ENTER_GL();
626 ret = glGetString(name);
627 LEAVE_GL();
628 return ret;
631 if (NULL == internal_gl_extensions) {
632 ENTER_GL();
633 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
635 if (GL_Extensions)
637 size_t len = strlen(GL_Extensions);
638 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
640 TRACE("GL_EXTENSIONS reported:\n");
641 while (*GL_Extensions != 0x00) {
642 const char* Start = GL_Extensions;
643 char ThisExtn[256];
645 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
646 GL_Extensions++;
648 memcpy(ThisExtn, Start, (GL_Extensions - Start));
649 ThisExtn[GL_Extensions - Start] = 0;
650 TRACE("- %s:", ThisExtn);
652 /* test if supported API is disabled by config */
653 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
654 strcat(internal_gl_extensions, " ");
655 strcat(internal_gl_extensions, ThisExtn);
656 TRACE(" active\n");
657 } else {
658 TRACE(" deactived (by config)\n");
661 if (*GL_Extensions == ' ') GL_Extensions++;
664 LEAVE_GL();
666 return (const GLubyte *) internal_gl_extensions;
669 /***********************************************************************
670 * glGetIntegerv (OPENGL32.@)
672 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
674 wine_wgl.p_wglGetIntegerv(pname, params);
678 /* This is for brain-dead applications that use OpenGL functions before even
679 creating a rendering context.... */
680 static BOOL process_attach(void)
682 HMODULE mod_x11, mod_gdi32;
683 DWORD size = sizeof(internal_gl_disabled_extensions);
684 HKEY hkey = 0;
686 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
687 mod_x11 = GetModuleHandleA( "winex11.drv" );
688 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
690 if (!mod_x11 || !mod_gdi32)
692 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
693 return FALSE;
696 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
697 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
699 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
701 /* Interal WGL function */
702 wine_wgl.p_wglDisable = (void *)wine_wgl.p_wglGetProcAddress("wglDisable");
703 wine_wgl.p_wglEnable = (void *)wine_wgl.p_wglGetProcAddress("wglEnable");
704 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
705 wine_wgl.p_wglIsEnabled = (void *)wine_wgl.p_wglGetProcAddress("wglIsEnabled");
706 wine_wgl.p_wglScissor = (void *)wine_wgl.p_wglGetProcAddress("wglScissor");
707 wine_wgl.p_wglViewport = (void *)wine_wgl.p_wglGetProcAddress("wglViewport");
709 internal_gl_disabled_extensions[0] = 0;
710 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
711 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
712 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
714 RegCloseKey(hkey);
717 return TRUE;
721 /**********************************************************************/
723 static void process_detach(void)
725 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
728 /***********************************************************************
729 * OpenGL initialisation routine
731 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
733 switch(reason)
735 case DLL_PROCESS_ATTACH:
736 opengl32_handle = hinst;
737 DisableThreadLibraryCalls(hinst);
738 return process_attach();
739 case DLL_PROCESS_DETACH:
740 process_detach();
741 break;
743 return TRUE;