push(c) 7dcddf6204ed5518706a76fe66fd836d81e70dd4
[wine/hacks.git] / dlls / opengl32 / wgl.c
blobec91cfe9dfd3e1a905da434b55831f70b81d1e06
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 /* x11drv GDI escapes */
60 #define X11DRV_ESCAPE 6789
61 enum x11drv_escape_codes
63 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
64 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
65 X11DRV_GET_FONT, /* get current X font for a DC */
66 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
67 X11DRV_START_EXPOSURES, /* start graphics exposures */
68 X11DRV_END_EXPOSURES, /* end graphics exposures */
69 X11DRV_GET_DCE, /* get the DCE pointer */
70 X11DRV_SET_DCE, /* set the DCE pointer */
71 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
72 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
75 void (*wine_tsx11_lock_ptr)(void) = NULL;
76 void (*wine_tsx11_unlock_ptr)(void) = NULL;
78 static HMODULE opengl32_handle;
80 static char internal_gl_disabled_extensions[512];
81 static char* internal_gl_extensions = NULL;
83 typedef struct wine_glcontext {
84 HDC hdc;
85 XVisualInfo *vis;
86 GLXFBConfig fb_conf;
87 GLXContext ctx;
88 BOOL do_escape;
89 /* ... more stuff here */
90 } Wine_GLContext;
92 void enter_gl(void)
94 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
96 if (curctx && curctx->do_escape)
98 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
99 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
102 wine_tsx11_lock_ptr();
103 return;
106 const GLubyte * WINAPI wine_glGetString( GLenum name );
108 /***********************************************************************
109 * wglCreateLayerContext (OPENGL32.@)
111 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
112 int iLayerPlane) {
113 TRACE("(%p,%d)\n", hdc, iLayerPlane);
115 if (iLayerPlane == 0) {
116 return wglCreateContext(hdc);
118 FIXME(" no handler for layer %d\n", iLayerPlane);
120 return NULL;
123 /***********************************************************************
124 * wglCopyContext (OPENGL32.@)
126 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
127 HGLRC hglrcDst,
128 UINT mask) {
129 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
131 return FALSE;
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 HAVE_GL_GLU_H
332 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
334 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
335 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
336 vertex[2] = 0.0;
339 static void tess_callback_vertex(GLvoid *vertex)
341 GLdouble *dbl = vertex;
342 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
343 glVertex3dv(vertex);
346 static void tess_callback_begin(GLenum which)
348 TRACE("%d\n", which);
349 glBegin(which);
352 static void tess_callback_end(void)
354 TRACE("\n");
355 glEnd();
358 /***********************************************************************
359 * wglUseFontOutlines_common
361 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
362 DWORD first,
363 DWORD count,
364 DWORD listBase,
365 FLOAT deviation,
366 FLOAT extrusion,
367 int format,
368 LPGLYPHMETRICSFLOAT lpgmf,
369 BOOL unicode)
371 UINT glyph;
372 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
373 GLUtesselator *tess;
374 LOGFONTW lf;
375 HFONT old_font, unscaled_font;
376 UINT em_size = 1024;
377 RECT rc;
379 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
380 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
383 ENTER_GL();
384 tess = gluNewTess();
385 if(tess)
387 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
388 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
389 gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
391 LEAVE_GL();
393 if(!tess) return FALSE;
395 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
396 rc.left = rc.right = rc.bottom = 0;
397 rc.top = em_size;
398 DPtoLP(hdc, (POINT*)&rc, 2);
399 lf.lfHeight = -abs(rc.top - rc.bottom);
400 lf.lfOrientation = lf.lfEscapement = 0;
401 unscaled_font = CreateFontIndirectW(&lf);
402 old_font = SelectObject(hdc, unscaled_font);
404 for (glyph = first; glyph < first + count; glyph++)
406 DWORD needed;
407 GLYPHMETRICS gm;
408 BYTE *buf;
409 TTPOLYGONHEADER *pph;
410 TTPOLYCURVE *ppc;
411 GLdouble *vertices;
413 if(unicode)
414 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
415 else
416 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
418 if(needed == GDI_ERROR)
419 goto error;
421 buf = HeapAlloc(GetProcessHeap(), 0, needed);
422 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
424 if(unicode)
425 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
426 else
427 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
429 TRACE("glyph %d\n", glyph);
431 if(lpgmf)
433 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
434 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
435 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
436 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
437 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
438 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
440 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
441 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
442 lpgmf++;
445 ENTER_GL();
446 glNewList(listBase++, GL_COMPILE);
447 gluTessBeginPolygon(tess, NULL);
449 pph = (TTPOLYGONHEADER*)buf;
450 while((BYTE*)pph < buf + needed)
452 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
454 gluTessBeginContour(tess);
456 fixed_to_double(pph->pfxStart, em_size, vertices);
457 gluTessVertex(tess, vertices, vertices);
458 vertices += 3;
460 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
461 while((char*)ppc < (char*)pph + pph->cb)
463 int i;
465 switch(ppc->wType) {
466 case TT_PRIM_LINE:
467 for(i = 0; i < ppc->cpfx; i++)
469 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
470 fixed_to_double(ppc->apfx[i], em_size, vertices);
471 gluTessVertex(tess, vertices, vertices);
472 vertices += 3;
474 break;
476 case TT_PRIM_QSPLINE:
477 for(i = 0; i < ppc->cpfx/2; i++)
479 /* FIXME just connecting the control points for now */
480 TRACE("\t\tcurve %d,%d %d,%d\n",
481 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
482 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
483 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
484 gluTessVertex(tess, vertices, vertices);
485 vertices += 3;
486 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
487 gluTessVertex(tess, vertices, vertices);
488 vertices += 3;
490 break;
491 default:
492 ERR("\t\tcurve type = %d\n", ppc->wType);
493 gluTessEndContour(tess);
494 goto error_in_list;
497 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
498 (ppc->cpfx - 1) * sizeof(POINTFX));
500 gluTessEndContour(tess);
501 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
504 error_in_list:
505 gluTessEndPolygon(tess);
506 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
507 glEndList();
508 LEAVE_GL();
509 HeapFree(GetProcessHeap(), 0, buf);
510 HeapFree(GetProcessHeap(), 0, vertices);
513 error:
514 DeleteObject(SelectObject(hdc, old_font));
515 gluDeleteTess(tess);
516 return TRUE;
520 #else /* HAVE_GL_GLU_H */
522 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
523 DWORD first,
524 DWORD count,
525 DWORD listBase,
526 FLOAT deviation,
527 FLOAT extrusion,
528 int format,
529 LPGLYPHMETRICSFLOAT lpgmf,
530 BOOL unicode)
532 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
533 return FALSE;
536 #endif /* HAVE_GL_GLU_H */
538 /***********************************************************************
539 * wglUseFontOutlinesA (OPENGL32.@)
541 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
542 DWORD first,
543 DWORD count,
544 DWORD listBase,
545 FLOAT deviation,
546 FLOAT extrusion,
547 int format,
548 LPGLYPHMETRICSFLOAT lpgmf)
550 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
553 /***********************************************************************
554 * wglUseFontOutlinesW (OPENGL32.@)
556 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
557 DWORD first,
558 DWORD count,
559 DWORD listBase,
560 FLOAT deviation,
561 FLOAT extrusion,
562 int format,
563 LPGLYPHMETRICSFLOAT lpgmf)
565 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
568 /***********************************************************************
569 * glFinish (OPENGL32.@)
571 void WINAPI wine_glFinish( void )
573 TRACE("()\n");
574 wine_wgl.p_wglFinish();
577 /***********************************************************************
578 * glFlush (OPENGL32.@)
580 void WINAPI wine_glFlush( void )
582 TRACE("()\n");
583 wine_wgl.p_wglFlush();
586 /***********************************************************************
587 * glGetString (OPENGL32.@)
589 const GLubyte * WINAPI wine_glGetString( GLenum name )
591 const GLubyte *ret;
592 const char* GL_Extensions = NULL;
594 if (GL_EXTENSIONS != name) {
595 ENTER_GL();
596 ret = glGetString(name);
597 LEAVE_GL();
598 return ret;
601 if (NULL == internal_gl_extensions) {
602 ENTER_GL();
603 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
605 if (GL_Extensions)
607 size_t len = strlen(GL_Extensions);
608 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
610 TRACE("GL_EXTENSIONS reported:\n");
611 while (*GL_Extensions != 0x00) {
612 const char* Start = GL_Extensions;
613 char ThisExtn[256];
615 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
616 GL_Extensions++;
618 memcpy(ThisExtn, Start, (GL_Extensions - Start));
619 ThisExtn[GL_Extensions - Start] = 0;
620 TRACE("- %s:", ThisExtn);
622 /* test if supported API is disabled by config */
623 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
624 strcat(internal_gl_extensions, " ");
625 strcat(internal_gl_extensions, ThisExtn);
626 TRACE(" active\n");
627 } else {
628 TRACE(" deactived (by config)\n");
631 if (*GL_Extensions == ' ') GL_Extensions++;
634 LEAVE_GL();
636 return (const GLubyte *) internal_gl_extensions;
639 /***********************************************************************
640 * glGetIntegerv (OPENGL32.@)
642 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
644 wine_wgl.p_wglGetIntegerv(pname, params);
648 /* This is for brain-dead applications that use OpenGL functions before even
649 creating a rendering context.... */
650 static BOOL process_attach(void)
652 HMODULE mod_x11, mod_gdi32;
653 DWORD size = sizeof(internal_gl_disabled_extensions);
654 HKEY hkey = 0;
656 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
657 mod_x11 = GetModuleHandleA( "winex11.drv" );
658 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
660 if (!mod_x11 || !mod_gdi32)
662 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
663 return FALSE;
666 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
667 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
669 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
671 /* Interal WGL function */
672 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
673 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
674 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
676 internal_gl_disabled_extensions[0] = 0;
677 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
678 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
679 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
681 RegCloseKey(hkey);
684 return TRUE;
688 /**********************************************************************/
690 static void process_detach(void)
692 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
695 /***********************************************************************
696 * OpenGL initialisation routine
698 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
700 switch(reason)
702 case DLL_PROCESS_ATTACH:
703 opengl32_handle = hinst;
704 DisableThreadLibraryCalls(hinst);
705 return process_attach();
706 case DLL_PROCESS_DETACH:
707 process_detach();
708 break;
710 return TRUE;