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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
36 #include "opengl_ext.h"
37 #include "wine/library.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 void (*wine_tsx11_lock_ptr)(void) = NULL;
52 void (*wine_tsx11_unlock_ptr)(void) = NULL;
54 static GLXContext default_cx = NULL;
55 static Display *default_display; /* display to use for default context */
57 static HMODULE opengl32_handle;
59 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
61 static char internal_gl_disabled_extensions[512];
62 static char* internal_gl_extensions = NULL;
64 typedef struct wine_glcontext {
70 struct wine_glcontext *next;
71 struct wine_glcontext *prev;
73 static Wine_GLContext *context_list;
75 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
78 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
82 static inline void free_context(Wine_GLContext *context)
84 if (context->next != NULL) context->next->prev = context->prev;
85 if (context->prev != NULL) context->prev->next = context->next;
86 else context_list = context->next;
88 HeapFree(GetProcessHeap(), 0, context);
91 static inline Wine_GLContext *alloc_context(void)
95 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
97 ret->next = context_list;
98 if (context_list) context_list->prev = ret;
104 inline static BOOL is_valid_context( Wine_GLContext *ctx )
107 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
108 return (ptr != NULL);
111 /* retrieve the X display to use on a given DC */
112 inline static Display *get_display( HDC hdc )
115 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
117 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
118 sizeof(display), (LPSTR)&display )) display = NULL;
123 /* retrieve the X drawable to use on a given DC */
124 inline static Drawable get_drawable( HDC hdc )
127 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
129 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
130 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
134 /** for use of wglGetCurrentReadDCARB */
135 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
138 for (ret = context_list; ret; ret = ret->next) {
139 if (d == get_drawable( ret->hdc )) {
146 /* retrieve the X drawable to use on a given DC */
147 inline static Font get_font( HDC hdc )
150 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
152 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
153 sizeof(font), (LPSTR)&font )) font = 0;
158 /***********************************************************************
159 * wglCreateContext (OPENGL32.@)
161 HGLRC WINAPI wglCreateContext(HDC hdc)
166 XVisualInfo template;
167 Display *display = get_display( hdc );
168 int hdcPF = GetPixelFormat(hdc);
171 TRACE("(%p)\n", hdc);
173 /* First, get the visual in use by the X11DRV */
174 if (!display) return 0;
175 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
176 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
179 ERR("NULL visual !!!\n");
180 /* Need to set errors here */
184 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
190 GLXFBConfig* cfgs_fmt = NULL;
193 cfgs_fmt = glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
194 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
195 ERR("Cannot get FB Configs, expect problems.\n");
196 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
199 if (nCfgs_fmt < hdcPF) {
200 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, nCfgs_fmt);
201 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
204 cur_cfg = cfgs_fmt[hdcPF - 1];
205 gl_test = glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
207 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
208 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
214 /* The context will be allocated in the wglMakeCurrent call */
216 ret = alloc_context();
219 ret->display = display;
221 ret->fb_conf = cur_cfg;
223 TRACE(" creating context %p (GL context creation delayed)\n", ret);
227 /***********************************************************************
228 * wglCreateLayerContext (OPENGL32.@)
230 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
232 TRACE("(%p,%d)\n", hdc, iLayerPlane);
234 if (iLayerPlane == 0) {
235 return wglCreateContext(hdc);
237 FIXME(" no handler for layer %d\n", iLayerPlane);
242 /***********************************************************************
243 * wglCopyContext (OPENGL32.@)
245 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
248 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
253 /***********************************************************************
254 * wglDeleteContext (OPENGL32.@)
256 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
258 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
261 TRACE("(%p)\n", hglrc);
264 /* A game (Half Life not to name it) deletes twice the same context,
265 * so make sure it is valid first */
266 if (is_valid_context( ctx ))
268 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
273 WARN("Error deleting context !\n");
274 SetLastError(ERROR_INVALID_HANDLE);
282 /***********************************************************************
283 * wglDescribeLayerPlane (OPENGL32.@)
285 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
289 LPLAYERPLANEDESCRIPTOR plpd) {
290 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
295 /***********************************************************************
296 * wglGetCurrentContext (OPENGL32.@)
298 HGLRC WINAPI wglGetCurrentContext(void) {
305 gl_ctx = glXGetCurrentContext();
306 ret = get_context_from_GLXContext(gl_ctx);
309 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
314 /***********************************************************************
315 * wglGetCurrentDC (OPENGL32.@)
317 HDC WINAPI wglGetCurrentDC(void) {
324 gl_ctx = glXGetCurrentContext();
325 ret = get_context_from_GLXContext(gl_ctx);
329 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
332 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
337 /***********************************************************************
338 * wglGetLayerPaletteEntries (OPENGL32.@)
340 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
344 const COLORREF *pcr) {
345 FIXME("(): stub !\n");
350 /***********************************************************************
351 * wglGetProcAddress (OPENGL32.@)
353 static int compar(const void *elt_a, const void *elt_b) {
354 return strcmp(((const OpenGL_extension *) elt_a)->name,
355 ((const OpenGL_extension *) elt_b)->name);
358 static int wgl_compar(const void *elt_a, const void *elt_b) {
359 return strcmp(((const WGL_extension *) elt_a)->func_name,
360 ((const WGL_extension *) elt_b)->func_name);
363 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
365 OpenGL_extension ext;
366 OpenGL_extension *ext_ret;
368 TRACE("(%s)\n", lpszProc);
370 /* First, look if it's not already defined in the 'standard' OpenGL functions */
371 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
372 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
376 if (p_glXGetProcAddressARB == NULL) {
377 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
381 /* After that, search in the thunks to find the real name of the extension */
382 ext.name = (char *) lpszProc;
383 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
384 extension_registry_size, sizeof(OpenGL_extension), compar);
386 if (ext_ret == NULL) {
387 WGL_extension wgl_ext, *wgl_ext_ret;
389 /* Try to find the function in the WGL extensions ... */
390 wgl_ext.func_name = (char *) lpszProc;
391 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
392 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
394 if (wgl_ext_ret == NULL) {
395 /* Some sanity checks :-) */
397 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
399 if (local_func != NULL) {
400 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
404 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
409 if (wgl_ext_ret->func_init != NULL) {
411 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
412 wgl_ext_ret->context)) == NULL) {
413 ret = wgl_ext_ret->func_address;
415 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
419 ret = wgl_ext_ret->func_address;
423 TRACE(" returning WGL function (%p)\n", ret);
428 local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
431 /* After that, look at the extensions defined in the Linux OpenGL library */
432 if (local_func == NULL) {
436 /* Remove the 3 last letters (EXT, ARB, ...).
438 I know that some extensions have more than 3 letters (MESA, NV,
439 INTEL, ...), but this is only a stop-gap measure to fix buggy
440 OpenGL drivers (moreover, it is only useful for old 1.0 apps
441 that query the glBindTextureEXT extension).
443 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
444 buf[strlen(ext_ret->glx_name) - 3] = '\0';
445 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
447 ret = GetProcAddress(opengl32_handle, buf);
449 TRACE(" found function in main OpenGL library (%p) !\n", ret);
451 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
456 TRACE(" returning function (%p)\n", ext_ret->func);
457 *(ext_ret->func_ptr) = local_func;
459 return ext_ret->func;
464 /***********************************************************************
465 * wglMakeCurrent (OPENGL32.@)
467 BOOL WINAPI wglMakeCurrent(HDC hdc,
471 TRACE("(%p,%p)\n", hdc, hglrc);
475 ret = glXMakeCurrent(default_display, None, NULL);
477 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
478 Drawable drawable = get_drawable( hdc );
479 if (ctx->ctx == NULL) {
480 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
481 TRACE(" created a delayed OpenGL context (%p) for %p\n", ctx->ctx, ctx->vis);
483 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
484 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
487 TRACE(" returning %s\n", (ret ? "True" : "False"));
491 /***********************************************************************
492 * wglMakeContextCurrentARB (OPENGL32.@)
494 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
497 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
501 ret = glXMakeCurrent(default_display, None, NULL);
503 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
504 Drawable d_draw = get_drawable( hDrawDC );
505 Drawable d_read = get_drawable( hReadDC );
507 if (ctx->ctx == NULL) {
508 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
509 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
511 ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
515 TRACE(" returning %s\n", (ret ? "True" : "False"));
519 /***********************************************************************
520 * wglGetCurrentReadDCARB (OPENGL32.@)
522 HDC WINAPI wglGetCurrentReadDCARB(void)
530 gl_d = glXGetCurrentReadDrawable();
531 ret = get_hdc_from_Drawable(gl_d);
534 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
540 /***********************************************************************
541 * wglRealizeLayerPalette (OPENGL32.@)
543 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
551 /***********************************************************************
552 * wglSetLayerPaletteEntries (OPENGL32.@)
554 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
558 const COLORREF *pcr) {
559 FIXME("(): stub !\n");
564 /***********************************************************************
565 * wglShareLists (OPENGL32.@)
567 BOOL WINAPI wglShareLists(HGLRC hglrc1,
569 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
570 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
572 TRACE("(%p, %p)\n", org, dest);
574 if (NULL != dest && dest->ctx != NULL) {
575 ERR("Could not share display lists, context already created !\n");
578 if (org->ctx == NULL) {
580 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
582 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
586 /* Create the destination context with display lists shared */
587 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
589 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
596 /***********************************************************************
597 * wglSwapLayerBuffers (OPENGL32.@)
599 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
601 TRACE("(%p, %08x)\n", hdc, fuPlanes);
603 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
604 if (!SwapBuffers(hdc)) return FALSE;
605 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
609 WARN("Following layers unhandled : %08x\n", fuPlanes);
615 static BOOL internal_wglUseFontBitmaps(HDC hdc,
619 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
621 /* We are running using client-side rendering fonts... */
625 void *bitmap = NULL, *gl_bitmap = NULL;
629 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
630 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
633 for (glyph = first; glyph < first + count; glyph++) {
634 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
635 int height, width_int;
637 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
638 if (needed_size == GDI_ERROR) {
639 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
642 TRACE(" - needed size : %d\n", needed_size);
645 if (needed_size > size) {
647 HeapFree(GetProcessHeap(), 0, bitmap);
648 HeapFree(GetProcessHeap(), 0, gl_bitmap);
649 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
650 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
652 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
653 if (TRACE_ON(opengl)) {
654 unsigned int height, width, bitmask;
655 unsigned char *bitmap_ = (unsigned char *) bitmap;
657 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
658 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
659 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
660 if (needed_size != 0) {
661 TRACE(" - bitmap :\n");
662 for (height = 0; height < gm.gmBlackBoxY; height++) {
664 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
669 if (*bitmap_ & bitmask)
674 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
680 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
681 * glyph for it to be drawn properly.
683 if (needed_size != 0) {
684 width_int = (gm.gmBlackBoxX + 31) / 32;
685 for (height = 0; height < gm.gmBlackBoxY; height++) {
687 for (width = 0; width < width_int; width++) {
688 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
689 ((int *) bitmap)[height * width_int + width];
695 glNewList(listBase++, GL_COMPILE);
696 if (needed_size != 0) {
697 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
698 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
699 gm.gmCellIncX, gm.gmCellIncY,
702 /* This is the case of 'empty' glyphs like the space character */
703 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
710 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
713 HeapFree(GetProcessHeap(), 0, bitmap);
714 HeapFree(GetProcessHeap(), 0, gl_bitmap);
719 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
722 HeapFree(GetProcessHeap(), 0, bitmap);
723 HeapFree(GetProcessHeap(), 0, gl_bitmap);
727 /***********************************************************************
728 * wglUseFontBitmapsA (OPENGL32.@)
730 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
735 Font fid = get_font( hdc );
737 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
740 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
744 /* I assume that the glyphs are at the same position for X and for Windows */
745 glXUseXFont(fid, first, count, listBase);
750 /***********************************************************************
751 * wglUseFontBitmapsW (OPENGL32.@)
753 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
758 Font fid = get_font( hdc );
760 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
763 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
766 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
769 /* I assume that the glyphs are at the same position for X and for Windows */
770 glXUseXFont(fid, first, count, listBase);
775 /***********************************************************************
776 * wglUseFontOutlinesA (OPENGL32.@)
778 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
785 LPGLYPHMETRICSFLOAT lpgmf) {
786 FIXME("(): stub !\n");
791 const GLubyte * internal_glGetString(GLenum name) {
792 const char* GL_Extensions = NULL;
794 if (GL_EXTENSIONS != name) {
795 return glGetString(name);
798 if (NULL == internal_gl_extensions) {
799 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
801 TRACE("GL_EXTENSIONS reported:\n");
802 if (NULL == GL_Extensions) {
803 ERR("GL_EXTENSIONS returns NULL\n");
806 size_t len = strlen(GL_Extensions);
807 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
809 while (*GL_Extensions != 0x00) {
810 const char* Start = GL_Extensions;
813 memset(ThisExtn, 0x00, sizeof(ThisExtn));
814 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
817 memcpy(ThisExtn, Start, (GL_Extensions - Start));
818 TRACE("- %s:", ThisExtn);
820 /* test if supported API is disabled by config */
821 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
822 strcat(internal_gl_extensions, " ");
823 strcat(internal_gl_extensions, ThisExtn);
826 TRACE(" deactived (by config)\n");
829 if (*GL_Extensions == ' ') GL_Extensions++;
833 return (const GLubyte *) internal_gl_extensions;
836 void internal_glGetIntegerv(GLenum pname, GLint* params) {
837 glGetIntegerv(pname, params);
838 if (pname == GL_ALPHA_BITS) {
840 GLXContext gl_ctx = glXGetCurrentContext();
841 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
842 glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
843 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
849 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
850 include all dependencies
853 #define SONAME_LIBGL "libGL.so"
856 /* This is for brain-dead applications that use OpenGL functions before even
857 creating a rendering context.... */
858 static BOOL process_attach(void)
860 XWindowAttributes win_attr;
863 XVisualInfo template;
865 XVisualInfo *vis = NULL;
866 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
867 HMODULE mod = GetModuleHandleA( "winex11.drv" );
869 DWORD size = sizeof(internal_gl_disabled_extensions);
874 ERR("X11DRV not loaded. Cannot create default context.\n");
878 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
879 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
882 default_display = get_display( hdc );
884 if (!default_display)
886 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
892 /* Try to get the visual from the Root Window. We can't use the standard (presumably
893 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
894 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
895 with mismatched visuals. Note that the Root Window visual may not be double
896 buffered, so apps actually attempting to render this way may flicker */
897 if (XGetWindowAttributes( default_display, root, &win_attr ))
899 rootVisual = win_attr.visual;
903 /* Get the default visual, since we can't seem to get the attributes from the
904 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
905 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
908 template.visualid = XVisualIDFromVisual(rootVisual);
909 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
910 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
911 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
915 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
916 if (opengl_handle != NULL) {
917 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
918 wine_dlclose(opengl_handle, NULL, 0);
919 if (p_glXGetProcAddressARB == NULL)
920 TRACE("could not find glXGetProcAddressARB in libGL.\n");
923 internal_gl_disabled_extensions[0] = 0;
924 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
925 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
926 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
931 if (default_cx == NULL) {
932 ERR("Could not create default context.\n");
936 /* After context initialize also the list of supported WGL extensions. */
937 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
943 /**********************************************************************/
945 static void process_detach(void)
947 glXDestroyContext(default_display, default_cx);
949 /* Do not leak memory... */
950 wgl_ext_finalize_extensions();
951 if (NULL != internal_gl_extensions) {
952 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
956 /***********************************************************************
957 * OpenGL initialisation routine
959 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
963 case DLL_PROCESS_ATTACH:
964 opengl32_handle = hinst;
965 DisableThreadLibraryCalls(hinst);
966 return process_attach();
967 case DLL_PROCESS_DETACH: