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_wglCopyContext)(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask);
53 BOOL (WINAPI *p_wglDeleteContext)(HGLRC hglrc);
54 BOOL (WINAPI *p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
55 HDC (WINAPI *p_wglGetCurrentDC)(void);
56 HGLRC (WINAPI *p_wglCreateContext)(HDC hdc);
57 HGLRC (WINAPI *p_wglGetCurrentContext)(void);
58 INT (WINAPI *p_ChoosePixelFormat)(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd);
59 INT (WINAPI *p_DescribePixelFormat)(HDC hdc, INT iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd);
60 INT (WINAPI *p_GetPixelFormat)(HDC hdc);
62 /* internal WGL functions */
63 void (WINAPI *p_wglGetIntegerv)(GLenum pname, GLint* params);
64 void (WINAPI *p_wglFinish)(void);
65 void (WINAPI *p_wglFlush)(void);
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 return wine_wgl.p_wglCopyContext(hglrcSrc, hglrcDst, mask);
110 /***********************************************************************
111 * wglDeleteContext (OPENGL32.@)
113 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
115 return wine_wgl.p_wglDeleteContext(hglrc);
118 /***********************************************************************
119 * wglMakeCurrent (OPENGL32.@)
121 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
123 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
126 /***********************************************************************
127 * wglShareLists (OPENGL32.@)
129 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
131 if (!hglrc1 || !hglrc2)
133 SetLastError(ERROR_INVALID_HANDLE);
136 return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
139 /***********************************************************************
140 * wglGetCurrentDC (OPENGL32.@)
142 HDC WINAPI wglGetCurrentDC(void)
144 return wine_wgl.p_wglGetCurrentDC();
147 /***********************************************************************
148 * wglCreateContext (OPENGL32.@)
150 HGLRC WINAPI wglCreateContext(HDC hdc)
152 return wine_wgl.p_wglCreateContext(hdc);
155 /***********************************************************************
156 * wglGetCurrentContext (OPENGL32.@)
158 HGLRC WINAPI wglGetCurrentContext(void)
160 return wine_wgl.p_wglGetCurrentContext();
163 /***********************************************************************
164 * wglChoosePixelFormat (OPENGL32.@)
166 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
168 return wine_wgl.p_ChoosePixelFormat(hdc, ppfd);
171 /***********************************************************************
172 * wglDescribePixelFormat (OPENGL32.@)
174 INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
175 LPPIXELFORMATDESCRIPTOR ppfd)
177 return wine_wgl.p_DescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
179 /***********************************************************************
180 * wglGetPixelFormat (OPENGL32.@)
182 INT WINAPI wglGetPixelFormat(HDC hdc)
184 return wine_wgl.p_GetPixelFormat(hdc);
187 /***********************************************************************
188 * wglCreateLayerContext (OPENGL32.@)
190 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
192 TRACE("(%p,%d)\n", hdc, iLayerPlane);
194 if (iLayerPlane == 0) {
195 return wglCreateContext(hdc);
197 FIXME(" no handler for layer %d\n", iLayerPlane);
202 /***********************************************************************
203 * wglDescribeLayerPlane (OPENGL32.@)
205 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
209 LPLAYERPLANEDESCRIPTOR plpd) {
210 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
215 /***********************************************************************
216 * wglGetLayerPaletteEntries (OPENGL32.@)
218 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
222 const COLORREF *pcr) {
223 FIXME("(): stub !\n");
228 static int compar(const void *elt_a, const void *elt_b) {
229 return strcmp(((const OpenGL_extension *) elt_a)->name,
230 ((const OpenGL_extension *) elt_b)->name);
233 /* Check if a GL extension is supported */
234 static BOOL is_extension_supported(const char* extension)
236 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
238 TRACE("Checking for extension '%s'\n", extension);
241 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
245 /* We use the GetProcAddress function from the display driver to retrieve function pointers
246 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
247 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
248 * require the function to return NULL when a extension isn't found. For this reason we check
249 * if the OpenGL extension required for the function we are looking up is supported. */
251 /* Check if the extension is part of the GL extension string to see if it is supported. */
252 if(strstr(gl_ext_string, extension) != NULL)
255 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
256 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
257 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
258 * Check if we are searching for a core GL function */
259 if(strncmp(extension, "GL_VERSION_", 11) == 0)
261 const GLubyte *gl_version = glGetString(GL_VERSION);
262 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
265 ERR("Error no OpenGL version found,\n");
269 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
270 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
271 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
274 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]);
280 /***********************************************************************
281 * wglGetProcAddress (OPENGL32.@)
283 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
285 OpenGL_extension ext;
286 const OpenGL_extension *ext_ret;
288 TRACE("(%s)\n", lpszProc);
290 if (lpszProc == NULL)
293 /* Without an active context opengl32 doesn't know to what
294 * driver it has to dispatch wglGetProcAddress.
296 if (wglGetCurrentContext() == NULL)
298 WARN("No active WGL context found\n");
302 /* First, look if it's not already defined in the 'standard' OpenGL functions */
303 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
304 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
308 /* After that, search in the thunks to find the real name of the extension */
310 ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
311 sizeof(OpenGL_extension), compar);
313 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
314 if (ext_ret == NULL) {
315 /* If the function name starts with a w it is a WGL extension */
316 if(lpszProc[0] == 'w')
317 return wine_wgl.p_wglGetProcAddress(lpszProc);
319 /* We are dealing with an unknown GL extension. */
320 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
322 } else { /* We are looking for an OpenGL extension */
324 /* Check if the GL extension required by the function is available */
325 if(!is_extension_supported(ext_ret->extension)) {
326 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
329 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
331 /* After that, look at the extensions defined in the Linux OpenGL library */
332 if (local_func == NULL) {
336 /* Remove the 3 last letters (EXT, ARB, ...).
338 I know that some extensions have more than 3 letters (MESA, NV,
339 INTEL, ...), but this is only a stop-gap measure to fix buggy
340 OpenGL drivers (moreover, it is only useful for old 1.0 apps
341 that query the glBindTextureEXT extension).
343 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
344 buf[strlen(ext_ret->name) - 3] = '\0';
345 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
347 ret = GetProcAddress(opengl32_handle, buf);
349 TRACE(" found function in main OpenGL library (%p) !\n", ret);
351 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
356 TRACE(" returning function (%p)\n", ext_ret->func);
357 extension_funcs[ext_ret - extension_registry] = local_func;
359 return ext_ret->func;
364 /***********************************************************************
365 * wglRealizeLayerPalette (OPENGL32.@)
367 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
375 /***********************************************************************
376 * wglSetLayerPaletteEntries (OPENGL32.@)
378 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
382 const COLORREF *pcr) {
383 FIXME("(): stub !\n");
388 /***********************************************************************
389 * wglSwapLayerBuffers (OPENGL32.@)
391 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
393 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
395 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
396 if (!SwapBuffers(hdc)) return FALSE;
397 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
401 WARN("Following layers unhandled : %08x\n", fuPlanes);
407 /***********************************************************************
408 * wglUseFontBitmaps_common
410 static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD listBase, BOOL unicode )
413 unsigned int glyph, size = 0;
414 void *bitmap = NULL, *gl_bitmap = NULL;
419 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
420 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
423 for (glyph = first; glyph < first + count; glyph++) {
424 static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
425 unsigned int needed_size, height, width, width_int;
428 needed_size = GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
430 needed_size = GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &identity);
432 TRACE("Glyph : %3d / List : %d size %d\n", glyph, listBase, needed_size);
433 if (needed_size == GDI_ERROR) {
438 if (needed_size > size) {
440 HeapFree(GetProcessHeap(), 0, bitmap);
441 HeapFree(GetProcessHeap(), 0, gl_bitmap);
442 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
443 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
446 ret = (GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
448 ret = (GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &identity) != GDI_ERROR);
452 unsigned int bitmask;
453 unsigned char *bitmap_ = bitmap;
455 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
456 TRACE(" - origin : (%d , %d)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
457 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
458 if (needed_size != 0) {
459 TRACE(" - bitmap :\n");
460 for (height = 0; height < gm.gmBlackBoxY; height++) {
462 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
467 if (*bitmap_ & bitmask)
472 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
478 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
479 * glyph for it to be drawn properly.
481 if (needed_size != 0) {
482 width_int = (gm.gmBlackBoxX + 31) / 32;
483 for (height = 0; height < gm.gmBlackBoxY; height++) {
484 for (width = 0; width < width_int; width++) {
485 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
486 ((int *) bitmap)[height * width_int + width];
492 glNewList(listBase++, GL_COMPILE);
493 if (needed_size != 0) {
494 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
495 0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y,
496 gm.gmCellIncX, gm.gmCellIncY,
499 /* This is the case of 'empty' glyphs like the space character */
500 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
507 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
509 HeapFree(GetProcessHeap(), 0, bitmap);
510 HeapFree(GetProcessHeap(), 0, gl_bitmap);
514 /***********************************************************************
515 * wglUseFontBitmapsA (OPENGL32.@)
517 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
519 return wglUseFontBitmaps_common( hdc, first, count, listBase, FALSE );
522 /***********************************************************************
523 * wglUseFontBitmapsW (OPENGL32.@)
525 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
527 return wglUseFontBitmaps_common( hdc, first, count, listBase, TRUE );
532 static void *load_libglu(void)
534 static int already_loaded;
537 if (already_loaded) return libglu_handle;
540 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
541 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
544 WARN("Failed to load %s\n", SONAME_LIBGLU);
548 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
549 LOAD_FUNCPTR(gluNewTess)
550 LOAD_FUNCPTR(gluDeleteTess)
551 LOAD_FUNCPTR(gluTessBeginContour)
552 LOAD_FUNCPTR(gluTessBeginPolygon)
553 LOAD_FUNCPTR(gluTessCallback)
554 LOAD_FUNCPTR(gluTessEndContour)
555 LOAD_FUNCPTR(gluTessEndPolygon)
556 LOAD_FUNCPTR(gluTessVertex)
558 libglu_handle = handle;
562 WARN("Unable to load function ptrs from libGLU\n");
563 /* Close the library as we won't use it */
564 wine_dlclose(handle, NULL, 0);
568 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
570 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
571 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
575 static void tess_callback_vertex(GLvoid *vertex)
577 GLdouble *dbl = vertex;
578 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
582 static void tess_callback_begin(GLenum which)
584 TRACE("%d\n", which);
588 static void tess_callback_end(void)
594 /***********************************************************************
595 * wglUseFontOutlines_common
597 static BOOL wglUseFontOutlines_common(HDC hdc,
604 LPGLYPHMETRICSFLOAT lpgmf,
608 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
611 HFONT old_font, unscaled_font;
615 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
616 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
620 ERR("libGLU is required for this function but isn't loaded\n");
625 tess = pgluNewTess();
628 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
629 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
630 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
634 if(!tess) return FALSE;
636 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
637 rc.left = rc.right = rc.bottom = 0;
639 DPtoLP(hdc, (POINT*)&rc, 2);
640 lf.lfHeight = -abs(rc.top - rc.bottom);
641 lf.lfOrientation = lf.lfEscapement = 0;
642 unscaled_font = CreateFontIndirectW(&lf);
643 old_font = SelectObject(hdc, unscaled_font);
645 for (glyph = first; glyph < first + count; glyph++)
650 TTPOLYGONHEADER *pph;
655 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
657 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
659 if(needed == GDI_ERROR)
662 buf = HeapAlloc(GetProcessHeap(), 0, needed);
663 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
666 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
668 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
670 TRACE("glyph %d\n", glyph);
674 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
675 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
676 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
677 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
678 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
679 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
681 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
682 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
687 glNewList(listBase++, GL_COMPILE);
688 pgluTessBeginPolygon(tess, NULL);
690 pph = (TTPOLYGONHEADER*)buf;
691 while((BYTE*)pph < buf + needed)
693 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
695 pgluTessBeginContour(tess);
697 fixed_to_double(pph->pfxStart, em_size, vertices);
698 pgluTessVertex(tess, vertices, vertices);
701 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
702 while((char*)ppc < (char*)pph + pph->cb)
708 for(i = 0; i < ppc->cpfx; i++)
710 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
711 fixed_to_double(ppc->apfx[i], em_size, vertices);
712 pgluTessVertex(tess, vertices, vertices);
717 case TT_PRIM_QSPLINE:
718 for(i = 0; i < ppc->cpfx/2; i++)
720 /* FIXME just connecting the control points for now */
721 TRACE("\t\tcurve %d,%d %d,%d\n",
722 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
723 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
724 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
725 pgluTessVertex(tess, vertices, vertices);
727 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
728 pgluTessVertex(tess, vertices, vertices);
733 ERR("\t\tcurve type = %d\n", ppc->wType);
734 pgluTessEndContour(tess);
738 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
739 (ppc->cpfx - 1) * sizeof(POINTFX));
741 pgluTessEndContour(tess);
742 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
746 pgluTessEndPolygon(tess);
747 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
750 HeapFree(GetProcessHeap(), 0, buf);
751 HeapFree(GetProcessHeap(), 0, vertices);
755 DeleteObject(SelectObject(hdc, old_font));
756 pgluDeleteTess(tess);
761 #else /* SONAME_LIBGLU */
763 static BOOL wglUseFontOutlines_common(HDC hdc,
770 LPGLYPHMETRICSFLOAT lpgmf,
773 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
777 #endif /* SONAME_LIBGLU */
779 /***********************************************************************
780 * wglUseFontOutlinesA (OPENGL32.@)
782 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
789 LPGLYPHMETRICSFLOAT lpgmf)
791 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
794 /***********************************************************************
795 * wglUseFontOutlinesW (OPENGL32.@)
797 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
804 LPGLYPHMETRICSFLOAT lpgmf)
806 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
809 /***********************************************************************
810 * glFinish (OPENGL32.@)
812 void WINAPI wine_glFinish( void )
815 wine_wgl.p_wglFinish();
818 /***********************************************************************
819 * glFlush (OPENGL32.@)
821 void WINAPI wine_glFlush( void )
824 wine_wgl.p_wglFlush();
827 /***********************************************************************
828 * glGetString (OPENGL32.@)
830 const GLubyte * WINAPI wine_glGetString( GLenum name )
833 const char* GL_Extensions = NULL;
835 /* this is for buggy nvidia driver, crashing if called from a different
836 thread with no context */
837 if(wglGetCurrentContext() == NULL)
840 if (GL_EXTENSIONS != name) {
842 ret = glGetString(name);
847 if (NULL == internal_gl_extensions) {
849 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
853 size_t len = strlen(GL_Extensions);
854 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
856 TRACE("GL_EXTENSIONS reported:\n");
857 while (*GL_Extensions != 0x00) {
858 const char* Start = GL_Extensions;
861 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
864 memcpy(ThisExtn, Start, (GL_Extensions - Start));
865 ThisExtn[GL_Extensions - Start] = 0;
866 TRACE("- %s:", ThisExtn);
868 /* test if supported API is disabled by config */
869 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
870 strcat(internal_gl_extensions, " ");
871 strcat(internal_gl_extensions, ThisExtn);
874 TRACE(" deactived (by config)\n");
877 if (*GL_Extensions == ' ') GL_Extensions++;
882 return (const GLubyte *) internal_gl_extensions;
885 /***********************************************************************
886 * glGetIntegerv (OPENGL32.@)
888 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
890 wine_wgl.p_wglGetIntegerv(pname, params);
893 /***********************************************************************
894 * wglSwapBuffers (OPENGL32.@)
896 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
898 return SwapBuffers(hdc);
901 /* This is for brain-dead applications that use OpenGL functions before even
902 creating a rendering context.... */
903 static BOOL process_attach(void)
905 HMODULE mod_x11, mod_gdi32;
909 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
910 mod_x11 = GetModuleHandleA( "winex11.drv" );
911 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
913 if (!mod_x11 || !mod_gdi32)
915 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
919 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
920 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
922 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
923 wine_wgl.p_SetPixelFormat = (void *)GetProcAddress(mod_gdi32, "SetPixelFormat");
924 wine_wgl.p_wglCopyContext = (void *)GetProcAddress(mod_gdi32, "wglCopyContext");
925 wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod_gdi32, "wglDeleteContext");
926 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod_gdi32, "wglMakeCurrent");
927 wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentDC");
928 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod_gdi32, "wglCreateContext");
929 wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentContext");
930 wine_wgl.p_ChoosePixelFormat = (void *)GetProcAddress(mod_gdi32, "ChoosePixelFormat");
931 wine_wgl.p_DescribePixelFormat = (void *)GetProcAddress(mod_gdi32, "DescribePixelFormat");
932 wine_wgl.p_GetPixelFormat = (void *)GetProcAddress(mod_gdi32, "GetPixelFormat");
934 /* internal WGL functions */
935 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
936 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
937 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
938 wine_wgl.p_wglShareLists = (void *)wine_wgl.p_wglGetProcAddress("wglShareLists");
940 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
941 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
942 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
943 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
944 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
953 /**********************************************************************/
955 static void process_detach(void)
957 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
958 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
959 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
962 /***********************************************************************
963 * OpenGL initialisation routine
965 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
969 case DLL_PROCESS_ATTACH:
970 opengl32_handle = hinst;
971 DisableThreadLibraryCalls(hinst);
972 return process_attach();
973 case DLL_PROCESS_DETACH: