ntdll: Get the unix tid on DragonFly BSD.
[wine/multimedia.git] / dlls / opengl32 / wgl.c
blob98b04d411a7042e2f19e4f0250aaaeb3ce92bc28
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_SetPixelFormat)(HDC hdc, INT iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd);
52 BOOL (WINAPI *p_wglCopyContext)(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask);
53 BOOL (WINAPI *p_wglDeleteContext)(HGLRC hglrc);
54 BOOL (WINAPI *p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
55 BOOL (WINAPI *p_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
56 BOOL (WINAPI *p_wglUseFontBitmapsA)(HDC hdc, DWORD first, DWORD count, DWORD listBase);
57 BOOL (WINAPI *p_wglUseFontBitmapsW)(HDC hdc, DWORD first, DWORD count, DWORD listBase);
58 HDC (WINAPI *p_wglGetCurrentDC)(void);
59 HGLRC (WINAPI *p_wglCreateContext)(HDC hdc);
60 HGLRC (WINAPI *p_wglGetCurrentContext)(void);
61 INT (WINAPI *p_ChoosePixelFormat)(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd);
62 INT (WINAPI *p_DescribePixelFormat)(HDC hdc, INT iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd);
63 INT (WINAPI *p_GetPixelFormat)(HDC hdc);
65 /* Interal WGL function */
66 void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params);
67 void (WINAPI *p_wglFinish)(void);
68 void (WINAPI *p_wglFlush)(void);
69 } wine_wgl;
71 #ifdef SONAME_LIBGLU
72 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
73 MAKE_FUNCPTR(gluNewTess)
74 MAKE_FUNCPTR(gluDeleteTess)
75 MAKE_FUNCPTR(gluTessBeginContour)
76 MAKE_FUNCPTR(gluTessBeginPolygon)
77 MAKE_FUNCPTR(gluTessCallback)
78 MAKE_FUNCPTR(gluTessEndContour)
79 MAKE_FUNCPTR(gluTessEndPolygon)
80 MAKE_FUNCPTR(gluTessVertex)
81 #undef MAKE_FUNCPTR
82 #endif /* SONAME_LIBGLU */
84 void (*wine_tsx11_lock_ptr)(void) = NULL;
85 void (*wine_tsx11_unlock_ptr)(void) = NULL;
87 static HMODULE opengl32_handle;
88 static void* libglu_handle = NULL;
90 static char* internal_gl_disabled_extensions = NULL;
91 static char* internal_gl_extensions = NULL;
93 const GLubyte * WINAPI wine_glGetString( GLenum name );
95 /***********************************************************************
96 * wglSetPixelFormat(OPENGL32.@)
98 BOOL WINAPI wglSetPixelFormat( HDC hdc, INT iPixelFormat,
99 const PIXELFORMATDESCRIPTOR *ppfd)
101 return wine_wgl.p_SetPixelFormat(hdc, iPixelFormat, ppfd);
104 /***********************************************************************
105 * wglCopyContext (OPENGL32.@)
107 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
109 return wine_wgl.p_wglCopyContext(hglrcSrc, hglrcDst, mask);
112 /***********************************************************************
113 * wglDeleteContext (OPENGL32.@)
115 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
117 return wine_wgl.p_wglDeleteContext(hglrc);
120 /***********************************************************************
121 * wglMakeCurrent (OPENGL32.@)
123 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
125 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
128 /***********************************************************************
129 * wglShareLists (OPENGL32.@)
131 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
133 return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
136 /***********************************************************************
137 * wglUseFontBitmapsA (OPENGL32.@)
139 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
141 return wine_wgl.p_wglUseFontBitmapsA(hdc, first, count, listBase);
144 /***********************************************************************
145 * wglUseFontBitmapsW (OPENGL32.@)
147 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
149 return wine_wgl.p_wglUseFontBitmapsW(hdc, first, count, listBase);
152 /***********************************************************************
153 * wglGetCurrentDC (OPENGL32.@)
155 HDC WINAPI wglGetCurrentDC(void)
157 return wine_wgl.p_wglGetCurrentDC();
160 /***********************************************************************
161 * wglCreateContext (OPENGL32.@)
163 HGLRC WINAPI wglCreateContext(HDC hdc)
165 return wine_wgl.p_wglCreateContext(hdc);
168 /***********************************************************************
169 * wglGetCurrentContext (OPENGL32.@)
171 HGLRC WINAPI wglGetCurrentContext(void)
173 return wine_wgl.p_wglGetCurrentContext();
176 /***********************************************************************
177 * wglChoosePixelFormat (OPENGL32.@)
179 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
181 return wine_wgl.p_ChoosePixelFormat(hdc, ppfd);
184 /***********************************************************************
185 * wglDescribePixelFormat (OPENGL32.@)
187 INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
188 LPPIXELFORMATDESCRIPTOR ppfd)
190 return wine_wgl.p_DescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
192 /***********************************************************************
193 * wglGetPixelFormat (OPENGL32.@)
195 INT WINAPI wglGetPixelFormat(HDC hdc)
197 return wine_wgl.p_GetPixelFormat(hdc);
200 /***********************************************************************
201 * wglCreateLayerContext (OPENGL32.@)
203 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
204 int iLayerPlane) {
205 TRACE("(%p,%d)\n", hdc, iLayerPlane);
207 if (iLayerPlane == 0) {
208 return wglCreateContext(hdc);
210 FIXME(" no handler for layer %d\n", iLayerPlane);
212 return NULL;
215 /***********************************************************************
216 * wglDescribeLayerPlane (OPENGL32.@)
218 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
219 int iPixelFormat,
220 int iLayerPlane,
221 UINT nBytes,
222 LPLAYERPLANEDESCRIPTOR plpd) {
223 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
225 return FALSE;
228 /***********************************************************************
229 * wglGetLayerPaletteEntries (OPENGL32.@)
231 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
232 int iLayerPlane,
233 int iStart,
234 int cEntries,
235 const COLORREF *pcr) {
236 FIXME("(): stub !\n");
238 return 0;
241 static int compar(const void *elt_a, const void *elt_b) {
242 return strcmp(((const OpenGL_extension *) elt_a)->name,
243 ((const OpenGL_extension *) elt_b)->name);
246 /* Check if a GL extension is supported */
247 static BOOL is_extension_supported(const char* extension)
249 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
251 TRACE("Checking for extension '%s'\n", extension);
253 if(!gl_ext_string) {
254 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
255 return FALSE;
258 /* We use the GetProcAddress function from the display driver to retrieve function pointers
259 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
260 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
261 * require the function to return NULL when a extension isn't found. For this reason we check
262 * if the OpenGL extension required for the function we are looking up is supported. */
264 /* Check if the extension is part of the GL extension string to see if it is supported. */
265 if(strstr(gl_ext_string, extension) != NULL)
266 return TRUE;
268 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
269 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
270 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
271 * Check if we are searching for a core GL function */
272 if(strncmp(extension, "GL_VERSION_", 11) == 0)
274 const GLubyte *gl_version = glGetString(GL_VERSION);
275 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
277 if(!gl_version) {
278 ERR("Error no OpenGL version found,\n");
279 return FALSE;
282 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
283 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
284 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
285 return TRUE;
287 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]);
290 return FALSE;
293 /***********************************************************************
294 * wglGetProcAddress (OPENGL32.@)
296 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
297 void *local_func;
298 OpenGL_extension ext;
299 const OpenGL_extension *ext_ret;
301 TRACE("(%s)\n", lpszProc);
303 if(lpszProc == NULL)
304 return NULL;
306 /* First, look if it's not already defined in the 'standard' OpenGL functions */
307 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
308 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
309 return local_func;
312 /* After that, search in the thunks to find the real name of the extension */
313 ext.name = lpszProc;
314 ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
315 sizeof(OpenGL_extension), compar);
317 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
318 if (ext_ret == NULL) {
319 /* If the function name starts with a w it is a WGL extension */
320 if(lpszProc[0] == 'w')
321 return wine_wgl.p_wglGetProcAddress(lpszProc);
323 /* We are dealing with an unknown GL extension. */
324 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
325 return NULL;
326 } else { /* We are looking for an OpenGL extension */
328 /* Check if the GL extension required by the function is available */
329 if(!is_extension_supported(ext_ret->extension)) {
330 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
333 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
335 /* After that, look at the extensions defined in the Linux OpenGL library */
336 if (local_func == NULL) {
337 char buf[256];
338 void *ret = NULL;
340 /* Remove the 3 last letters (EXT, ARB, ...).
342 I know that some extensions have more than 3 letters (MESA, NV,
343 INTEL, ...), but this is only a stop-gap measure to fix buggy
344 OpenGL drivers (moreover, it is only useful for old 1.0 apps
345 that query the glBindTextureEXT extension).
347 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
348 buf[strlen(ext_ret->name) - 3] = '\0';
349 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
351 ret = GetProcAddress(opengl32_handle, buf);
352 if (ret != NULL) {
353 TRACE(" found function in main OpenGL library (%p) !\n", ret);
354 } else {
355 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
358 return ret;
359 } else {
360 TRACE(" returning function (%p)\n", ext_ret->func);
361 extension_funcs[ext_ret - extension_registry] = local_func;
363 return ext_ret->func;
368 /***********************************************************************
369 * wglRealizeLayerPalette (OPENGL32.@)
371 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
372 int iLayerPlane,
373 BOOL bRealize) {
374 FIXME("()\n");
376 return FALSE;
379 /***********************************************************************
380 * wglSetLayerPaletteEntries (OPENGL32.@)
382 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
383 int iLayerPlane,
384 int iStart,
385 int cEntries,
386 const COLORREF *pcr) {
387 FIXME("(): stub !\n");
389 return 0;
392 /***********************************************************************
393 * wglSwapLayerBuffers (OPENGL32.@)
395 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
396 UINT fuPlanes) {
397 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
399 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
400 if (!SwapBuffers(hdc)) return FALSE;
401 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
404 if (fuPlanes) {
405 WARN("Following layers unhandled : %08x\n", fuPlanes);
408 return TRUE;
411 #ifdef SONAME_LIBGLU
413 static void *load_libglu(void)
415 static int already_loaded;
416 void *handle;
418 if (already_loaded) return libglu_handle;
419 already_loaded = 1;
421 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
422 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
423 if (!handle)
425 WARN("Failed to load %s\n", SONAME_LIBGLU);
426 return NULL;
429 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
430 LOAD_FUNCPTR(gluNewTess)
431 LOAD_FUNCPTR(gluDeleteTess)
432 LOAD_FUNCPTR(gluTessBeginContour)
433 LOAD_FUNCPTR(gluTessBeginPolygon)
434 LOAD_FUNCPTR(gluTessCallback)
435 LOAD_FUNCPTR(gluTessEndContour)
436 LOAD_FUNCPTR(gluTessEndPolygon)
437 LOAD_FUNCPTR(gluTessVertex)
438 #undef LOAD_FUNCPTR
439 libglu_handle = handle;
440 return handle;
442 sym_not_found:
443 WARN("Unable to load function ptrs from libGLU\n");
444 /* Close the library as we won't use it */
445 wine_dlclose(handle, NULL, 0);
446 return NULL;
449 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
451 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
452 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
453 vertex[2] = 0.0;
456 static void tess_callback_vertex(GLvoid *vertex)
458 GLdouble *dbl = vertex;
459 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
460 glVertex3dv(vertex);
463 static void tess_callback_begin(GLenum which)
465 TRACE("%d\n", which);
466 glBegin(which);
469 static void tess_callback_end(void)
471 TRACE("\n");
472 glEnd();
475 /***********************************************************************
476 * wglUseFontOutlines_common
478 static BOOL wglUseFontOutlines_common(HDC hdc,
479 DWORD first,
480 DWORD count,
481 DWORD listBase,
482 FLOAT deviation,
483 FLOAT extrusion,
484 int format,
485 LPGLYPHMETRICSFLOAT lpgmf,
486 BOOL unicode)
488 UINT glyph;
489 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
490 GLUtesselator *tess;
491 LOGFONTW lf;
492 HFONT old_font, unscaled_font;
493 UINT em_size = 1024;
494 RECT rc;
496 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
497 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
499 if (!load_libglu())
501 ERR("libGLU is required for this function but isn't loaded\n");
502 return FALSE;
505 ENTER_GL();
506 tess = pgluNewTess();
507 if(tess)
509 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
510 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
511 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
513 LEAVE_GL();
515 if(!tess) return FALSE;
517 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
518 rc.left = rc.right = rc.bottom = 0;
519 rc.top = em_size;
520 DPtoLP(hdc, (POINT*)&rc, 2);
521 lf.lfHeight = -abs(rc.top - rc.bottom);
522 lf.lfOrientation = lf.lfEscapement = 0;
523 unscaled_font = CreateFontIndirectW(&lf);
524 old_font = SelectObject(hdc, unscaled_font);
526 for (glyph = first; glyph < first + count; glyph++)
528 DWORD needed;
529 GLYPHMETRICS gm;
530 BYTE *buf;
531 TTPOLYGONHEADER *pph;
532 TTPOLYCURVE *ppc;
533 GLdouble *vertices;
535 if(unicode)
536 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
537 else
538 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
540 if(needed == GDI_ERROR)
541 goto error;
543 buf = HeapAlloc(GetProcessHeap(), 0, needed);
544 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
546 if(unicode)
547 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
548 else
549 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
551 TRACE("glyph %d\n", glyph);
553 if(lpgmf)
555 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
556 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
557 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
558 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
559 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
560 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
562 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
563 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
564 lpgmf++;
567 ENTER_GL();
568 glNewList(listBase++, GL_COMPILE);
569 pgluTessBeginPolygon(tess, NULL);
571 pph = (TTPOLYGONHEADER*)buf;
572 while((BYTE*)pph < buf + needed)
574 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
576 pgluTessBeginContour(tess);
578 fixed_to_double(pph->pfxStart, em_size, vertices);
579 pgluTessVertex(tess, vertices, vertices);
580 vertices += 3;
582 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
583 while((char*)ppc < (char*)pph + pph->cb)
585 int i;
587 switch(ppc->wType) {
588 case TT_PRIM_LINE:
589 for(i = 0; i < ppc->cpfx; i++)
591 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
592 fixed_to_double(ppc->apfx[i], em_size, vertices);
593 pgluTessVertex(tess, vertices, vertices);
594 vertices += 3;
596 break;
598 case TT_PRIM_QSPLINE:
599 for(i = 0; i < ppc->cpfx/2; i++)
601 /* FIXME just connecting the control points for now */
602 TRACE("\t\tcurve %d,%d %d,%d\n",
603 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
604 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
605 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
606 pgluTessVertex(tess, vertices, vertices);
607 vertices += 3;
608 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
609 pgluTessVertex(tess, vertices, vertices);
610 vertices += 3;
612 break;
613 default:
614 ERR("\t\tcurve type = %d\n", ppc->wType);
615 pgluTessEndContour(tess);
616 goto error_in_list;
619 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
620 (ppc->cpfx - 1) * sizeof(POINTFX));
622 pgluTessEndContour(tess);
623 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
626 error_in_list:
627 pgluTessEndPolygon(tess);
628 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
629 glEndList();
630 LEAVE_GL();
631 HeapFree(GetProcessHeap(), 0, buf);
632 HeapFree(GetProcessHeap(), 0, vertices);
635 error:
636 DeleteObject(SelectObject(hdc, old_font));
637 pgluDeleteTess(tess);
638 return TRUE;
642 #else /* SONAME_LIBGLU */
644 static BOOL wglUseFontOutlines_common(HDC hdc,
645 DWORD first,
646 DWORD count,
647 DWORD listBase,
648 FLOAT deviation,
649 FLOAT extrusion,
650 int format,
651 LPGLYPHMETRICSFLOAT lpgmf,
652 BOOL unicode)
654 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
655 return FALSE;
658 #endif /* SONAME_LIBGLU */
660 /***********************************************************************
661 * wglUseFontOutlinesA (OPENGL32.@)
663 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
664 DWORD first,
665 DWORD count,
666 DWORD listBase,
667 FLOAT deviation,
668 FLOAT extrusion,
669 int format,
670 LPGLYPHMETRICSFLOAT lpgmf)
672 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
675 /***********************************************************************
676 * wglUseFontOutlinesW (OPENGL32.@)
678 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
679 DWORD first,
680 DWORD count,
681 DWORD listBase,
682 FLOAT deviation,
683 FLOAT extrusion,
684 int format,
685 LPGLYPHMETRICSFLOAT lpgmf)
687 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
690 /***********************************************************************
691 * glFinish (OPENGL32.@)
693 void WINAPI wine_glFinish( void )
695 TRACE("()\n");
696 wine_wgl.p_wglFinish();
699 /***********************************************************************
700 * glFlush (OPENGL32.@)
702 void WINAPI wine_glFlush( void )
704 TRACE("()\n");
705 wine_wgl.p_wglFlush();
708 /***********************************************************************
709 * glGetString (OPENGL32.@)
711 const GLubyte * WINAPI wine_glGetString( GLenum name )
713 const GLubyte *ret;
714 const char* GL_Extensions = NULL;
716 /* this is for buggy nvidia driver, crashing if called from a different
717 thread with no context */
718 if(wglGetCurrentContext() == NULL)
719 return NULL;
721 if (GL_EXTENSIONS != name) {
722 ENTER_GL();
723 ret = glGetString(name);
724 LEAVE_GL();
725 return ret;
728 if (NULL == internal_gl_extensions) {
729 ENTER_GL();
730 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
732 if (GL_Extensions)
734 size_t len = strlen(GL_Extensions);
735 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
737 TRACE("GL_EXTENSIONS reported:\n");
738 while (*GL_Extensions != 0x00) {
739 const char* Start = GL_Extensions;
740 char ThisExtn[256];
742 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
743 GL_Extensions++;
745 memcpy(ThisExtn, Start, (GL_Extensions - Start));
746 ThisExtn[GL_Extensions - Start] = 0;
747 TRACE("- %s:", ThisExtn);
749 /* test if supported API is disabled by config */
750 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
751 strcat(internal_gl_extensions, " ");
752 strcat(internal_gl_extensions, ThisExtn);
753 TRACE(" active\n");
754 } else {
755 TRACE(" deactived (by config)\n");
758 if (*GL_Extensions == ' ') GL_Extensions++;
761 LEAVE_GL();
763 return (const GLubyte *) internal_gl_extensions;
766 /***********************************************************************
767 * glGetIntegerv (OPENGL32.@)
769 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
771 wine_wgl.p_wglGetIntegerv(pname, params);
774 /***********************************************************************
775 * wglSwapBuffers (OPENGL32.@)
777 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
779 return SwapBuffers(hdc);
782 /* This is for brain-dead applications that use OpenGL functions before even
783 creating a rendering context.... */
784 static BOOL process_attach(void)
786 HMODULE mod_x11, mod_gdi32;
787 DWORD size;
788 HKEY hkey = 0;
790 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
791 mod_x11 = GetModuleHandleA( "winex11.drv" );
792 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
794 if (!mod_x11 || !mod_gdi32)
796 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
797 return FALSE;
800 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
801 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
803 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
804 wine_wgl.p_SetPixelFormat = (void *)GetProcAddress(mod_gdi32, "SetPixelFormat");
805 wine_wgl.p_wglCopyContext = (void *)GetProcAddress(mod_gdi32, "wglCopyContext");
806 wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod_gdi32, "wglDeleteContext");
807 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod_gdi32, "wglMakeCurrent");
808 wine_wgl.p_wglShareLists = (void *)GetProcAddress(mod_gdi32, "wglShareLists");
809 wine_wgl.p_wglUseFontBitmapsA = (void *)GetProcAddress(mod_gdi32, "wglUseFontBitmapsA");
810 wine_wgl.p_wglUseFontBitmapsW = (void *)GetProcAddress(mod_gdi32, "wglUseFontBitmapsW");
811 wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentDC");
812 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod_gdi32, "wglCreateContext");
813 wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentContext");
814 wine_wgl.p_ChoosePixelFormat = (void *)GetProcAddress(mod_gdi32, "ChoosePixelFormat");
815 wine_wgl.p_DescribePixelFormat = (void *)GetProcAddress(mod_gdi32, "DescribePixelFormat");
816 wine_wgl.p_GetPixelFormat = (void *)GetProcAddress(mod_gdi32, "GetPixelFormat");
818 /* Interal WGL function */
819 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
820 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
821 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
823 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
824 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
825 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
826 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
827 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
829 RegCloseKey(hkey);
832 return TRUE;
836 /**********************************************************************/
838 static void process_detach(void)
840 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
841 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
842 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
845 /***********************************************************************
846 * OpenGL initialisation routine
848 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
850 switch(reason)
852 case DLL_PROCESS_ATTACH:
853 opengl32_handle = hinst;
854 DisableThreadLibraryCalls(hinst);
855 return process_attach();
856 case DLL_PROCESS_DETACH:
857 process_detach();
858 break;
860 return TRUE;