Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / opengl32 / wgl.c
blob6cb4e41e06be5bc6ab488e343a3db508cfbe6e8e
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 "winerror.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winternl.h"
35 #include "winnt.h"
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"
46 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
47 WINE_DECLARE_DEBUG_CHANNEL(opengl);
49 typedef struct wine_wgl_s {
50 PROC WINAPI (*p_wglGetProcAddress)(LPCSTR lpszProc);
52 void WINAPI (*p_wglDisable)(GLenum cap);
53 void WINAPI (*p_wglEnable)(GLenum cap);
54 void WINAPI (*p_wglGetIntegerv)(GLenum pname, GLint* params);
55 GLboolean WINAPI (*p_wglIsEnabled)(GLenum cap);
56 void WINAPI (*p_wglScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
57 void WINAPI (*p_wglViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
58 } wine_wgl_t;
60 /** global wgl object */
61 static wine_wgl_t wine_wgl;
63 /* x11drv GDI escapes */
64 #define X11DRV_ESCAPE 6789
65 enum x11drv_escape_codes
67 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
68 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
69 X11DRV_GET_FONT, /* get current X font for a DC */
70 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
71 X11DRV_START_EXPOSURES, /* start graphics exposures */
72 X11DRV_END_EXPOSURES, /* end graphics exposures */
73 X11DRV_GET_DCE, /* get the DCE pointer */
74 X11DRV_SET_DCE, /* set the DCE pointer */
75 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
76 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
79 void (*wine_tsx11_lock_ptr)(void) = NULL;
80 void (*wine_tsx11_unlock_ptr)(void) = NULL;
82 static HMODULE opengl32_handle;
84 static char internal_gl_disabled_extensions[512];
85 static BOOL wowhack = FALSE;
86 static char* internal_gl_extensions = NULL;
88 typedef struct wine_glcontext {
89 HDC hdc;
90 XVisualInfo *vis;
91 GLXFBConfig fb_conf;
92 GLXContext ctx;
93 BOOL do_escape;
94 /* ... more stuff here */
95 } Wine_GLContext;
97 void enter_gl(void)
99 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
101 if (curctx && curctx->do_escape)
103 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
104 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
107 wine_tsx11_lock_ptr();
108 return;
112 * Get a config key from either the app-specific or the default config
115 inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
116 char *buffer, DWORD size )
118 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
119 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0;
120 return ERROR_FILE_NOT_FOUND;
123 const GLubyte * WINAPI wine_glGetString( GLenum name );
125 /***********************************************************************
126 * wglCreateLayerContext (OPENGL32.@)
128 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
129 int iLayerPlane) {
130 TRACE("(%p,%d)\n", hdc, iLayerPlane);
132 if (iLayerPlane == 0) {
133 return wglCreateContext(hdc);
135 FIXME(" no handler for layer %d\n", iLayerPlane);
137 return NULL;
140 /***********************************************************************
141 * wglCopyContext (OPENGL32.@)
143 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
144 HGLRC hglrcDst,
145 UINT mask) {
146 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
148 return FALSE;
151 /***********************************************************************
152 * wglDescribeLayerPlane (OPENGL32.@)
154 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
155 int iPixelFormat,
156 int iLayerPlane,
157 UINT nBytes,
158 LPLAYERPLANEDESCRIPTOR plpd) {
159 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
161 return FALSE;
164 /***********************************************************************
165 * wglGetLayerPaletteEntries (OPENGL32.@)
167 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
168 int iLayerPlane,
169 int iStart,
170 int cEntries,
171 const COLORREF *pcr) {
172 FIXME("(): stub !\n");
174 return 0;
177 static int compar(const void *elt_a, const void *elt_b) {
178 return strcmp(((const OpenGL_extension *) elt_a)->name,
179 ((const OpenGL_extension *) elt_b)->name);
182 /* Check if a GL extension is supported */
183 static BOOL is_extension_supported(const char* extension)
185 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
187 TRACE("Checking for extension '%s'\n", extension);
189 if(!gl_ext_string) {
190 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
191 return FALSE;
194 /* We use the GetProcAddress function from the display driver to retrieve function pointers
195 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
196 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
197 * require the function to return NULL when a extension isn't found. For this reason we check
198 * if the OpenGL extension required for the function we are looking up is supported. */
200 /* Check if the extension is part of the GL extension string to see if it is supported. */
201 if(strstr(gl_ext_string, extension) != NULL)
202 return TRUE;
204 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
205 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
206 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
207 * Check if we are searching for a core GL function */
208 if(strncmp(extension, "GL_VERSION_", 11) == 0)
210 const GLubyte *gl_version = glGetString(GL_VERSION);
211 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
213 if(!gl_version) {
214 ERR("Error no OpenGL version found,\n");
215 return FALSE;
218 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
219 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
220 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
221 return TRUE;
223 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]);
226 return FALSE;
229 /***********************************************************************
230 * wglGetProcAddress (OPENGL32.@)
232 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
233 void *local_func;
234 OpenGL_extension ext;
235 const OpenGL_extension *ext_ret;
237 TRACE("(%s)\n", lpszProc);
239 if(lpszProc == NULL)
240 return NULL;
242 /* First, look if it's not already defined in the 'standard' OpenGL functions */
243 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
244 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
245 return local_func;
248 /* After that, search in the thunks to find the real name of the extension */
249 ext.name = lpszProc;
250 ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
251 extension_registry_size, sizeof(OpenGL_extension), compar);
253 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
254 if (ext_ret == NULL) {
255 /* If the function name starts with a w it is a WGL extension */
256 if(lpszProc[0] == 'w')
257 return wine_wgl.p_wglGetProcAddress(lpszProc);
259 /* We are dealing with an unknown GL extension. */
260 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
261 return NULL;
262 } else { /* We are looking for an OpenGL extension */
264 /* Check if the GL extension required by the function is available */
265 if(!is_extension_supported(ext_ret->extension)) {
266 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
267 return NULL;
270 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
272 /* After that, look at the extensions defined in the Linux OpenGL library */
273 if (local_func == NULL) {
274 char buf[256];
275 void *ret = NULL;
277 /* Remove the 3 last letters (EXT, ARB, ...).
279 I know that some extensions have more than 3 letters (MESA, NV,
280 INTEL, ...), but this is only a stop-gap measure to fix buggy
281 OpenGL drivers (moreover, it is only useful for old 1.0 apps
282 that query the glBindTextureEXT extension).
284 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
285 buf[strlen(ext_ret->name) - 3] = '\0';
286 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
288 ret = GetProcAddress(opengl32_handle, buf);
289 if (ret != NULL) {
290 TRACE(" found function in main OpenGL library (%p) !\n", ret);
291 } else {
292 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
295 return ret;
296 } else {
297 TRACE(" returning function (%p)\n", ext_ret->func);
298 extension_funcs[ext_ret - extension_registry] = local_func;
300 return ext_ret->func;
305 /***********************************************************************
306 * wglRealizeLayerPalette (OPENGL32.@)
308 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
309 int iLayerPlane,
310 BOOL bRealize) {
311 FIXME("()\n");
313 return FALSE;
316 /***********************************************************************
317 * wglSetLayerPaletteEntries (OPENGL32.@)
319 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
320 int iLayerPlane,
321 int iStart,
322 int cEntries,
323 const COLORREF *pcr) {
324 FIXME("(): stub !\n");
326 return 0;
329 /***********************************************************************
330 * wglSwapLayerBuffers (OPENGL32.@)
332 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
333 UINT fuPlanes) {
334 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
336 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
337 if (!SwapBuffers(hdc)) return FALSE;
338 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
341 if (fuPlanes) {
342 WARN("Following layers unhandled : %08x\n", fuPlanes);
345 return TRUE;
348 #ifdef HAVE_GL_GLU_H
350 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
352 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
353 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
354 vertex[2] = 0.0;
357 static void tess_callback_vertex(GLvoid *vertex)
359 GLdouble *dbl = vertex;
360 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
361 glVertex3dv(vertex);
364 static void tess_callback_begin(GLenum which)
366 TRACE("%d\n", which);
367 glBegin(which);
370 static void tess_callback_end(void)
372 TRACE("\n");
373 glEnd();
376 /***********************************************************************
377 * wglUseFontOutlines_common
379 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
380 DWORD first,
381 DWORD count,
382 DWORD listBase,
383 FLOAT deviation,
384 FLOAT extrusion,
385 int format,
386 LPGLYPHMETRICSFLOAT lpgmf,
387 BOOL unicode)
389 UINT glyph;
390 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
391 GLUtesselator *tess;
392 LOGFONTW lf;
393 HFONT old_font, unscaled_font;
394 UINT em_size = 1024;
395 RECT rc;
397 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
398 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
401 ENTER_GL();
402 tess = gluNewTess();
403 if(tess)
405 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
406 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
407 gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
409 LEAVE_GL();
411 if(!tess) return FALSE;
413 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
414 rc.left = rc.right = rc.bottom = 0;
415 rc.top = em_size;
416 DPtoLP(hdc, (POINT*)&rc, 2);
417 lf.lfHeight = -abs(rc.top - rc.bottom);
418 lf.lfOrientation = lf.lfEscapement = 0;
419 unscaled_font = CreateFontIndirectW(&lf);
420 old_font = SelectObject(hdc, unscaled_font);
422 for (glyph = first; glyph < first + count; glyph++)
424 DWORD needed;
425 GLYPHMETRICS gm;
426 BYTE *buf;
427 TTPOLYGONHEADER *pph;
428 TTPOLYCURVE *ppc;
429 GLdouble *vertices;
431 if(unicode)
432 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
433 else
434 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
436 if(needed == GDI_ERROR)
437 goto error;
439 buf = HeapAlloc(GetProcessHeap(), 0, needed);
440 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
442 if(unicode)
443 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
444 else
445 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
447 TRACE("glyph %d\n", glyph);
449 if(lpgmf)
451 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
452 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
453 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
454 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
455 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
456 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
458 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
459 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
460 lpgmf++;
463 ENTER_GL();
464 glNewList(listBase++, GL_COMPILE);
465 gluTessBeginPolygon(tess, NULL);
467 pph = (TTPOLYGONHEADER*)buf;
468 while((BYTE*)pph < buf + needed)
470 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
472 gluTessBeginContour(tess);
474 fixed_to_double(pph->pfxStart, em_size, vertices);
475 gluTessVertex(tess, vertices, vertices);
476 vertices += 3;
478 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
479 while((char*)ppc < (char*)pph + pph->cb)
481 int i;
483 switch(ppc->wType) {
484 case TT_PRIM_LINE:
485 for(i = 0; i < ppc->cpfx; i++)
487 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
488 fixed_to_double(ppc->apfx[i], em_size, vertices);
489 gluTessVertex(tess, vertices, vertices);
490 vertices += 3;
492 break;
494 case TT_PRIM_QSPLINE:
495 for(i = 0; i < ppc->cpfx/2; i++)
497 /* FIXME just connecting the control points for now */
498 TRACE("\t\tcurve %d,%d %d,%d\n",
499 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
500 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
501 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
502 gluTessVertex(tess, vertices, vertices);
503 vertices += 3;
504 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
505 gluTessVertex(tess, vertices, vertices);
506 vertices += 3;
508 break;
509 default:
510 ERR("\t\tcurve type = %d\n", ppc->wType);
511 gluTessEndContour(tess);
512 goto error_in_list;
515 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
516 (ppc->cpfx - 1) * sizeof(POINTFX));
518 gluTessEndContour(tess);
519 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
522 error_in_list:
523 gluTessEndPolygon(tess);
524 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
525 glEndList();
526 LEAVE_GL();
527 HeapFree(GetProcessHeap(), 0, buf);
528 HeapFree(GetProcessHeap(), 0, vertices);
531 error:
532 DeleteObject(SelectObject(hdc, old_font));
533 gluDeleteTess(tess);
534 return TRUE;
538 #else /* HAVE_GL_GLU_H */
540 static BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
541 DWORD first,
542 DWORD count,
543 DWORD listBase,
544 FLOAT deviation,
545 FLOAT extrusion,
546 int format,
547 LPGLYPHMETRICSFLOAT lpgmf,
548 BOOL unicode)
550 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
551 return FALSE;
554 #endif /* HAVE_GL_GLU_H */
556 /***********************************************************************
557 * wglUseFontOutlinesA (OPENGL32.@)
559 BOOL WINAPI wglUseFontOutlinesA(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, FALSE);
571 /***********************************************************************
572 * wglUseFontOutlinesW (OPENGL32.@)
574 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
575 DWORD first,
576 DWORD count,
577 DWORD listBase,
578 FLOAT deviation,
579 FLOAT extrusion,
580 int format,
581 LPGLYPHMETRICSFLOAT lpgmf)
583 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
586 /***********************************************************************
587 * glEnable (OPENGL32.@)
589 void WINAPI wine_glEnable( GLenum cap )
591 TRACE("(%d)\n", cap );
592 wine_wgl.p_wglEnable(cap);
595 /***********************************************************************
596 * glIsEnabled (OPENGL32.@)
598 GLboolean WINAPI wine_glIsEnabled( GLenum cap )
600 TRACE("(%d)\n", cap );
601 return wine_wgl.p_wglIsEnabled(cap);
604 /***********************************************************************
605 * glDisable (OPENGL32.@)
607 void WINAPI wine_glDisable( GLenum cap )
609 TRACE("(%d)\n", cap );
610 wine_wgl.p_wglDisable(cap);
613 /***********************************************************************
614 * glScissor (OPENGL32.@)
616 void WINAPI wine_glScissor( GLint x, GLint y, GLsizei width, GLsizei height )
618 TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
619 wine_wgl.p_wglScissor(x, y, width, height);
622 /***********************************************************************
623 * glViewport (OPENGL32.@)
625 void WINAPI wine_glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
627 TRACE("(%d, %d, %d, %d)\n", x, y, width, height );
628 wine_wgl.p_wglViewport(x, y, width, height);
631 /***********************************************************************
632 * glGetString (OPENGL32.@)
634 const GLubyte * WINAPI wine_glGetString( GLenum name )
636 const GLubyte *ret;
637 const char* GL_Extensions = NULL;
639 if (GL_EXTENSIONS != name) {
640 ENTER_GL();
641 ret = glGetString(name);
642 LEAVE_GL();
643 return ret;
646 if (NULL == internal_gl_extensions) {
647 ENTER_GL();
648 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
650 if (GL_Extensions)
652 size_t len = strlen(GL_Extensions);
653 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
655 TRACE("GL_EXTENSIONS reported:\n");
656 while (*GL_Extensions != 0x00) {
657 const char* Start = GL_Extensions;
658 char ThisExtn[256];
660 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
661 GL_Extensions++;
663 memcpy(ThisExtn, Start, (GL_Extensions - Start));
664 ThisExtn[GL_Extensions - Start] = 0;
665 TRACE("- %s:", ThisExtn);
667 /* test if supported API is disabled by config */
668 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
669 strcat(internal_gl_extensions, " ");
670 strcat(internal_gl_extensions, ThisExtn);
671 TRACE(" active\n");
672 } else {
673 TRACE(" deactived (by config)\n");
676 if (*GL_Extensions == ' ') GL_Extensions++;
679 LEAVE_GL();
681 return (const GLubyte *) internal_gl_extensions;
684 /***********************************************************************
685 * glGetIntegerv (OPENGL32.@)
687 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
689 wine_wgl.p_wglGetIntegerv(pname, params);
693 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
694 include all dependencies
696 #ifndef SONAME_LIBGL
697 #define SONAME_LIBGL "libGL.so"
698 #endif
700 #define IS_OPTION_TRUE(ch) \
701 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
702 #define IS_OPTION_FALSE(ch) \
703 ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
705 /* This is for brain-dead applications that use OpenGL functions before even
706 creating a rendering context.... */
707 static BOOL process_attach(void)
709 HMODULE mod_x11, mod_gdi32;
710 DWORD size = sizeof(internal_gl_disabled_extensions);
711 char tmp[32];
712 HKEY hkey = 0;
713 HKEY appkey = 0;
714 char buffer[MAX_PATH+10];
715 DWORD len;
717 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
718 mod_x11 = GetModuleHandleA( "winex11.drv" );
719 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
721 if (!mod_x11 || !mod_gdi32)
723 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
724 return FALSE;
727 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
728 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
730 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
732 /* Interal WGL function */
733 wine_wgl.p_wglDisable = (void *)wine_wgl.p_wglGetProcAddress("wglDisable");
734 wine_wgl.p_wglEnable = (void *)wine_wgl.p_wglGetProcAddress("wglEnable");
735 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
736 wine_wgl.p_wglIsEnabled = (void *)wine_wgl.p_wglGetProcAddress("wglIsEnabled");
737 wine_wgl.p_wglScissor = (void *)wine_wgl.p_wglGetProcAddress("wglScissor");
738 wine_wgl.p_wglViewport = (void *)wine_wgl.p_wglGetProcAddress("wglViewport");
740 internal_gl_disabled_extensions[0] = 0;
742 /* @@ Wine registry key: HKLM\Software\Wine\OpenGL */
743 if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey) ) hkey = 0;
745 len = GetModuleFileNameA( 0, buffer, MAX_PATH );
746 if (len && len < MAX_PATH)
748 HKEY tmpkey;
749 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\OpenGL */
750 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
752 char *p, *appname = buffer;
753 if ((p = strrchr( appname, '/' ))) appname = p + 1;
754 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
755 strcat( appname, "\\OpenGL" );
756 TRACE("appname = [%s]\n", appname);
757 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
758 RegCloseKey( tmpkey );
762 if ( 0 != hkey || 0 != appkey ) {
763 if ( !get_config_key( hkey, appkey, "DisabledExtensions", internal_gl_disabled_extensions, size) ) {
764 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
766 size = sizeof(tmp);
767 if ( !get_config_key( hkey, appkey, "wowhack", tmp, size) ) {
768 TRACE("found wowhack=\"%s\"\n", tmp);
769 if(IS_OPTION_TRUE(tmp[0])) wowhack = TRUE;
772 if (appkey)
773 RegCloseKey( appkey );
774 if (hkey)
775 RegCloseKey( hkey );
778 return TRUE;
782 /**********************************************************************/
784 static void process_detach(void)
786 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
789 /***********************************************************************
790 * OpenGL initialisation routine
792 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
794 switch(reason)
796 case DLL_PROCESS_ATTACH:
797 opengl32_handle = hinst;
798 DisableThreadLibraryCalls(hinst);
799 return process_attach();
800 case DLL_PROCESS_DETACH:
801 process_detach();
802 break;
804 return TRUE;