dsound: Use if(0) instead of #if 0 to make sure code still compiles.
[wine/wine-gecko.git] / dlls / opengl32 / wgl.c
blob74f3d889dee96e1cfc3a3d26eea2556a898eabef
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 static struct
50 PROC (WINAPI *p_wglGetProcAddress)(LPCSTR lpszProc);
51 BOOL (WINAPI *p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
52 HGLRC (WINAPI *p_wglCreateContext)(HDC hdc);
53 void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params);
54 void (WINAPI *p_wglFinish)(void);
55 void (WINAPI *p_wglFlush)(void);
56 } wine_wgl;
58 #ifdef SONAME_LIBGLU
59 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
60 MAKE_FUNCPTR(gluNewTess)
61 MAKE_FUNCPTR(gluDeleteTess)
62 MAKE_FUNCPTR(gluTessBeginContour)
63 MAKE_FUNCPTR(gluTessBeginPolygon)
64 MAKE_FUNCPTR(gluTessCallback)
65 MAKE_FUNCPTR(gluTessEndContour)
66 MAKE_FUNCPTR(gluTessEndPolygon)
67 MAKE_FUNCPTR(gluTessVertex)
68 #undef MAKE_FUNCPTR
69 #endif /* SONAME_LIBGLU */
71 /* x11drv GDI escapes */
72 #define X11DRV_ESCAPE 6789
73 enum x11drv_escape_codes
75 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
76 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
77 X11DRV_GET_FONT, /* get current X font for a DC */
78 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
79 X11DRV_START_EXPOSURES, /* start graphics exposures */
80 X11DRV_END_EXPOSURES, /* end graphics exposures */
81 X11DRV_GET_DCE, /* get the DCE pointer */
82 X11DRV_SET_DCE, /* set the DCE pointer */
83 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
84 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
87 void (*wine_tsx11_lock_ptr)(void) = NULL;
88 void (*wine_tsx11_unlock_ptr)(void) = NULL;
90 static HMODULE opengl32_handle;
91 static void* libglu_handle = NULL;
93 static char* internal_gl_disabled_extensions = NULL;
94 static char* internal_gl_extensions = NULL;
96 typedef struct wine_glcontext {
97 HDC hdc;
98 BOOL do_escape;
99 /* ... more stuff here */
100 } Wine_GLContext;
102 void enter_gl(void)
104 Wine_GLContext *curctx = NtCurrentTeb()->glContext;
106 if (curctx && curctx->do_escape)
108 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
109 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
112 wine_tsx11_lock_ptr();
113 return;
116 const GLubyte * WINAPI wine_glGetString( GLenum name );
118 /***********************************************************************
119 * wglMakeCurrent (OPENGL32.@)
121 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
123 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
126 /***********************************************************************
127 * wglCreateContext (OPENGL32.@)
129 HGLRC WINAPI wglCreateContext(HDC hdc)
131 return wine_wgl.p_wglCreateContext(hdc);
134 /***********************************************************************
135 * wglCreateLayerContext (OPENGL32.@)
137 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
138 int iLayerPlane) {
139 TRACE("(%p,%d)\n", hdc, iLayerPlane);
141 if (iLayerPlane == 0) {
142 return wglCreateContext(hdc);
144 FIXME(" no handler for layer %d\n", iLayerPlane);
146 return NULL;
149 /***********************************************************************
150 * wglDescribeLayerPlane (OPENGL32.@)
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);
159 return FALSE;
162 /***********************************************************************
163 * wglGetLayerPaletteEntries (OPENGL32.@)
165 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
166 int iLayerPlane,
167 int iStart,
168 int cEntries,
169 const COLORREF *pcr) {
170 FIXME("(): stub !\n");
172 return 0;
175 static int compar(const void *elt_a, const void *elt_b) {
176 return strcmp(((const OpenGL_extension *) elt_a)->name,
177 ((const OpenGL_extension *) elt_b)->name);
180 /* Check if a GL extension is supported */
181 static BOOL is_extension_supported(const char* extension)
183 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
185 TRACE("Checking for extension '%s'\n", extension);
187 if(!gl_ext_string) {
188 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
189 return FALSE;
192 /* We use the GetProcAddress function from the display driver to retrieve function pointers
193 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
194 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
195 * require the function to return NULL when a extension isn't found. For this reason we check
196 * if the OpenGL extension required for the function we are looking up is supported. */
198 /* Check if the extension is part of the GL extension string to see if it is supported. */
199 if(strstr(gl_ext_string, extension) != NULL)
200 return TRUE;
202 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
203 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
204 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
205 * Check if we are searching for a core GL function */
206 if(strncmp(extension, "GL_VERSION_", 11) == 0)
208 const GLubyte *gl_version = glGetString(GL_VERSION);
209 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
211 if(!gl_version) {
212 ERR("Error no OpenGL version found,\n");
213 return FALSE;
216 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
217 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
218 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
219 return TRUE;
221 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]);
224 return FALSE;
227 /***********************************************************************
228 * wglGetProcAddress (OPENGL32.@)
230 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
231 void *local_func;
232 OpenGL_extension ext;
233 const OpenGL_extension *ext_ret;
235 TRACE("(%s)\n", lpszProc);
237 if(lpszProc == NULL)
238 return NULL;
240 /* First, look if it's not already defined in the 'standard' OpenGL functions */
241 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
242 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
243 return local_func;
246 /* After that, search in the thunks to find the real name of the extension */
247 ext.name = lpszProc;
248 ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
249 sizeof(OpenGL_extension), compar);
251 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
252 if (ext_ret == NULL) {
253 /* If the function name starts with a w it is a WGL extension */
254 if(lpszProc[0] == 'w')
255 return wine_wgl.p_wglGetProcAddress(lpszProc);
257 /* We are dealing with an unknown GL extension. */
258 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
259 return NULL;
260 } else { /* We are looking for an OpenGL extension */
262 /* Check if the GL extension required by the function is available */
263 if(!is_extension_supported(ext_ret->extension)) {
264 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
267 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
269 /* After that, look at the extensions defined in the Linux OpenGL library */
270 if (local_func == NULL) {
271 char buf[256];
272 void *ret = NULL;
274 /* Remove the 3 last letters (EXT, ARB, ...).
276 I know that some extensions have more than 3 letters (MESA, NV,
277 INTEL, ...), but this is only a stop-gap measure to fix buggy
278 OpenGL drivers (moreover, it is only useful for old 1.0 apps
279 that query the glBindTextureEXT extension).
281 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
282 buf[strlen(ext_ret->name) - 3] = '\0';
283 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
285 ret = GetProcAddress(opengl32_handle, buf);
286 if (ret != NULL) {
287 TRACE(" found function in main OpenGL library (%p) !\n", ret);
288 } else {
289 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
292 return ret;
293 } else {
294 TRACE(" returning function (%p)\n", ext_ret->func);
295 extension_funcs[ext_ret - extension_registry] = local_func;
297 return ext_ret->func;
302 /***********************************************************************
303 * wglRealizeLayerPalette (OPENGL32.@)
305 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
306 int iLayerPlane,
307 BOOL bRealize) {
308 FIXME("()\n");
310 return FALSE;
313 /***********************************************************************
314 * wglSetLayerPaletteEntries (OPENGL32.@)
316 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
317 int iLayerPlane,
318 int iStart,
319 int cEntries,
320 const COLORREF *pcr) {
321 FIXME("(): stub !\n");
323 return 0;
326 /***********************************************************************
327 * wglSwapLayerBuffers (OPENGL32.@)
329 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
330 UINT fuPlanes) {
331 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
333 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
334 if (!SwapBuffers(hdc)) return FALSE;
335 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
338 if (fuPlanes) {
339 WARN("Following layers unhandled : %08x\n", fuPlanes);
342 return TRUE;
345 #ifdef SONAME_LIBGLU
347 static void *load_libglu(void)
349 static int already_loaded;
350 void *handle;
352 if (already_loaded) return libglu_handle;
353 already_loaded = 1;
355 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
356 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
357 if (!handle)
359 WARN("Failed to load %s\n", SONAME_LIBGLU);
360 return NULL;
363 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
364 LOAD_FUNCPTR(gluNewTess)
365 LOAD_FUNCPTR(gluDeleteTess)
366 LOAD_FUNCPTR(gluTessBeginContour)
367 LOAD_FUNCPTR(gluTessBeginPolygon)
368 LOAD_FUNCPTR(gluTessCallback)
369 LOAD_FUNCPTR(gluTessEndContour)
370 LOAD_FUNCPTR(gluTessEndPolygon)
371 LOAD_FUNCPTR(gluTessVertex)
372 #undef LOAD_FUNCPTR
373 libglu_handle = handle;
374 return handle;
376 sym_not_found:
377 WARN("Unable to load function ptrs from libGLU\n");
378 /* Close the library as we won't use it */
379 wine_dlclose(handle, NULL, 0);
380 return NULL;
383 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
385 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
386 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
387 vertex[2] = 0.0;
390 static void tess_callback_vertex(GLvoid *vertex)
392 GLdouble *dbl = vertex;
393 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
394 glVertex3dv(vertex);
397 static void tess_callback_begin(GLenum which)
399 TRACE("%d\n", which);
400 glBegin(which);
403 static void tess_callback_end(void)
405 TRACE("\n");
406 glEnd();
409 /***********************************************************************
410 * wglUseFontOutlines_common
412 static BOOL wglUseFontOutlines_common(HDC hdc,
413 DWORD first,
414 DWORD count,
415 DWORD listBase,
416 FLOAT deviation,
417 FLOAT extrusion,
418 int format,
419 LPGLYPHMETRICSFLOAT lpgmf,
420 BOOL unicode)
422 UINT glyph;
423 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
424 GLUtesselator *tess;
425 LOGFONTW lf;
426 HFONT old_font, unscaled_font;
427 UINT em_size = 1024;
428 RECT rc;
430 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
431 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
433 if (!load_libglu())
435 ERR("libGLU is required for this function but isn't loaded\n");
436 return FALSE;
439 ENTER_GL();
440 tess = pgluNewTess();
441 if(tess)
443 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
444 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
445 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
447 LEAVE_GL();
449 if(!tess) return FALSE;
451 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
452 rc.left = rc.right = rc.bottom = 0;
453 rc.top = em_size;
454 DPtoLP(hdc, (POINT*)&rc, 2);
455 lf.lfHeight = -abs(rc.top - rc.bottom);
456 lf.lfOrientation = lf.lfEscapement = 0;
457 unscaled_font = CreateFontIndirectW(&lf);
458 old_font = SelectObject(hdc, unscaled_font);
460 for (glyph = first; glyph < first + count; glyph++)
462 DWORD needed;
463 GLYPHMETRICS gm;
464 BYTE *buf;
465 TTPOLYGONHEADER *pph;
466 TTPOLYCURVE *ppc;
467 GLdouble *vertices;
469 if(unicode)
470 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
471 else
472 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
474 if(needed == GDI_ERROR)
475 goto error;
477 buf = HeapAlloc(GetProcessHeap(), 0, needed);
478 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
480 if(unicode)
481 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
482 else
483 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
485 TRACE("glyph %d\n", glyph);
487 if(lpgmf)
489 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
490 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
491 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
492 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
493 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
494 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
496 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
497 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
498 lpgmf++;
501 ENTER_GL();
502 glNewList(listBase++, GL_COMPILE);
503 pgluTessBeginPolygon(tess, NULL);
505 pph = (TTPOLYGONHEADER*)buf;
506 while((BYTE*)pph < buf + needed)
508 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
510 pgluTessBeginContour(tess);
512 fixed_to_double(pph->pfxStart, em_size, vertices);
513 pgluTessVertex(tess, vertices, vertices);
514 vertices += 3;
516 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
517 while((char*)ppc < (char*)pph + pph->cb)
519 int i;
521 switch(ppc->wType) {
522 case TT_PRIM_LINE:
523 for(i = 0; i < ppc->cpfx; i++)
525 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
526 fixed_to_double(ppc->apfx[i], em_size, vertices);
527 pgluTessVertex(tess, vertices, vertices);
528 vertices += 3;
530 break;
532 case TT_PRIM_QSPLINE:
533 for(i = 0; i < ppc->cpfx/2; i++)
535 /* FIXME just connecting the control points for now */
536 TRACE("\t\tcurve %d,%d %d,%d\n",
537 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
538 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
539 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
540 pgluTessVertex(tess, vertices, vertices);
541 vertices += 3;
542 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
543 pgluTessVertex(tess, vertices, vertices);
544 vertices += 3;
546 break;
547 default:
548 ERR("\t\tcurve type = %d\n", ppc->wType);
549 pgluTessEndContour(tess);
550 goto error_in_list;
553 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
554 (ppc->cpfx - 1) * sizeof(POINTFX));
556 pgluTessEndContour(tess);
557 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
560 error_in_list:
561 pgluTessEndPolygon(tess);
562 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
563 glEndList();
564 LEAVE_GL();
565 HeapFree(GetProcessHeap(), 0, buf);
566 HeapFree(GetProcessHeap(), 0, vertices);
569 error:
570 DeleteObject(SelectObject(hdc, old_font));
571 pgluDeleteTess(tess);
572 return TRUE;
576 #else /* SONAME_LIBGLU */
578 static BOOL wglUseFontOutlines_common(HDC hdc,
579 DWORD first,
580 DWORD count,
581 DWORD listBase,
582 FLOAT deviation,
583 FLOAT extrusion,
584 int format,
585 LPGLYPHMETRICSFLOAT lpgmf,
586 BOOL unicode)
588 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
589 return FALSE;
592 #endif /* SONAME_LIBGLU */
594 /***********************************************************************
595 * wglUseFontOutlinesA (OPENGL32.@)
597 BOOL WINAPI wglUseFontOutlinesA(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, FALSE);
609 /***********************************************************************
610 * wglUseFontOutlinesW (OPENGL32.@)
612 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
613 DWORD first,
614 DWORD count,
615 DWORD listBase,
616 FLOAT deviation,
617 FLOAT extrusion,
618 int format,
619 LPGLYPHMETRICSFLOAT lpgmf)
621 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
624 /***********************************************************************
625 * glFinish (OPENGL32.@)
627 void WINAPI wine_glFinish( void )
629 TRACE("()\n");
630 wine_wgl.p_wglFinish();
633 /***********************************************************************
634 * glFlush (OPENGL32.@)
636 void WINAPI wine_glFlush( void )
638 TRACE("()\n");
639 wine_wgl.p_wglFlush();
642 /***********************************************************************
643 * glGetString (OPENGL32.@)
645 const GLubyte * WINAPI wine_glGetString( GLenum name )
647 const GLubyte *ret;
648 const char* GL_Extensions = NULL;
650 /* this is for buggy nvidia driver, crashing if called from a different
651 thread with no context */
652 if(wglGetCurrentContext() == NULL)
653 return NULL;
655 if (GL_EXTENSIONS != name) {
656 ENTER_GL();
657 ret = glGetString(name);
658 LEAVE_GL();
659 return ret;
662 if (NULL == internal_gl_extensions) {
663 ENTER_GL();
664 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
666 if (GL_Extensions)
668 size_t len = strlen(GL_Extensions);
669 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
671 TRACE("GL_EXTENSIONS reported:\n");
672 while (*GL_Extensions != 0x00) {
673 const char* Start = GL_Extensions;
674 char ThisExtn[256];
676 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
677 GL_Extensions++;
679 memcpy(ThisExtn, Start, (GL_Extensions - Start));
680 ThisExtn[GL_Extensions - Start] = 0;
681 TRACE("- %s:", ThisExtn);
683 /* test if supported API is disabled by config */
684 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
685 strcat(internal_gl_extensions, " ");
686 strcat(internal_gl_extensions, ThisExtn);
687 TRACE(" active\n");
688 } else {
689 TRACE(" deactived (by config)\n");
692 if (*GL_Extensions == ' ') GL_Extensions++;
695 LEAVE_GL();
697 return (const GLubyte *) internal_gl_extensions;
700 /***********************************************************************
701 * glGetIntegerv (OPENGL32.@)
703 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
705 wine_wgl.p_wglGetIntegerv(pname, params);
708 /***********************************************************************
709 * wglSwapBuffers (OPENGL32.@)
711 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
713 return SwapBuffers(hdc);
716 /* This is for brain-dead applications that use OpenGL functions before even
717 creating a rendering context.... */
718 static BOOL process_attach(void)
720 HMODULE mod_x11, mod_gdi32;
721 DWORD size;
722 HKEY hkey = 0;
724 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
725 mod_x11 = GetModuleHandleA( "winex11.drv" );
726 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
728 if (!mod_x11 || !mod_gdi32)
730 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
731 return FALSE;
734 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
735 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
737 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
738 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod_gdi32, "wglMakeCurrent");
739 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod_gdi32, "wglCreateContext");
741 /* Interal WGL function */
742 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
743 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
744 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
746 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
747 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
748 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
749 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
750 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
752 RegCloseKey(hkey);
755 return TRUE;
759 /**********************************************************************/
761 static void process_detach(void)
763 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
764 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
765 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
768 /***********************************************************************
769 * OpenGL initialisation routine
771 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
773 switch(reason)
775 case DLL_PROCESS_ATTACH:
776 opengl32_handle = hinst;
777 DisableThreadLibraryCalls(hinst);
778 return process_attach();
779 case DLL_PROCESS_DETACH:
780 process_detach();
781 break;
783 return TRUE;