shell32: Use S_OK as successful return code name.
[wine/multimedia.git] / dlls / opengl32 / wgl.c
blobcdd6686d03268bf8e6664bce340921dee42f3bdf
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 /* x11drv GDI escapes */
85 #define X11DRV_ESCAPE 6789
86 enum x11drv_escape_codes
88 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
89 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
90 X11DRV_GET_FONT, /* get current X font for a DC */
91 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
92 X11DRV_START_EXPOSURES, /* start graphics exposures */
93 X11DRV_END_EXPOSURES, /* end graphics exposures */
94 X11DRV_GET_DCE, /* get the DCE pointer */
95 X11DRV_SET_DCE, /* set the DCE pointer */
96 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
97 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
100 void (*wine_tsx11_lock_ptr)(void) = NULL;
101 void (*wine_tsx11_unlock_ptr)(void) = NULL;
103 static HMODULE opengl32_handle;
104 static void* libglu_handle = NULL;
106 static char* internal_gl_disabled_extensions = NULL;
107 static char* internal_gl_extensions = NULL;
109 typedef struct wine_glcontext {
110 HDC hdc;
111 BOOL do_escape;
112 /* ... more stuff here */
113 } Wine_GLContext;
115 void enter_gl(void)
117 Wine_GLContext *curctx = NtCurrentTeb()->glContext;
119 if (curctx && curctx->do_escape)
121 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
122 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
125 wine_tsx11_lock_ptr();
126 return;
129 const GLubyte * WINAPI wine_glGetString( GLenum name );
131 /***********************************************************************
132 * wglSetPixelFormat(OPENGL32.@)
134 BOOL WINAPI wglSetPixelFormat( HDC hdc, INT iPixelFormat,
135 const PIXELFORMATDESCRIPTOR *ppfd)
137 return wine_wgl.p_SetPixelFormat(hdc, iPixelFormat, ppfd);
140 /***********************************************************************
141 * wglCopyContext (OPENGL32.@)
143 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
145 return wine_wgl.p_wglCopyContext(hglrcSrc, hglrcDst, mask);
148 /***********************************************************************
149 * wglDeleteContext (OPENGL32.@)
151 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
153 return wine_wgl.p_wglDeleteContext(hglrc);
156 /***********************************************************************
157 * wglMakeCurrent (OPENGL32.@)
159 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
161 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
164 /***********************************************************************
165 * wglShareLists (OPENGL32.@)
167 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
169 return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
172 /***********************************************************************
173 * wglUseFontBitmapsA (OPENGL32.@)
175 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
177 return wine_wgl.p_wglUseFontBitmapsA(hdc, first, count, listBase);
180 /***********************************************************************
181 * wglUseFontBitmapsW (OPENGL32.@)
183 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
185 return wine_wgl.p_wglUseFontBitmapsW(hdc, first, count, listBase);
188 /***********************************************************************
189 * wglGetCurrentDC (OPENGL32.@)
191 HDC WINAPI wglGetCurrentDC(void)
193 return wine_wgl.p_wglGetCurrentDC();
196 /***********************************************************************
197 * wglCreateContext (OPENGL32.@)
199 HGLRC WINAPI wglCreateContext(HDC hdc)
201 return wine_wgl.p_wglCreateContext(hdc);
204 /***********************************************************************
205 * wglGetCurrentContext (OPENGL32.@)
207 HGLRC WINAPI wglGetCurrentContext(void)
209 return wine_wgl.p_wglGetCurrentContext();
212 /***********************************************************************
213 * wglChoosePixelFormat (OPENGL32.@)
215 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
217 return wine_wgl.p_ChoosePixelFormat(hdc, ppfd);
220 /***********************************************************************
221 * wglDescribePixelFormat (OPENGL32.@)
223 INT WINAPI wglDescribePixelFormat(HDC hdc, INT iPixelFormat, UINT nBytes,
224 LPPIXELFORMATDESCRIPTOR ppfd)
226 return wine_wgl.p_DescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
228 /***********************************************************************
229 * wglGetPixelFormat (OPENGL32.@)
231 INT WINAPI wglGetPixelFormat(HDC hdc)
233 return wine_wgl.p_GetPixelFormat(hdc);
236 /***********************************************************************
237 * wglCreateLayerContext (OPENGL32.@)
239 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
240 int iLayerPlane) {
241 TRACE("(%p,%d)\n", hdc, iLayerPlane);
243 if (iLayerPlane == 0) {
244 return wglCreateContext(hdc);
246 FIXME(" no handler for layer %d\n", iLayerPlane);
248 return NULL;
251 /***********************************************************************
252 * wglDescribeLayerPlane (OPENGL32.@)
254 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
255 int iPixelFormat,
256 int iLayerPlane,
257 UINT nBytes,
258 LPLAYERPLANEDESCRIPTOR plpd) {
259 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
261 return FALSE;
264 /***********************************************************************
265 * wglGetLayerPaletteEntries (OPENGL32.@)
267 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
268 int iLayerPlane,
269 int iStart,
270 int cEntries,
271 const COLORREF *pcr) {
272 FIXME("(): stub !\n");
274 return 0;
277 static int compar(const void *elt_a, const void *elt_b) {
278 return strcmp(((const OpenGL_extension *) elt_a)->name,
279 ((const OpenGL_extension *) elt_b)->name);
282 /* Check if a GL extension is supported */
283 static BOOL is_extension_supported(const char* extension)
285 const char *gl_ext_string = (const char*)wine_glGetString(GL_EXTENSIONS);
287 TRACE("Checking for extension '%s'\n", extension);
289 if(!gl_ext_string) {
290 ERR("No OpenGL extensions found, check if your OpenGL setup is correct!\n");
291 return FALSE;
294 /* We use the GetProcAddress function from the display driver to retrieve function pointers
295 * for OpenGL and WGL extensions. In case of winex11.drv the OpenGL extension lookup is done
296 * using glXGetProcAddress. This function is quite unreliable in the sense that its specs don't
297 * require the function to return NULL when a extension isn't found. For this reason we check
298 * if the OpenGL extension required for the function we are looking up is supported. */
300 /* Check if the extension is part of the GL extension string to see if it is supported. */
301 if(strstr(gl_ext_string, extension) != NULL)
302 return TRUE;
304 /* In general an OpenGL function starts as an ARB/EXT extension and at some stage
305 * it becomes part of the core OpenGL library and can be reached without the ARB/EXT
306 * suffix as well. In the extension table, these functions contain GL_VERSION_major_minor.
307 * Check if we are searching for a core GL function */
308 if(strncmp(extension, "GL_VERSION_", 11) == 0)
310 const GLubyte *gl_version = glGetString(GL_VERSION);
311 const char *version = extension + 11; /* Move past 'GL_VERSION_' */
313 if(!gl_version) {
314 ERR("Error no OpenGL version found,\n");
315 return FALSE;
318 /* Compare the major/minor version numbers of the native OpenGL library and what is required by the function.
319 * The gl_version string is guaranteed to have at least a major/minor and sometimes it has a release number as well. */
320 if( (gl_version[0] >= version[0]) || ((gl_version[0] == version[0]) && (gl_version[2] >= version[2])) ) {
321 return TRUE;
323 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]);
326 return FALSE;
329 /***********************************************************************
330 * wglGetProcAddress (OPENGL32.@)
332 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
333 void *local_func;
334 OpenGL_extension ext;
335 const OpenGL_extension *ext_ret;
337 TRACE("(%s)\n", lpszProc);
339 if(lpszProc == NULL)
340 return NULL;
342 /* First, look if it's not already defined in the 'standard' OpenGL functions */
343 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
344 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
345 return local_func;
348 /* After that, search in the thunks to find the real name of the extension */
349 ext.name = lpszProc;
350 ext_ret = bsearch(&ext, extension_registry, extension_registry_size,
351 sizeof(OpenGL_extension), compar);
353 /* If nothing was found, we are looking for a WGL extension or an unknown GL extension. */
354 if (ext_ret == NULL) {
355 /* If the function name starts with a w it is a WGL extension */
356 if(lpszProc[0] == 'w')
357 return wine_wgl.p_wglGetProcAddress(lpszProc);
359 /* We are dealing with an unknown GL extension. */
360 WARN("Extension '%s' not defined in opengl32.dll's function table!\n", lpszProc);
361 return NULL;
362 } else { /* We are looking for an OpenGL extension */
364 /* Check if the GL extension required by the function is available */
365 if(!is_extension_supported(ext_ret->extension)) {
366 WARN("Extension '%s' required by function '%s' not supported!\n", ext_ret->extension, lpszProc);
369 local_func = wine_wgl.p_wglGetProcAddress(ext_ret->name);
371 /* After that, look at the extensions defined in the Linux OpenGL library */
372 if (local_func == NULL) {
373 char buf[256];
374 void *ret = NULL;
376 /* Remove the 3 last letters (EXT, ARB, ...).
378 I know that some extensions have more than 3 letters (MESA, NV,
379 INTEL, ...), but this is only a stop-gap measure to fix buggy
380 OpenGL drivers (moreover, it is only useful for old 1.0 apps
381 that query the glBindTextureEXT extension).
383 memcpy(buf, ext_ret->name, strlen(ext_ret->name) - 3);
384 buf[strlen(ext_ret->name) - 3] = '\0';
385 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
387 ret = GetProcAddress(opengl32_handle, buf);
388 if (ret != NULL) {
389 TRACE(" found function in main OpenGL library (%p) !\n", ret);
390 } else {
391 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->name);
394 return ret;
395 } else {
396 TRACE(" returning function (%p)\n", ext_ret->func);
397 extension_funcs[ext_ret - extension_registry] = local_func;
399 return ext_ret->func;
404 /***********************************************************************
405 * wglRealizeLayerPalette (OPENGL32.@)
407 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
408 int iLayerPlane,
409 BOOL bRealize) {
410 FIXME("()\n");
412 return FALSE;
415 /***********************************************************************
416 * wglSetLayerPaletteEntries (OPENGL32.@)
418 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
419 int iLayerPlane,
420 int iStart,
421 int cEntries,
422 const COLORREF *pcr) {
423 FIXME("(): stub !\n");
425 return 0;
428 /***********************************************************************
429 * wglSwapLayerBuffers (OPENGL32.@)
431 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
432 UINT fuPlanes) {
433 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
435 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
436 if (!SwapBuffers(hdc)) return FALSE;
437 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
440 if (fuPlanes) {
441 WARN("Following layers unhandled : %08x\n", fuPlanes);
444 return TRUE;
447 #ifdef SONAME_LIBGLU
449 static void *load_libglu(void)
451 static int already_loaded;
452 void *handle;
454 if (already_loaded) return libglu_handle;
455 already_loaded = 1;
457 TRACE("Trying to load GLU library: %s\n", SONAME_LIBGLU);
458 handle = wine_dlopen(SONAME_LIBGLU, RTLD_NOW, NULL, 0);
459 if (!handle)
461 WARN("Failed to load %s\n", SONAME_LIBGLU);
462 return NULL;
465 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(handle, #f, NULL, 0)) == NULL) goto sym_not_found;
466 LOAD_FUNCPTR(gluNewTess)
467 LOAD_FUNCPTR(gluDeleteTess)
468 LOAD_FUNCPTR(gluTessBeginContour)
469 LOAD_FUNCPTR(gluTessBeginPolygon)
470 LOAD_FUNCPTR(gluTessCallback)
471 LOAD_FUNCPTR(gluTessEndContour)
472 LOAD_FUNCPTR(gluTessEndPolygon)
473 LOAD_FUNCPTR(gluTessVertex)
474 #undef LOAD_FUNCPTR
475 libglu_handle = handle;
476 return handle;
478 sym_not_found:
479 WARN("Unable to load function ptrs from libGLU\n");
480 /* Close the library as we won't use it */
481 wine_dlclose(handle, NULL, 0);
482 return NULL;
485 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
487 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
488 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
489 vertex[2] = 0.0;
492 static void tess_callback_vertex(GLvoid *vertex)
494 GLdouble *dbl = vertex;
495 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
496 glVertex3dv(vertex);
499 static void tess_callback_begin(GLenum which)
501 TRACE("%d\n", which);
502 glBegin(which);
505 static void tess_callback_end(void)
507 TRACE("\n");
508 glEnd();
511 /***********************************************************************
512 * wglUseFontOutlines_common
514 static BOOL wglUseFontOutlines_common(HDC hdc,
515 DWORD first,
516 DWORD count,
517 DWORD listBase,
518 FLOAT deviation,
519 FLOAT extrusion,
520 int format,
521 LPGLYPHMETRICSFLOAT lpgmf,
522 BOOL unicode)
524 UINT glyph;
525 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
526 GLUtesselator *tess;
527 LOGFONTW lf;
528 HFONT old_font, unscaled_font;
529 UINT em_size = 1024;
530 RECT rc;
532 TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
533 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
535 if (!load_libglu())
537 ERR("libGLU is required for this function but isn't loaded\n");
538 return FALSE;
541 ENTER_GL();
542 tess = pgluNewTess();
543 if(tess)
545 pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
546 pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
547 pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
549 LEAVE_GL();
551 if(!tess) return FALSE;
553 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
554 rc.left = rc.right = rc.bottom = 0;
555 rc.top = em_size;
556 DPtoLP(hdc, (POINT*)&rc, 2);
557 lf.lfHeight = -abs(rc.top - rc.bottom);
558 lf.lfOrientation = lf.lfEscapement = 0;
559 unscaled_font = CreateFontIndirectW(&lf);
560 old_font = SelectObject(hdc, unscaled_font);
562 for (glyph = first; glyph < first + count; glyph++)
564 DWORD needed;
565 GLYPHMETRICS gm;
566 BYTE *buf;
567 TTPOLYGONHEADER *pph;
568 TTPOLYCURVE *ppc;
569 GLdouble *vertices;
571 if(unicode)
572 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
573 else
574 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
576 if(needed == GDI_ERROR)
577 goto error;
579 buf = HeapAlloc(GetProcessHeap(), 0, needed);
580 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
582 if(unicode)
583 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
584 else
585 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
587 TRACE("glyph %d\n", glyph);
589 if(lpgmf)
591 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
592 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
593 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
594 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
595 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
596 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
598 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
599 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
600 lpgmf++;
603 ENTER_GL();
604 glNewList(listBase++, GL_COMPILE);
605 pgluTessBeginPolygon(tess, NULL);
607 pph = (TTPOLYGONHEADER*)buf;
608 while((BYTE*)pph < buf + needed)
610 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
612 pgluTessBeginContour(tess);
614 fixed_to_double(pph->pfxStart, em_size, vertices);
615 pgluTessVertex(tess, vertices, vertices);
616 vertices += 3;
618 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
619 while((char*)ppc < (char*)pph + pph->cb)
621 int i;
623 switch(ppc->wType) {
624 case TT_PRIM_LINE:
625 for(i = 0; i < ppc->cpfx; i++)
627 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
628 fixed_to_double(ppc->apfx[i], em_size, vertices);
629 pgluTessVertex(tess, vertices, vertices);
630 vertices += 3;
632 break;
634 case TT_PRIM_QSPLINE:
635 for(i = 0; i < ppc->cpfx/2; i++)
637 /* FIXME just connecting the control points for now */
638 TRACE("\t\tcurve %d,%d %d,%d\n",
639 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
640 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
641 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
642 pgluTessVertex(tess, vertices, vertices);
643 vertices += 3;
644 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
645 pgluTessVertex(tess, vertices, vertices);
646 vertices += 3;
648 break;
649 default:
650 ERR("\t\tcurve type = %d\n", ppc->wType);
651 pgluTessEndContour(tess);
652 goto error_in_list;
655 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
656 (ppc->cpfx - 1) * sizeof(POINTFX));
658 pgluTessEndContour(tess);
659 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
662 error_in_list:
663 pgluTessEndPolygon(tess);
664 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
665 glEndList();
666 LEAVE_GL();
667 HeapFree(GetProcessHeap(), 0, buf);
668 HeapFree(GetProcessHeap(), 0, vertices);
671 error:
672 DeleteObject(SelectObject(hdc, old_font));
673 pgluDeleteTess(tess);
674 return TRUE;
678 #else /* SONAME_LIBGLU */
680 static BOOL wglUseFontOutlines_common(HDC hdc,
681 DWORD first,
682 DWORD count,
683 DWORD listBase,
684 FLOAT deviation,
685 FLOAT extrusion,
686 int format,
687 LPGLYPHMETRICSFLOAT lpgmf,
688 BOOL unicode)
690 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
691 return FALSE;
694 #endif /* SONAME_LIBGLU */
696 /***********************************************************************
697 * wglUseFontOutlinesA (OPENGL32.@)
699 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
700 DWORD first,
701 DWORD count,
702 DWORD listBase,
703 FLOAT deviation,
704 FLOAT extrusion,
705 int format,
706 LPGLYPHMETRICSFLOAT lpgmf)
708 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
711 /***********************************************************************
712 * wglUseFontOutlinesW (OPENGL32.@)
714 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
715 DWORD first,
716 DWORD count,
717 DWORD listBase,
718 FLOAT deviation,
719 FLOAT extrusion,
720 int format,
721 LPGLYPHMETRICSFLOAT lpgmf)
723 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
726 /***********************************************************************
727 * glFinish (OPENGL32.@)
729 void WINAPI wine_glFinish( void )
731 TRACE("()\n");
732 wine_wgl.p_wglFinish();
735 /***********************************************************************
736 * glFlush (OPENGL32.@)
738 void WINAPI wine_glFlush( void )
740 TRACE("()\n");
741 wine_wgl.p_wglFlush();
744 /***********************************************************************
745 * glGetString (OPENGL32.@)
747 const GLubyte * WINAPI wine_glGetString( GLenum name )
749 const GLubyte *ret;
750 const char* GL_Extensions = NULL;
752 /* this is for buggy nvidia driver, crashing if called from a different
753 thread with no context */
754 if(wglGetCurrentContext() == NULL)
755 return NULL;
757 if (GL_EXTENSIONS != name) {
758 ENTER_GL();
759 ret = glGetString(name);
760 LEAVE_GL();
761 return ret;
764 if (NULL == internal_gl_extensions) {
765 ENTER_GL();
766 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
768 if (GL_Extensions)
770 size_t len = strlen(GL_Extensions);
771 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
773 TRACE("GL_EXTENSIONS reported:\n");
774 while (*GL_Extensions != 0x00) {
775 const char* Start = GL_Extensions;
776 char ThisExtn[256];
778 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
779 GL_Extensions++;
781 memcpy(ThisExtn, Start, (GL_Extensions - Start));
782 ThisExtn[GL_Extensions - Start] = 0;
783 TRACE("- %s:", ThisExtn);
785 /* test if supported API is disabled by config */
786 if (!internal_gl_disabled_extensions || !strstr(internal_gl_disabled_extensions, ThisExtn)) {
787 strcat(internal_gl_extensions, " ");
788 strcat(internal_gl_extensions, ThisExtn);
789 TRACE(" active\n");
790 } else {
791 TRACE(" deactived (by config)\n");
794 if (*GL_Extensions == ' ') GL_Extensions++;
797 LEAVE_GL();
799 return (const GLubyte *) internal_gl_extensions;
802 /***********************************************************************
803 * glGetIntegerv (OPENGL32.@)
805 void WINAPI wine_glGetIntegerv( GLenum pname, GLint* params )
807 wine_wgl.p_wglGetIntegerv(pname, params);
810 /***********************************************************************
811 * wglSwapBuffers (OPENGL32.@)
813 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers( HDC hdc )
815 return SwapBuffers(hdc);
818 /* This is for brain-dead applications that use OpenGL functions before even
819 creating a rendering context.... */
820 static BOOL process_attach(void)
822 HMODULE mod_x11, mod_gdi32;
823 DWORD size;
824 HKEY hkey = 0;
826 GetDesktopWindow(); /* make sure winex11 is loaded (FIXME) */
827 mod_x11 = GetModuleHandleA( "winex11.drv" );
828 mod_gdi32 = GetModuleHandleA( "gdi32.dll" );
830 if (!mod_x11 || !mod_gdi32)
832 ERR("X11DRV or GDI32 not loaded. Cannot create default context.\n");
833 return FALSE;
836 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_lock" );
837 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod_x11, "wine_tsx11_unlock" );
839 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod_gdi32, "wglGetProcAddress");
840 wine_wgl.p_SetPixelFormat = (void *)GetProcAddress(mod_gdi32, "SetPixelFormat");
841 wine_wgl.p_wglCopyContext = (void *)GetProcAddress(mod_gdi32, "wglCopyContext");
842 wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod_gdi32, "wglDeleteContext");
843 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod_gdi32, "wglMakeCurrent");
844 wine_wgl.p_wglShareLists = (void *)GetProcAddress(mod_gdi32, "wglShareLists");
845 wine_wgl.p_wglUseFontBitmapsA = (void *)GetProcAddress(mod_gdi32, "wglUseFontBitmapsA");
846 wine_wgl.p_wglUseFontBitmapsW = (void *)GetProcAddress(mod_gdi32, "wglUseFontBitmapsW");
847 wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentDC");
848 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod_gdi32, "wglCreateContext");
849 wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod_gdi32, "wglGetCurrentContext");
850 wine_wgl.p_ChoosePixelFormat = (void *)GetProcAddress(mod_gdi32, "ChoosePixelFormat");
851 wine_wgl.p_DescribePixelFormat = (void *)GetProcAddress(mod_gdi32, "DescribePixelFormat");
852 wine_wgl.p_GetPixelFormat = (void *)GetProcAddress(mod_gdi32, "GetPixelFormat");
854 /* Interal WGL function */
855 wine_wgl.p_wglGetIntegerv = (void *)wine_wgl.p_wglGetProcAddress("wglGetIntegerv");
856 wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish");
857 wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush");
859 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) {
860 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, NULL, &size)) {
861 internal_gl_disabled_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
862 RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size);
863 TRACE("found DisabledExtensions=%s\n", debugstr_a(internal_gl_disabled_extensions));
865 RegCloseKey(hkey);
868 return TRUE;
872 /**********************************************************************/
874 static void process_detach(void)
876 if (libglu_handle) wine_dlclose(libglu_handle, NULL, 0);
877 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
878 HeapFree(GetProcessHeap(), 0, internal_gl_disabled_extensions);
881 /***********************************************************************
882 * OpenGL initialisation routine
884 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
886 switch(reason)
888 case DLL_PROCESS_ATTACH:
889 opengl32_handle = hinst;
890 DisableThreadLibraryCalls(hinst);
891 return process_attach();
892 case DLL_PROCESS_DETACH:
893 process_detach();
894 break;
896 return TRUE;