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"
37 #include "opengl_ext.h"
43 #include "wine/library.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
47 WINE_DECLARE_DEBUG_CHANNEL(opengl);
49 typedef struct wine_wgl_s {
50 HGLRC WINAPI (*p_wglCreateContext)(HDC hdc);
51 BOOL WINAPI (*p_wglDeleteContext)(HGLRC hglrc);
52 HGLRC WINAPI (*p_wglGetCurrentContext)(void);
53 HDC WINAPI (*p_wglGetCurrentDC)(void);
54 HDC WINAPI (*p_wglGetCurrentReadDCARB)(void);
55 PROC WINAPI (*p_wglGetProcAddress)(LPCSTR lpszProc);
56 BOOL WINAPI (*p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
57 BOOL WINAPI (*p_wglMakeContextCurrentARB)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
58 BOOL WINAPI (*p_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
60 void WINAPI (*p_wglGetIntegerv)(GLenum pname, GLint* params);
63 /** global wgl object */
64 static wine_wgl_t wine_wgl;
66 /* x11drv GDI escapes */
67 #define X11DRV_ESCAPE 6789
68 enum x11drv_escape_codes
70 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
71 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
72 X11DRV_GET_FONT, /* get current X font for a DC */
73 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
74 X11DRV_START_EXPOSURES, /* start graphics exposures */
75 X11DRV_END_EXPOSURES, /* end graphics exposures */
76 X11DRV_GET_DCE, /* get the DCE pointer */
77 X11DRV_SET_DCE, /* set the DCE pointer */
78 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
79 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
82 void (*wine_tsx11_lock_ptr)(void) = NULL;
83 void (*wine_tsx11_unlock_ptr)(void) = NULL;
85 static GLXContext default_cx = NULL;
86 static Display *default_display; /* display to use for default context */
88 static HMODULE opengl32_handle;
90 static void* (*p_glXGetProcAddressARB)(const GLubyte *);
92 static char internal_gl_disabled_extensions[512];
93 static char* internal_gl_extensions = NULL;
95 typedef struct wine_glcontext {
102 struct wine_glcontext *next;
103 struct wine_glcontext *prev;
108 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
110 if (curctx && curctx->do_escape)
112 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
113 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
116 wine_tsx11_lock_ptr();
120 /* retrieve the X display to use on a given DC */
121 inline static Display *get_display( HDC hdc )
124 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
126 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
127 sizeof(display), (LPSTR)&display )) display = NULL;
131 /* retrieve the X font to use on a given DC */
132 inline static Font get_font( HDC hdc )
135 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
137 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
138 sizeof(font), (LPSTR)&font )) font = 0;
142 /***********************************************************************
143 * wglCreateContext (OPENGL32.@)
145 HGLRC WINAPI wglCreateContext(HDC hdc)
147 TRACE("(%p)\n", hdc);
148 return wine_wgl.p_wglCreateContext(hdc);
151 /***********************************************************************
152 * wglCreateLayerContext (OPENGL32.@)
154 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
156 TRACE("(%p,%d)\n", hdc, iLayerPlane);
158 if (iLayerPlane == 0) {
159 return wglCreateContext(hdc);
161 FIXME(" no handler for layer %d\n", iLayerPlane);
166 /***********************************************************************
167 * wglCopyContext (OPENGL32.@)
169 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
172 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
177 /***********************************************************************
178 * wglDeleteContext (OPENGL32.@)
180 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
182 TRACE("(%p)\n", hglrc);
183 return wine_wgl.p_wglDeleteContext(hglrc);
186 /***********************************************************************
187 * wglDescribeLayerPlane (OPENGL32.@)
189 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
193 LPLAYERPLANEDESCRIPTOR plpd) {
194 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
199 /***********************************************************************
200 * wglGetCurrentContext (OPENGL32.@)
202 HGLRC WINAPI wglGetCurrentContext(void) {
204 return wine_wgl.p_wglGetCurrentContext();
207 /***********************************************************************
208 * wglGetCurrentDC (OPENGL32.@)
210 HDC WINAPI wglGetCurrentDC(void) {
212 return wine_wgl.p_wglGetCurrentDC();
215 /***********************************************************************
216 * wglGetLayerPaletteEntries (OPENGL32.@)
218 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
222 const COLORREF *pcr) {
223 FIXME("(): stub !\n");
228 /***********************************************************************
229 * wglGetProcAddress (OPENGL32.@)
231 static int compar(const void *elt_a, const void *elt_b) {
232 return strcmp(((const OpenGL_extension *) elt_a)->name,
233 ((const OpenGL_extension *) elt_b)->name);
236 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
238 OpenGL_extension ext;
239 const OpenGL_extension *ext_ret;
241 TRACE("(%s)\n", lpszProc);
243 /* First, look if it's not already defined in the 'standard' OpenGL functions */
244 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
245 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
249 if (p_glXGetProcAddressARB == NULL) {
250 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
254 /* After that, search in the thunks to find the real name of the extension */
256 ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
257 extension_registry_size, sizeof(OpenGL_extension), compar);
259 /* If nothing was found, we are looking for a WGL extension */
260 if (ext_ret == NULL) {
261 return wine_wgl.p_wglGetProcAddress(lpszProc);
262 } else { /* We are looking for an OpenGL extension */
263 const char *glx_name = ext_ret->glx_name ? ext_ret->glx_name : ext_ret->name;
265 local_func = p_glXGetProcAddressARB( (const GLubyte*)glx_name);
268 /* After that, look at the extensions defined in the Linux OpenGL library */
269 if (local_func == NULL) {
273 /* Remove the 3 last letters (EXT, ARB, ...).
275 I know that some extensions have more than 3 letters (MESA, NV,
276 INTEL, ...), but this is only a stop-gap measure to fix buggy
277 OpenGL drivers (moreover, it is only useful for old 1.0 apps
278 that query the glBindTextureEXT extension).
280 memcpy(buf, glx_name, strlen(glx_name) - 3);
281 buf[strlen(glx_name) - 3] = '\0';
282 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
284 ret = GetProcAddress(opengl32_handle, buf);
286 TRACE(" found function in main OpenGL library (%p) !\n", ret);
288 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, glx_name);
293 TRACE(" returning function (%p)\n", ext_ret->func);
294 extension_funcs[ext_ret - extension_registry] = local_func;
296 return ext_ret->func;
301 /***********************************************************************
302 * wglMakeCurrent (OPENGL32.@)
304 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc) {
305 TRACE("hdc: (%p), hglrc: (%p)\n", hdc, hglrc);
306 return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
309 /***********************************************************************
310 * wglMakeContextCurrentARB (OPENGL32.@)
312 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
314 TRACE("hDrawDC: (%p), hReadDC: (%p), hglrc: (%p)\n", hDrawDC, hReadDC, hglrc);
315 return wine_wgl.p_wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc);
318 /***********************************************************************
319 * wglGetCurrentReadDCARB (OPENGL32.@)
321 HDC WINAPI wglGetCurrentReadDCARB(void)
324 return wine_wgl.p_wglGetCurrentReadDCARB();
327 /***********************************************************************
328 * wglRealizeLayerPalette (OPENGL32.@)
330 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
338 /***********************************************************************
339 * wglSetLayerPaletteEntries (OPENGL32.@)
341 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
345 const COLORREF *pcr) {
346 FIXME("(): stub !\n");
351 /***********************************************************************
352 * wglShareLists (OPENGL32.@)
354 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
355 TRACE("(%p, %p)\n", hglrc1, hglrc2);
356 return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
359 /***********************************************************************
360 * wglSwapLayerBuffers (OPENGL32.@)
362 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
364 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
366 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
367 if (!SwapBuffers(hdc)) return FALSE;
368 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
372 WARN("Following layers unhandled : %08x\n", fuPlanes);
378 static BOOL internal_wglUseFontBitmaps(HDC hdc,
382 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
384 /* We are running using client-side rendering fonts... */
388 void *bitmap = NULL, *gl_bitmap = NULL;
392 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
393 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
396 for (glyph = first; glyph < first + count; glyph++) {
397 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
398 int height, width_int;
400 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
401 if (needed_size == GDI_ERROR) {
402 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
405 TRACE(" - needed size : %d\n", needed_size);
408 if (needed_size > size) {
410 HeapFree(GetProcessHeap(), 0, bitmap);
411 HeapFree(GetProcessHeap(), 0, gl_bitmap);
412 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
413 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
415 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
416 if (TRACE_ON(opengl)) {
417 unsigned int height, width, bitmask;
418 unsigned char *bitmap_ = (unsigned char *) bitmap;
420 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
421 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
422 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
423 if (needed_size != 0) {
424 TRACE(" - bitmap :\n");
425 for (height = 0; height < gm.gmBlackBoxY; height++) {
427 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
432 if (*bitmap_ & bitmask)
437 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
443 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
444 * glyph for it to be drawn properly.
446 if (needed_size != 0) {
447 width_int = (gm.gmBlackBoxX + 31) / 32;
448 for (height = 0; height < gm.gmBlackBoxY; height++) {
450 for (width = 0; width < width_int; width++) {
451 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
452 ((int *) bitmap)[height * width_int + width];
458 glNewList(listBase++, GL_COMPILE);
459 if (needed_size != 0) {
460 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
461 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
462 gm.gmCellIncX, gm.gmCellIncY,
465 /* This is the case of 'empty' glyphs like the space character */
466 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
473 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
476 HeapFree(GetProcessHeap(), 0, bitmap);
477 HeapFree(GetProcessHeap(), 0, gl_bitmap);
482 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
485 HeapFree(GetProcessHeap(), 0, bitmap);
486 HeapFree(GetProcessHeap(), 0, gl_bitmap);
490 /***********************************************************************
491 * wglUseFontBitmapsA (OPENGL32.@)
493 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
498 Font fid = get_font( hdc );
500 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
503 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
507 /* I assume that the glyphs are at the same position for X and for Windows */
508 glXUseXFont(fid, first, count, listBase);
513 /***********************************************************************
514 * wglUseFontBitmapsW (OPENGL32.@)
516 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
521 Font fid = get_font( hdc );
523 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
526 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
529 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
532 /* I assume that the glyphs are at the same position for X and for Windows */
533 glXUseXFont(fid, first, count, listBase);
540 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
542 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
543 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
547 static void tess_callback_vertex(GLvoid *vertex)
549 GLdouble *dbl = vertex;
550 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
554 static void tess_callback_begin(GLenum which)
556 TRACE("%d\n", which);
560 static void tess_callback_end(void)
566 /***********************************************************************
567 * wglUseFontOutlines_common
569 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
576 LPGLYPHMETRICSFLOAT lpgmf,
580 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
583 HFONT old_font, unscaled_font;
587 TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
588 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
595 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
596 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
597 gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
601 if(!tess) return FALSE;
603 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
604 rc.left = rc.right = rc.bottom = 0;
606 DPtoLP(hdc, (POINT*)&rc, 2);
607 lf.lfHeight = -abs(rc.top - rc.bottom);
608 lf.lfOrientation = lf.lfEscapement = 0;
609 unscaled_font = CreateFontIndirectW(&lf);
610 old_font = SelectObject(hdc, unscaled_font);
612 for (glyph = first; glyph < first + count; glyph++)
617 TTPOLYGONHEADER *pph;
622 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
624 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
626 if(needed == GDI_ERROR)
629 buf = HeapAlloc(GetProcessHeap(), 0, needed);
630 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
633 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
635 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
637 TRACE("glyph %d\n", glyph);
641 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
642 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
643 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
644 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
645 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
646 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
648 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
649 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
654 glNewList(listBase++, GL_COMPILE);
655 gluTessBeginPolygon(tess, NULL);
657 pph = (TTPOLYGONHEADER*)buf;
658 while((BYTE*)pph < buf + needed)
660 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
662 gluTessBeginContour(tess);
664 fixed_to_double(pph->pfxStart, em_size, vertices);
665 gluTessVertex(tess, vertices, vertices);
668 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
669 while((char*)ppc < (char*)pph + pph->cb)
675 for(i = 0; i < ppc->cpfx; i++)
677 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
678 fixed_to_double(ppc->apfx[i], em_size, vertices);
679 gluTessVertex(tess, vertices, vertices);
684 case TT_PRIM_QSPLINE:
685 for(i = 0; i < ppc->cpfx/2; i++)
687 /* FIXME just connecting the control points for now */
688 TRACE("\t\tcurve %d,%d %d,%d\n",
689 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
690 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
691 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
692 gluTessVertex(tess, vertices, vertices);
694 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
695 gluTessVertex(tess, vertices, vertices);
700 ERR("\t\tcurve type = %d\n", ppc->wType);
701 gluTessEndContour(tess);
705 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
706 (ppc->cpfx - 1) * sizeof(POINTFX));
708 gluTessEndContour(tess);
709 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
713 gluTessEndPolygon(tess);
714 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
717 HeapFree(GetProcessHeap(), 0, buf);
718 HeapFree(GetProcessHeap(), 0, vertices);
722 DeleteObject(SelectObject(hdc, old_font));
728 #else /* HAVE_GL_GLU_H */
730 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
737 LPGLYPHMETRICSFLOAT lpgmf,
740 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
744 #endif /* HAVE_GL_GLU_H */
746 /***********************************************************************
747 * wglUseFontOutlinesA (OPENGL32.@)
749 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
756 LPGLYPHMETRICSFLOAT lpgmf)
758 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
761 /***********************************************************************
762 * wglUseFontOutlinesW (OPENGL32.@)
764 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
771 LPGLYPHMETRICSFLOAT lpgmf)
773 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
776 const GLubyte * internal_glGetString(GLenum name) {
777 const char* GL_Extensions = NULL;
779 if (GL_EXTENSIONS != name) {
780 return glGetString(name);
783 if (NULL == internal_gl_extensions) {
784 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
786 TRACE("GL_EXTENSIONS reported:\n");
787 if (NULL == GL_Extensions) {
788 ERR("GL_EXTENSIONS returns NULL\n");
791 size_t len = strlen(GL_Extensions);
792 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
794 while (*GL_Extensions != 0x00) {
795 const char* Start = GL_Extensions;
798 memset(ThisExtn, 0x00, sizeof(ThisExtn));
799 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
802 memcpy(ThisExtn, Start, (GL_Extensions - Start));
803 TRACE("- %s:", ThisExtn);
805 /* test if supported API is disabled by config */
806 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
807 strcat(internal_gl_extensions, " ");
808 strcat(internal_gl_extensions, ThisExtn);
811 TRACE(" deactived (by config)\n");
814 if (*GL_Extensions == ' ') GL_Extensions++;
818 return (const GLubyte *) internal_gl_extensions;
821 void internal_glGetIntegerv(GLenum pname, GLint* params) {
822 TRACE("pname: 0x%x, params %p\n", pname, params);
823 glGetIntegerv(pname, params);
824 /* A few parameters like GL_DEPTH_BITS differ between WGL and GLX, the wglGetIntegerv helper function handles those */
825 wine_wgl.p_wglGetIntegerv(pname, params);
829 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
830 include all dependencies
833 #define SONAME_LIBGL "libGL.so"
836 /* This is for brain-dead applications that use OpenGL functions before even
837 creating a rendering context.... */
838 static BOOL process_attach(void)
840 XWindowAttributes win_attr;
843 XVisualInfo template;
845 XVisualInfo *vis = NULL;
846 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
847 HMODULE mod = GetModuleHandleA( "winex11.drv" );
849 DWORD size = sizeof(internal_gl_disabled_extensions);
854 ERR("X11DRV not loaded. Cannot create default context.\n");
858 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
859 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
861 /* Load WGL function pointers from winex11.drv */
862 wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod, "wglCreateContext");
863 wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod, "wglDeleteContext");
864 wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod, "wglGetCurrentContext");
865 wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod, "wglGetCurrentDC");
866 wine_wgl.p_wglGetCurrentReadDCARB = (void *)GetProcAddress(mod, "wglGetCurrentReadDCARB");
867 wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod, "wglGetProcAddress");
868 wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod, "wglMakeCurrent");
869 wine_wgl.p_wglMakeContextCurrentARB = (void *)GetProcAddress(mod, "wglMakeContextCurrentARB");
870 wine_wgl.p_wglShareLists = (void *)GetProcAddress(mod, "wglShareLists");
871 /* Interal WGL function */
872 wine_wgl.p_wglGetIntegerv = (void *)GetProcAddress(mod, "wglGetIntegerv");
875 default_display = get_display( hdc );
877 if (!default_display)
879 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
885 /* Try to get the visual from the Root Window. We can't use the standard (presumably
886 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
887 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
888 with mismatched visuals. Note that the Root Window visual may not be double
889 buffered, so apps actually attempting to render this way may flicker */
890 if (XGetWindowAttributes( default_display, root, &win_attr ))
892 rootVisual = win_attr.visual;
896 /* Get the default visual, since we can't seem to get the attributes from the
897 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
898 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
901 template.visualid = XVisualIDFromVisual(rootVisual);
902 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
903 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
904 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
908 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
909 if (opengl_handle != NULL) {
910 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
911 wine_dlclose(opengl_handle, NULL, 0);
912 if (p_glXGetProcAddressARB == NULL)
913 TRACE("could not find glXGetProcAddressARB in libGL.\n");
916 internal_gl_disabled_extensions[0] = 0;
917 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
918 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
919 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
924 if (default_cx == NULL) {
925 ERR("Could not create default context.\n");
931 /**********************************************************************/
933 static void process_detach(void)
935 glXDestroyContext(default_display, default_cx);
937 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
940 /***********************************************************************
941 * OpenGL initialisation routine
943 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
947 case DLL_PROCESS_ATTACH:
948 opengl32_handle = hinst;
949 DisableThreadLibraryCalls(hinst);
950 return process_attach();
951 case DLL_PROCESS_DETACH: