include: Update RASCONN and error codes.
[wine.git] / dlls / opengl32 / wgl.c
bloba07fcf3bc67220eb8617bc0e865ec26cb1b98896
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_wglGetIntegerv)(GLenum pname, GLint* params);
52 void WINAPI (*p_wglFinish)(void);
53 void WINAPI (*p_wglFlush)(void);
54 } wine_wgl_t;
56 /** global wgl object */
57 static wine_wgl_t wine_wgl;
59 #ifdef SONAME_LIBGLU
60 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
61 MAKE_FUNCPTR(gluNewTess)
62 MAKE_FUNCPTR(gluDeleteTess)
63 MAKE_FUNCPTR(gluTessBeginContour)
64 MAKE_FUNCPTR(gluTessBeginPolygon)
65 MAKE_FUNCPTR(gluTessCallback)
66 MAKE_FUNCPTR(gluTessEndContour)
67 MAKE_FUNCPTR(gluTessEndPolygon)
68 MAKE_FUNCPTR(gluTessVertex)
69 #undef MAKE_FUNCPTR
70 #endif /* SONAME_LIBGLU */
72 /* x11drv GDI escapes */
73 #define X11DRV_ESCAPE 6789
74 enum x11drv_escape_codes
76 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
77 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
78 X11DRV_GET_FONT, /* get current X font for a DC */
79 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
80 X11DRV_START_EXPOSURES, /* start graphics exposures */
81 X11DRV_END_EXPOSURES, /* end graphics exposures */
82 X11DRV_GET_DCE, /* get the DCE pointer */
83 X11DRV_SET_DCE, /* set the DCE pointer */
84 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
85 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
88 void (*wine_tsx11_lock_ptr)(void) = NULL;
89 void (*wine_tsx11_unlock_ptr)(void) = NULL;
91 static HMODULE opengl32_handle;
92 static void* libglu_handle = NULL;
94 static char* internal_gl_disabled_extensions = NULL;
95 static char* internal_gl_extensions = NULL;
97 typedef struct wine_glcontext {
98 HDC hdc;
99 BOOL do_escape;
100 /* ... more stuff here */
101 } Wine_GLContext;
103 void enter_gl(void)
105 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
107 if (curctx && curctx->do_escape)
109 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
110 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
113 wine_tsx11_lock_ptr();
114 return;
117 const GLubyte * WINAPI wine_glGetString( GLenum name );
119 /***********************************************************************
120 * wglCreateLayerContext (OPENGL32.@)
122 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
123 int iLayerPlane) {
124 TRACE("(%p,%d)\n", hdc, iLayerPlane);
126 if (iLayerPlane == 0) {
127 return wglCreateContext(hdc);
129 FIXME(" no handler for layer %d\n", iLayerPlane);
131 return NULL;
134 /***********************************************************************
135 * wglDescribeLayerPlane (OPENGL32.@)
137 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
138 int iPixelFormat,
139 int iLayerPlane,
140 UINT nBytes,
141 LPLAYERPLANEDESCRIPTOR plpd) {
142 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
144 return FALSE;
147 /***********************************************************************
148 * wglGetLayerPaletteEntries (OPENGL32.@)
150 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
151 int iLayerPlane,
152 int iStart,
153 int cEntries,
154 const COLORREF *pcr) {
155 FIXME("(): stub !\n");
157 return 0;
160 static int compar(const void *elt_a, const void *elt_b) {
161 return strcmp(((const OpenGL_extension *) elt_a)->name,
162 ((const OpenGL_extension *) elt_b)->name);
165 /* Check if a GL extension is supported */
166 static BOOL is_extension_supported(const char* extension)
168 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
170 TRACE("Checking for extension '%s'\n", extension);
172 if(!gl_ext_string) {
173 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
174 return FALSE;
177 /* We use the GetProcAddress function from the display driver to retrieve function pointers
178 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
179 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
180 * require the function to return NULL when a extension isn't found. For this reason we check
181 * if the OpenGL extension required for the function we are looking up is supported. */
183 /* Check if the extension is part of the GL extension string to see if it is supported. */
184 if(strstr(gl_ext_string, extension) != NULL)
185 return TRUE;
187 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
188 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
189 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
190 * Check if we are searching for a core GL function */
191 if(strncmp(extension, "GL_VERSION_", 11) == 0)
193 const GLubyte *gl_version = glGetString(GL_VERSION);
194 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
196 if(!gl_version) {
197 ERR("Error no OpenGL version found,\n");
198 return FALSE;
201 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
202 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
203 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
204 return TRUE;
206 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]);
209 return FALSE;
212 /***********************************************************************
213 * wglGetProcAddress (OPENGL32.@)
215 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
216 void *local_func;
217 OpenGL_extension ext;
218 const OpenGL_extension *ext_ret;
220 TRACE("(%s)\n", lpszProc);
222 if(lpszProc == NULL)
223 return NULL;
225 /* First, look if it's not already defined in the 'standard' OpenGL functions */
226 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
227 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
228 return local_func;
231 /* After that, search in the thunks to find the real name of the extension */
232 ext.name = lpszProc;
233 ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
234 extension_registry_size, sizeof(OpenGL_extension), compar);
236 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
237 if (ext_ret == NULL) {
238 /* If the function name starts with a w it is a WGL extension */
239 if(lpszProc[0] == 'w')
240 return wine_wgl.p_wglGetProcAddress(lpszProc);
242 /* We are dealing with an unknown GL extension. */
243 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
244 return NULL;
245 } else { /* We are looking for an OpenGL extension */
247 /* Check if the GL extension required by the function is available */
248 if(!is_extension_supported(ext_ret->extension)) {
249 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
252 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
254 /* After that, look at the extensions defined in the Linux OpenGL library */
255 if (local_func == NULL) {
256 char buf[256];
257 void *ret = NULL;
259 /* Remove the 3 last letters (EXT, ARB, ...).
261 I know that some extensions have more than 3 letters (MESA, NV,
262 INTEL, ...), but this is only a stop-gap measure to fix buggy
263 OpenGL drivers (moreover, it is only useful for old 1.0 apps
264 that query the glBindTextureEXT extension).
266 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
267 buf[strlen(ext_ret->name) - 3] = '\0';
268 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
270 ret = GetProcAddress(opengl32_handle, buf);
271 if (ret != NULL) {
272 TRACE(" found function in main OpenGL library (%p) !\n", ret);
273 } else {
274 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
277 return ret;
278 } else {
279 TRACE(" returning function (%p)\n", ext_ret->func);
280 extension_funcs[ext_ret - extension_registry] = local_func;
282 return ext_ret->func;
287 /***********************************************************************
288 * wglRealizeLayerPalette (OPENGL32.@)
290 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
291 int iLayerPlane,
292 BOOL bRealize) {
293 FIXME("()\n");
295 return FALSE;
298 /***********************************************************************
299 * wglSetLayerPaletteEntries (OPENGL32.@)
301 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
302 int iLayerPlane,
303 int iStart,
304 int cEntries,
305 const COLORREF *pcr) {
306 FIXME("(): stub !\n");
308 return 0;
311 /***********************************************************************
312 * wglSwapLayerBuffers (OPENGL32.@)
314 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
315 UINT fuPlanes) {
316 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
318 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
319 if (!SwapBuffers(hdc)) return FALSE;
320 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
323 if (fuPlanes) {
324 WARN("Following layers unhandled : %08x\n", fuPlanes);
327 return TRUE;
330 #ifdef SONAME_LIBGLU
332 static void *load_libglu(void)
334 static int already_loaded;
335 void *handle;
337 if (already_loaded) return libglu_handle;
338 already_loaded = 1;
340 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
341 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
342 if (!handle)
344 WARN("Failed to load %s\n", SONAME_LIBGLU);
345 return NULL;
348 #define LOAD_FUNCPTR(f) if((p##f = (void*)wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
349 LOAD_FUNCPTR(gluNewTess)
350 LOAD_FUNCPTR(gluDeleteTess)
351 LOAD_FUNCPTR(gluTessBeginContour)
352 LOAD_FUNCPTR(gluTessBeginPolygon)
353 LOAD_FUNCPTR(gluTessCallback)
354 LOAD_FUNCPTR(gluTessEndContour)
355 LOAD_FUNCPTR(gluTessEndPolygon)
356 LOAD_FUNCPTR(gluTessVertex)
357 #undef LOAD_FUNCPTR
358 libglu_handle = handle;
359 return handle;
361 sym_not_found:
362 WARN("Unable to load function ptrs from libGLU\n");
363 /* Close the library as we won't use it */
364 wine_dlclose(handle, NULL, 0);
365 return NULL;
368 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
370 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
371 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
372 vertex[2] = 0.0;
375 static void tess_callback_vertex(GLvoid *vertex)
377 GLdouble *dbl = vertex;
378 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
379 glVertex3dv(vertex);
382 static void tess_callback_begin(GLenum which)
384 TRACE("%d\n", which);
385 glBegin(which);
388 static void tess_callback_end(void)
390 TRACE("\n");
391 glEnd();
394 /***********************************************************************
395 * wglUseFontOutlines_common
397 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
398 DWORD first,
399 DWORD count,
400 DWORD listBase,
401 FLOAT deviation,
402 FLOAT extrusion,
403 int format,
404 LPGLYPHMETRICSFLOAT lpgmf,
405 BOOL unicode)
407 UINT glyph;
408 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
409 GLUtesselator *tess;
410 LOGFONTW lf;
411 HFONT old_font, unscaled_font;
412 UINT em_size = 1024;
413 RECT rc;
415 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
416 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
418 if (!load_libglu())
420 ERR("libGLU is required for this function but isn't loaded\n");
421 return FALSE;
424 ENTER_GL();
425 tess = pgluNewTess();
426 if(tess)
428 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
429 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
430 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
432 LEAVE_GL();
434 if(!tess) return FALSE;
436 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
437 rc.left = rc.right = rc.bottom = 0;
438 rc.top = em_size;
439 DPtoLP(hdc, (POINT*)&rc, 2);
440 lf.lfHeight = -abs(rc.top - rc.bottom);
441 lf.lfOrientation = lf.lfEscapement = 0;
442 unscaled_font = CreateFontIndirectW(&lf);
443 old_font = SelectObject(hdc, unscaled_font);
445 for (glyph = first; glyph < first + count; glyph++)
447 DWORD needed;
448 GLYPHMETRICS gm;
449 BYTE *buf;
450 TTPOLYGONHEADER *pph;
451 TTPOLYCURVE *ppc;
452 GLdouble *vertices;
454 if(unicode)
455 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
456 else
457 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
459 if(needed == GDI_ERROR)
460 goto error;
462 buf = HeapAlloc(GetProcessHeap(), 0, needed);
463 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
465 if(unicode)
466 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
467 else
468 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
470 TRACE("glyph %d\n", glyph);
472 if(lpgmf)
474 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
475 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
476 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
477 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
478 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
479 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
481 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
482 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
483 lpgmf++;
486 ENTER_GL();
487 glNewList(listBase++, GL_COMPILE);
488 pgluTessBeginPolygon(tess, NULL);
490 pph = (TTPOLYGONHEADER*)buf;
491 while((BYTE*)pph < buf + needed)
493 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
495 pgluTessBeginContour(tess);
497 fixed_to_double(pph->pfxStart, em_size, vertices);
498 pgluTessVertex(tess, vertices, vertices);
499 vertices += 3;
501 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
502 while((char*)ppc < (char*)pph + pph->cb)
504 int i;
506 switch(ppc->wType) {
507 case TT_PRIM_LINE:
508 for(i = 0; i < ppc->cpfx; i++)
510 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
511 fixed_to_double(ppc->apfx[i], em_size, vertices);
512 pgluTessVertex(tess, vertices, vertices);
513 vertices += 3;
515 break;
517 case TT_PRIM_QSPLINE:
518 for(i = 0; i < ppc->cpfx/2; i++)
520 /* FIXME just connecting the control points for now */
521 TRACE("\t\tcurve %d,%d %d,%d\n",
522 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
523 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
524 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
525 pgluTessVertex(tess, vertices, vertices);
526 vertices += 3;
527 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
528 pgluTessVertex(tess, vertices, vertices);
529 vertices += 3;
531 break;
532 default:
533 ERR("\t\tcurve type = %d\n", ppc->wType);
534 pgluTessEndContour(tess);
535 goto error_in_list;
538 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
539 (ppc->cpfx - 1) * sizeof(POINTFX));
541 pgluTessEndContour(tess);
542 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
545 error_in_list:
546 pgluTessEndPolygon(tess);
547 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
548 glEndList();
549 LEAVE_GL();
550 HeapFree(GetProcessHeap(), 0, buf);
551 HeapFree(GetProcessHeap(), 0, vertices);
554 error:
555 DeleteObject(SelectObject(hdc, old_font));
556 pgluDeleteTess(tess);
557 return TRUE;
561 #else /* SONAME_LIBGLU */
563 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
564 DWORD first,
565 DWORD count,
566 DWORD listBase,
567 FLOAT deviation,
568 FLOAT extrusion,
569 int format,
570 LPGLYPHMETRICSFLOAT lpgmf,
571 BOOL unicode)
573 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
574 return FALSE;
577 #endif /* SONAME_LIBGLU */
579 /***********************************************************************
580 * wglUseFontOutlinesA (OPENGL32.@)
582 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
583 DWORD first,
584 DWORD count,
585 DWORD listBase,
586 FLOAT deviation,
587 FLOAT extrusion,
588 int format,
589 LPGLYPHMETRICSFLOAT lpgmf)
591 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
594 /***********************************************************************
595 * wglUseFontOutlinesW (OPENGL32.@)
597 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
598 DWORD first,
599 DWORD count,
600 DWORD listBase,
601 FLOAT deviation,
602 FLOAT extrusion,
603 int format,
604 LPGLYPHMETRICSFLOAT lpgmf)
606 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
609 /***********************************************************************
610 * glFinish (OPENGL32.@)
612 void WINAPI wine_glFinish( void )
614 TRACE("()\n");
615 wine_wgl.p_wglFinish();
618 /***********************************************************************
619 * glFlush (OPENGL32.@)
621 void WINAPI wine_glFlush( void )
623 TRACE("()\n");
624 wine_wgl.p_wglFlush();
627 /***********************************************************************
628 * glGetString (OPENGL32.@)
630 const GLubyte * WINAPI wine_glGetString( GLenum name )
632 const GLubyte *ret;
633 const char* GL_Extensions = NULL;
635 /* this is for buggy nvidia driver, crashing if called from a different
636 thread with no context */
637 if(wglGetCurrentContext() == NULL)
638 return NULL;
640 if (GL_EXTENSIONS != name) {
641 ENTER_GL();
642 ret = glGetString(name);
643 LEAVE_GL();
644 return ret;
647 if (NULL == internal_gl_extensions) {
648 ENTER_GL();
649 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
651 if (GL_Extensions)
653 size_t len = strlen(GL_Extensions);
654 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
656 TRACE("GL_EXTENSIONS reported:\n");
657 while (*GL_Extensions != 0x00) {
658 const char* Start = GL_Extensions;
659 char ThisExtn[256];
661 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
662 GL_Extensions++;
664 memcpy(ThisExtn, Start, (GL_Extensions - Start));
665 ThisExtn[GL_Extensions - Start] = 0;
666 TRACE("- %s:", ThisExtn);
668 /* test if supported API is disabled by config */
669 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
670 strcat(internal_gl_extensions, " ");
671 strcat(internal_gl_extensions, ThisExtn);
672 TRACE(" active\n");
673 } else {
674 TRACE(" deactived (by config)\n");
677 if (*GL_Extensions == ' ') GL_Extensions++;
680 LEAVE_GL();
682 return (const GLubyte *) internal_gl_extensions;
685 /***********************************************************************
686 * glGetIntegerv (OPENGL32.@)
688 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
690 wine_wgl.p_wglGetIntegerv(pname, params);
694 /* This is for brain-dead applications that use OpenGL functions before even
695 creating a rendering context.... */
696 static BOOL process_attach(void)
698 HMODULE mod_x11, mod_gdi32;
699 DWORD size;
700 HKEY hkey = 0;
702 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
703 mod_x11 = GetModuleHandleA( "winex11.drv" );
704 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
706 if (!mod_x11 || !mod_gdi32)
708 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
709 return FALSE;
712 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
713 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
715 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
717 /* Interal WGL function */
718 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
719 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
720 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
722 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
723 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
724 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
725 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
726 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
728 RegCloseKey(hkey);
731 return TRUE;
735 /**********************************************************************/
737 static void process_detach(void)
739 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
740 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
741 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
744 /***********************************************************************
745 * OpenGL initialisation routine
747 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
749 switch(reason)
751 case DLL_PROCESS_ATTACH:
752 opengl32_handle = hinst;
753 DisableThreadLibraryCalls(hinst);
754 return process_attach();
755 case DLL_PROCESS_DETACH:
756 process_detach();
757 break;
759 return TRUE;