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
22 #include "wine/port.h"
36 #include "opengl_ext.h"
42 #include "wine/library.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
46 WINE_DECLARE_DEBUG_CHANNEL(opengl);
50 PROC (WINAPI *p_wglGetProcAddress)(LPCSTR lpszProc);
51 BOOL (WINAPI *p_SetPixelFormat)(HDC hdc, INT iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd);
52 BOOL (WINAPI *p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
53 HGLRC (WINAPI *p_wglCreateContext)(HDC hdc);
54 INT (WINAPI *p_ChoosePixelFormat)(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd);
55 INT (WINAPI *p_DescribePixelFormat)(HDC hdc, INT iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd);
56 INT (WINAPI *p_GetPixelFormat)(HDC hdc);
58 /* internal WGL functions */
59 BOOL (WINAPI *p_wglCopyContext)(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask);
60 BOOL (WINAPI *p_wglDeleteContext)(HGLRC hglrc);
61 void (WINAPI *p_wglFinish)(void);
62 void (WINAPI *p_wglFlush)(void);
63 HGLRC (WINAPI *p_wglGetCurrentContext)(void);
64 HDC (WINAPI *p_wglGetCurrentDC)(void);
65 void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params);
66 BOOL (WINAPI *p_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
70 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
71 MAKE_FUNCPTR(gluNewTess)
72 MAKE_FUNCPTR(gluDeleteTess)
73 MAKE_FUNCPTR(gluTessBeginContour)
74 MAKE_FUNCPTR(gluTessBeginPolygon)
75 MAKE_FUNCPTR(gluTessCallback)
76 MAKE_FUNCPTR(gluTessEndContour)
77 MAKE_FUNCPTR(gluTessEndPolygon)
78 MAKE_FUNCPTR(gluTessVertex)
80 #endif /* SONAME_LIBGLU */
82 void (*wine_tsx11_lock_ptr)(void) = NULL;
83 void (*wine_tsx11_unlock_ptr)(void) = NULL;
85 static HMODULE opengl32_handle;
86 static void* libglu_handle = NULL;
88 static char* internal_gl_disabled_extensions = NULL;
89 static char* internal_gl_extensions = NULL;
91 const GLubyte * WINAPI wine_glGetString( GLenum name );
93 /***********************************************************************
94 * wglSetPixelFormat(OPENGL32.@)
96 BOOL WINAPI wglSetPixelFormat( HDC hdc, INT iPixelFormat,
97 const PIXELFORMATDESCRIPTOR *ppfd)
99 return wine_wgl.p_SetPixelFormat(hdc, iPixelFormat, ppfd);
102 /***********************************************************************
103 * wglCopyContext (OPENGL32.@)
105 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
107 if (!hglrcSrc || !hglrcDst)
109 SetLastError(ERROR_INVALID_HANDLE);
112 return wine_wgl.p_wglCopyContext(hglrcSrc, hglrcDst, mask);
115 /***********************************************************************
116 * wglDeleteContext (OPENGL32.@)
118 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
122 SetLastError(ERROR_INVALID_HANDLE);
125 return wine_wgl.p_wglDeleteContext(hglrc);
128 /***********************************************************************
129 * wglMakeCurrent (OPENGL32.@)
131 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
133 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
136 /***********************************************************************
137 * wglShareLists (OPENGL32.@)
139 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
141 if (!hglrc1 || !hglrc2)
143 SetLastError(ERROR_INVALID_HANDLE);
146 return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
149 /***********************************************************************
150 * wglGetCurrentDC (OPENGL32.@)
152 HDC WINAPI wglGetCurrentDC(void)
154 return wine_wgl.p_wglGetCurrentDC();
157 /***********************************************************************
158 * wglCreateContext (OPENGL32.@)
160 HGLRC WINAPI wglCreateContext(HDC hdc)
162 return wine_wgl.p_wglCreateContext(hdc);
165 /***********************************************************************
166 * wglGetCurrentContext (OPENGL32.@)
168 HGLRC WINAPI wglGetCurrentContext(void)
170 return wine_wgl.p_wglGetCurrentContext();
173 /***********************************************************************
174 * wglChoosePixelFormat (OPENGL32.@)
176 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
178 return wine_wgl.p_ChoosePixelFormat(hdc, ppfd);
181 /***********************************************************************
182 * wglDescribePixelFormat (OPENGL32.@)
184 INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
185 LPPIXELFORMATDESCRIPTOR ppfd)
187 return wine_wgl.p_DescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
189 /***********************************************************************
190 * wglGetPixelFormat (OPENGL32.@)
192 INT WINAPI wglGetPixelFormat(HDC hdc)
194 return wine_wgl.p_GetPixelFormat(hdc);
197 /***********************************************************************
198 * wglCreateLayerContext (OPENGL32.@)
200 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
202 TRACE("(%p,%d)\n", hdc, iLayerPlane);
204 if (iLayerPlane == 0) {
205 return wglCreateContext(hdc);
207 FIXME(" no handler for layer %d\n", iLayerPlane);
212 /***********************************************************************
213 * wglDescribeLayerPlane (OPENGL32.@)
215 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
219 LPLAYERPLANEDESCRIPTOR plpd) {
220 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
225 /***********************************************************************
226 * wglGetLayerPaletteEntries (OPENGL32.@)
228 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
232 const COLORREF *pcr) {
233 FIXME("(): stub !\n");
238 static int compar(const void *elt_a, const void *elt_b) {
239 return strcmp(((const OpenGL_extension *) elt_a)->name,
240 ((const OpenGL_extension *) elt_b)->name);
243 /* Check if a GL extension is supported */
244 static BOOL is_extension_supported(const char* extension)
246 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
248 TRACE("Checking for extension '%s'\n", extension);
251 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
255 /* We use the GetProcAddress function from the display driver to retrieve function pointers
256 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
257 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
258 * require the function to return NULL when a extension isn't found. For this reason we check
259 * if the OpenGL extension required for the function we are looking up is supported. */
261 /* Check if the extension is part of the GL extension string to see if it is supported. */
262 if(strstr(gl_ext_string, extension) != NULL)
265 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
266 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
267 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
268 * Check if we are searching for a core GL function */
269 if(strncmp(extension, "GL_VERSION_", 11) == 0)
271 const GLubyte *gl_version = glGetString(GL_VERSION);
272 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
275 ERR("Error no OpenGL version found,\n");
279 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
280 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
281 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
284 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 /***********************************************************************
291 * wglGetProcAddress (OPENGL32.@)
293 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
295 OpenGL_extension ext;
296 const OpenGL_extension *ext_ret;
298 TRACE("(%s)\n", lpszProc);
300 if (lpszProc == NULL)
303 /* Without an active context opengl32 doesn't know to what
304 * driver it has to dispatch wglGetProcAddress.
306 if (wglGetCurrentContext() == NULL)
308 WARN("No active WGL context found\n");
312 /* First, look if it's not already defined in the 'standard' OpenGL functions */
313 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
314 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
318 /* After that, search in the thunks to find the real name of the extension */
320 ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
321 sizeof(OpenGL_extension), compar);
323 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
324 if (ext_ret == NULL) {
325 /* If the function name starts with a w it is a WGL extension */
326 if(lpszProc[0] == 'w')
327 return wine_wgl.p_wglGetProcAddress(lpszProc);
329 /* We are dealing with an unknown GL extension. */
330 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
332 } else { /* We are looking for an OpenGL extension */
334 /* Check if the GL extension required by the function is available */
335 if(!is_extension_supported(ext_ret->extension)) {
336 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
339 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
341 /* After that, look at the extensions defined in the Linux OpenGL library */
342 if (local_func == NULL) {
346 /* Remove the 3 last letters (EXT, ARB, ...).
348 I know that some extensions have more than 3 letters (MESA, NV,
349 INTEL, ...), but this is only a stop-gap measure to fix buggy
350 OpenGL drivers (moreover, it is only useful for old 1.0 apps
351 that query the glBindTextureEXT extension).
353 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
354 buf[strlen(ext_ret->name) - 3] = '\0';
355 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
357 ret = GetProcAddress(opengl32_handle, buf);
359 TRACE(" found function in main OpenGL library (%p) !\n", ret);
361 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
366 TRACE(" returning function (%p)\n", ext_ret->func);
367 extension_funcs[ext_ret - extension_registry] = local_func;
369 return ext_ret->func;
374 /***********************************************************************
375 * wglRealizeLayerPalette (OPENGL32.@)
377 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
385 /***********************************************************************
386 * wglSetLayerPaletteEntries (OPENGL32.@)
388 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
392 const COLORREF *pcr) {
393 FIXME("(): stub !\n");
398 /***********************************************************************
399 * wglSwapLayerBuffers (OPENGL32.@)
401 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
403 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
405 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
406 if (!SwapBuffers(hdc)) return FALSE;
407 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
411 WARN("Following layers unhandled : %08x\n", fuPlanes);
417 /***********************************************************************
418 * wglUseFontBitmaps_common
420 static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD listBase, BOOL unicode )
423 unsigned int glyph, size = 0;
424 void *bitmap = NULL, *gl_bitmap = NULL;
429 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
430 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
433 for (glyph = first; glyph < first + count; glyph++) {
434 static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
435 unsigned int needed_size, height, width, width_int;
438 needed_size = GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
440 needed_size = GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
442 TRACE("Glyph : %3d / List : %d size %d\n", glyph, listBase, needed_size);
443 if (needed_size == GDI_ERROR) {
448 if (needed_size > size) {
450 HeapFree(GetProcessHeap(), 0, bitmap);
451 HeapFree(GetProcessHeap(), 0, gl_bitmap);
452 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
453 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
456 ret = (GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
458 ret = (GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
462 unsigned int bitmask;
463 unsigned char *bitmap_ = bitmap;
465 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
466 TRACE(" - origin : (%d , %d)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
467 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
468 if (needed_size != 0) {
469 TRACE(" - bitmap :\n");
470 for (height = 0; height < gm.gmBlackBoxY; height++) {
472 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
477 if (*bitmap_ & bitmask)
482 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
488 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
489 * glyph for it to be drawn properly.
491 if (needed_size != 0) {
492 width_int = (gm.gmBlackBoxX + 31) / 32;
493 for (height = 0; height < gm.gmBlackBoxY; height++) {
494 for (width = 0; width < width_int; width++) {
495 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
496 ((int *) bitmap)[height * width_int + width];
502 glNewList(listBase++, GL_COMPILE);
503 if (needed_size != 0) {
504 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
505 0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y,
506 gm.gmCellIncX, gm.gmCellIncY,
509 /* This is the case of 'empty' glyphs like the space character */
510 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
517 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
519 HeapFree(GetProcessHeap(), 0, bitmap);
520 HeapFree(GetProcessHeap(), 0, gl_bitmap);
524 /***********************************************************************
525 * wglUseFontBitmapsA (OPENGL32.@)
527 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
529 return wglUseFontBitmaps_common( hdc, first, count, listBase, FALSE );
532 /***********************************************************************
533 * wglUseFontBitmapsW (OPENGL32.@)
535 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
537 return wglUseFontBitmaps_common( hdc, first, count, listBase, TRUE );
542 static void *load_libglu(void)
544 static int already_loaded;
547 if (already_loaded) return libglu_handle;
550 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
551 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
554 WARN("Failed to load %s\n", SONAME_LIBGLU);
558 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
559 LOAD_FUNCPTR(gluNewTess)
560 LOAD_FUNCPTR(gluDeleteTess)
561 LOAD_FUNCPTR(gluTessBeginContour)
562 LOAD_FUNCPTR(gluTessBeginPolygon)
563 LOAD_FUNCPTR(gluTessCallback)
564 LOAD_FUNCPTR(gluTessEndContour)
565 LOAD_FUNCPTR(gluTessEndPolygon)
566 LOAD_FUNCPTR(gluTessVertex)
568 libglu_handle = handle;
572 WARN("Unable to load function ptrs from libGLU\n");
573 /* Close the library as we won't use it */
574 wine_dlclose(handle, NULL, 0);
578 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
580 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
581 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
585 static void tess_callback_vertex(GLvoid *vertex)
587 GLdouble *dbl = vertex;
588 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
592 static void tess_callback_begin(GLenum which)
594 TRACE("%d\n", which);
598 static void tess_callback_end(void)
604 /***********************************************************************
605 * wglUseFontOutlines_common
607 static BOOL wglUseFontOutlines_common(HDC hdc,
614 LPGLYPHMETRICSFLOAT lpgmf,
618 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
621 HFONT old_font, unscaled_font;
625 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
626 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
630 ERR("libGLU is required for this function but isn't loaded\n");
635 tess = pgluNewTess();
638 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
639 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
640 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
644 if(!tess) return FALSE;
646 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
647 rc.left = rc.right = rc.bottom = 0;
649 DPtoLP(hdc, (POINT*)&rc, 2);
650 lf.lfHeight = -abs(rc.top - rc.bottom);
651 lf.lfOrientation = lf.lfEscapement = 0;
652 unscaled_font = CreateFontIndirectW(&lf);
653 old_font = SelectObject(hdc, unscaled_font);
655 for (glyph = first; glyph < first + count; glyph++)
660 TTPOLYGONHEADER *pph;
665 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
667 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
669 if(needed == GDI_ERROR)
672 buf = HeapAlloc(GetProcessHeap(), 0, needed);
673 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
676 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
678 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
680 TRACE("glyph %d\n", glyph);
684 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
685 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
686 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
687 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
688 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
689 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
691 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
692 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
697 glNewList(listBase++, GL_COMPILE);
698 pgluTessBeginPolygon(tess, NULL);
700 pph = (TTPOLYGONHEADER*)buf;
701 while((BYTE*)pph < buf + needed)
703 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
705 pgluTessBeginContour(tess);
707 fixed_to_double(pph->pfxStart, em_size, vertices);
708 pgluTessVertex(tess, vertices, vertices);
711 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
712 while((char*)ppc < (char*)pph + pph->cb)
718 for(i = 0; i < ppc->cpfx; i++)
720 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
721 fixed_to_double(ppc->apfx[i], em_size, vertices);
722 pgluTessVertex(tess, vertices, vertices);
727 case TT_PRIM_QSPLINE:
728 for(i = 0; i < ppc->cpfx/2; i++)
730 /* FIXME just connecting the control points for now */
731 TRACE("\t\tcurve %d,%d %d,%d\n",
732 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
733 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
734 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
735 pgluTessVertex(tess, vertices, vertices);
737 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
738 pgluTessVertex(tess, vertices, vertices);
743 ERR("\t\tcurve type = %d\n", ppc->wType);
744 pgluTessEndContour(tess);
748 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
749 (ppc->cpfx - 1) * sizeof(POINTFX));
751 pgluTessEndContour(tess);
752 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
756 pgluTessEndPolygon(tess);
757 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
760 HeapFree(GetProcessHeap(), 0, buf);
761 HeapFree(GetProcessHeap(), 0, vertices);
765 DeleteObject(SelectObject(hdc, old_font));
766 pgluDeleteTess(tess);
771 #else /* SONAME_LIBGLU */
773 static BOOL wglUseFontOutlines_common(HDC hdc,
780 LPGLYPHMETRICSFLOAT lpgmf,
783 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
787 #endif /* SONAME_LIBGLU */
789 /***********************************************************************
790 * wglUseFontOutlinesA (OPENGL32.@)
792 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
799 LPGLYPHMETRICSFLOAT lpgmf)
801 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
804 /***********************************************************************
805 * wglUseFontOutlinesW (OPENGL32.@)
807 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
814 LPGLYPHMETRICSFLOAT lpgmf)
816 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
819 /***********************************************************************
820 * glFinish (OPENGL32.@)
822 void WINAPI wine_glFinish( void )
825 wine_wgl.p_wglFinish();
828 /***********************************************************************
829 * glFlush (OPENGL32.@)
831 void WINAPI wine_glFlush( void )
834 wine_wgl.p_wglFlush();
837 /***********************************************************************
838 * glGetString (OPENGL32.@)
840 const GLubyte * WINAPI wine_glGetString( GLenum name )
843 const char* GL_Extensions = NULL;
845 /* this is for buggy nvidia driver, crashing if called from a different
846 thread with no context */
847 if(wglGetCurrentContext() == NULL)
850 if (GL_EXTENSIONS != name) {
852 ret = glGetString(name);
857 if (NULL == internal_gl_extensions) {
859 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
863 size_t len = strlen(GL_Extensions);
864 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
866 TRACE("GL_EXTENSIONS reported:\n");
867 while (*GL_Extensions != 0x00) {
868 const char* Start = GL_Extensions;
871 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
874 memcpy(ThisExtn, Start, (GL_Extensions - Start));
875 ThisExtn[GL_Extensions - Start] = 0;
876 TRACE("- %s:", ThisExtn);
878 /* test if supported API is disabled by config */
879 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
880 strcat(internal_gl_extensions, " ");
881 strcat(internal_gl_extensions, ThisExtn);
884 TRACE(" deactived (by config)\n");
887 if (*GL_Extensions == ' ') GL_Extensions++;
892 return (const GLubyte *) internal_gl_extensions;
895 /***********************************************************************
896 * glGetIntegerv (OPENGL32.@)
898 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
900 wine_wgl.p_wglGetIntegerv(pname, params);
903 /***********************************************************************
904 * wglSwapBuffers (OPENGL32.@)
906 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
908 return SwapBuffers(hdc);
911 /* This is for brain-dead applications that use OpenGL functions before even
912 creating a rendering context.... */
913 static BOOL process_attach(void)
915 HMODULE mod_x11, mod_gdi32;
919 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
920 mod_x11 = GetModuleHandleA( "winex11.drv" );
921 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
923 if (!mod_x11 || !mod_gdi32)
925 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
929 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
930 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
932 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
933 wine_wgl.p_SetPixelFormat = (void *)GetProcAddress(mod_gdi32, "SetPixelFormat");
934 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod_gdi32, "wglMakeCurrent");
935 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod_gdi32, "wglCreateContext");
936 wine_wgl.p_ChoosePixelFormat = (void *)GetProcAddress(mod_gdi32, "ChoosePixelFormat");
937 wine_wgl.p_DescribePixelFormat = (void *)GetProcAddress(mod_gdi32, "DescribePixelFormat");
938 wine_wgl.p_GetPixelFormat = (void *)GetProcAddress(mod_gdi32, "GetPixelFormat");
940 /* internal WGL functions */
941 wine_wgl.p_wglCopyContext = (void *)wine_wgl.p_wglGetProcAddress("wglCopyContext");
942 wine_wgl.p_wglDeleteContext = (void *)wine_wgl.p_wglGetProcAddress("wglDeleteContext");
943 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
944 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
945 wine_wgl.p_wglGetCurrentContext = (void *)wine_wgl.p_wglGetProcAddress("wglGetCurrentContext");
946 wine_wgl.p_wglGetCurrentDC = (void *)wine_wgl.p_wglGetProcAddress("wglGetCurrentDC");
947 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
948 wine_wgl.p_wglShareLists = (void *)wine_wgl.p_wglGetProcAddress("wglShareLists");
950 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
951 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
952 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
953 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
954 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
963 /**********************************************************************/
965 static void process_detach(void)
967 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
968 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
969 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
972 /***********************************************************************
973 * OpenGL initialisation routine
975 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
979 case DLL_PROCESS_ATTACH:
980 opengl32_handle = hinst;
981 DisableThreadLibraryCalls(hinst);
982 return process_attach();
983 case DLL_PROCESS_DETACH: