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 );
169 TRACE("(%p)\n", hdc);
171 /* First, get the visual in use by the X11DRV */
172 if (!display) return 0;
173 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
174 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
177 ERR("NULL visual !!!\n");
178 /* Need to set errors here */
182 /* The context will be allocated in the wglMakeCurrent call */
184 ret = alloc_context();
187 ret->display = display;
191 int hdcPF = GetPixelFormat(hdc);
193 GLXFBConfig* cfgs_fmt = NULL;
197 cfgs_fmt = glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
198 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
199 ERR("Cannot get FB Configs, expect problems.\n");
202 cur_cfg = cfgs_fmt[hdcPF - 1];
203 gl_test = glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
205 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
208 ret->fb_conf = cur_cfg;
212 TRACE(" creating context %p (GL context creation delayed)\n", ret);
216 /***********************************************************************
217 * wglCreateLayerContext (OPENGL32.@)
219 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
221 TRACE("(%p,%d)\n", hdc, iLayerPlane);
223 if (iLayerPlane == 0) {
224 return wglCreateContext(hdc);
226 FIXME(" no handler for layer %d\n", iLayerPlane);
231 /***********************************************************************
232 * wglCopyContext (OPENGL32.@)
234 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
237 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
242 /***********************************************************************
243 * wglDeleteContext (OPENGL32.@)
245 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
247 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
250 TRACE("(%p)\n", hglrc);
253 /* A game (Half Life not to name it) deletes twice the same context,
254 * so make sure it is valid first */
255 if (is_valid_context( ctx ))
257 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
262 WARN("Error deleting context !\n");
263 SetLastError(ERROR_INVALID_HANDLE);
271 /***********************************************************************
272 * wglDescribeLayerPlane (OPENGL32.@)
274 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
278 LPLAYERPLANEDESCRIPTOR plpd) {
279 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
284 /***********************************************************************
285 * wglGetCurrentContext (OPENGL32.@)
287 HGLRC WINAPI wglGetCurrentContext(void) {
294 gl_ctx = glXGetCurrentContext();
295 ret = get_context_from_GLXContext(gl_ctx);
298 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
303 /***********************************************************************
304 * wglGetCurrentDC (OPENGL32.@)
306 HDC WINAPI wglGetCurrentDC(void) {
313 gl_ctx = glXGetCurrentContext();
314 ret = get_context_from_GLXContext(gl_ctx);
318 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
321 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
326 /***********************************************************************
327 * wglGetLayerPaletteEntries (OPENGL32.@)
329 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
333 const COLORREF *pcr) {
334 FIXME("(): stub !\n");
339 /***********************************************************************
340 * wglGetProcAddress (OPENGL32.@)
342 static int compar(const void *elt_a, const void *elt_b) {
343 return strcmp(((const OpenGL_extension *) elt_a)->name,
344 ((const OpenGL_extension *) elt_b)->name);
347 static int wgl_compar(const void *elt_a, const void *elt_b) {
348 return strcmp(((const WGL_extension *) elt_a)->func_name,
349 ((const WGL_extension *) elt_b)->func_name);
352 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
354 OpenGL_extension ext;
355 OpenGL_extension *ext_ret;
357 TRACE("(%s)\n", lpszProc);
359 /* First, look if it's not already defined in the 'standard' OpenGL functions */
360 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
361 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
365 if (p_glXGetProcAddressARB == NULL) {
366 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
370 /* After that, search in the thunks to find the real name of the extension */
371 ext.name = (char *) lpszProc;
372 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
373 extension_registry_size, sizeof(OpenGL_extension), compar);
375 if (ext_ret == NULL) {
376 WGL_extension wgl_ext, *wgl_ext_ret;
378 /* Try to find the function in the WGL extensions ... */
379 wgl_ext.func_name = (char *) lpszProc;
380 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
381 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
383 if (wgl_ext_ret == NULL) {
384 /* Some sanity checks :-) */
386 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
388 if (local_func != NULL) {
389 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
393 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
398 if (wgl_ext_ret->func_init != NULL) {
400 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
401 wgl_ext_ret->context)) == NULL) {
402 ret = wgl_ext_ret->func_address;
404 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
408 ret = wgl_ext_ret->func_address;
412 TRACE(" returning WGL function (%p)\n", ret);
417 local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
420 /* After that, look at the extensions defined in the Linux OpenGL library */
421 if (local_func == NULL) {
425 /* Remove the 3 last letters (EXT, ARB, ...).
427 I know that some extensions have more than 3 letters (MESA, NV,
428 INTEL, ...), but this is only a stop-gap measure to fix buggy
429 OpenGL drivers (moreover, it is only useful for old 1.0 apps
430 that query the glBindTextureEXT extension).
432 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
433 buf[strlen(ext_ret->glx_name) - 3] = '\0';
434 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
436 ret = GetProcAddress(opengl32_handle, buf);
438 TRACE(" found function in main OpenGL library (%p) !\n", ret);
440 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
445 TRACE(" returning function (%p)\n", ext_ret->func);
446 *(ext_ret->func_ptr) = local_func;
448 return ext_ret->func;
453 /***********************************************************************
454 * wglMakeCurrent (OPENGL32.@)
456 BOOL WINAPI wglMakeCurrent(HDC hdc,
460 TRACE("(%p,%p)\n", hdc, hglrc);
464 ret = glXMakeCurrent(default_display, None, NULL);
466 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
467 Drawable drawable = get_drawable( hdc );
468 if (ctx->ctx == NULL) {
469 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
470 TRACE(" created a delayed OpenGL context (%p) for %p\n", ctx->ctx, ctx->vis);
472 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
473 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
476 TRACE(" returning %s\n", (ret ? "True" : "False"));
480 /***********************************************************************
481 * wglMakeContextCurrentARB (OPENGL32.@)
483 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
486 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
490 ret = glXMakeCurrent(default_display, None, NULL);
492 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
493 Drawable d_draw = get_drawable( hDrawDC );
494 Drawable d_read = get_drawable( hReadDC );
496 if (ctx->ctx == NULL) {
497 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
498 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
500 ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
504 TRACE(" returning %s\n", (ret ? "True" : "False"));
508 /***********************************************************************
509 * wglGetCurrentReadDCARB (OPENGL32.@)
511 HDC WINAPI wglGetCurrentReadDCARB(void)
519 gl_d = glXGetCurrentReadDrawable();
520 ret = get_hdc_from_Drawable(gl_d);
523 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
529 /***********************************************************************
530 * wglRealizeLayerPalette (OPENGL32.@)
532 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
540 /***********************************************************************
541 * wglSetLayerPaletteEntries (OPENGL32.@)
543 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
547 const COLORREF *pcr) {
548 FIXME("(): stub !\n");
553 /***********************************************************************
554 * wglShareLists (OPENGL32.@)
556 BOOL WINAPI wglShareLists(HGLRC hglrc1,
558 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
559 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
561 TRACE("(%p, %p)\n", org, dest);
563 if (NULL != dest && dest->ctx != NULL) {
564 ERR("Could not share display lists, context already created !\n");
567 if (org->ctx == NULL) {
569 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
571 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
575 /* Create the destination context with display lists shared */
576 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
578 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
585 /***********************************************************************
586 * wglSwapLayerBuffers (OPENGL32.@)
588 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
590 TRACE("(%p, %08x)\n", hdc, fuPlanes);
592 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
593 if (!SwapBuffers(hdc)) return FALSE;
594 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
598 WARN("Following layers unhandled : %08x\n", fuPlanes);
604 static BOOL internal_wglUseFontBitmaps(HDC hdc,
608 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
610 /* We are running using client-side rendering fonts... */
614 void *bitmap = NULL, *gl_bitmap = NULL;
618 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
619 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
622 for (glyph = first; glyph < first + count; glyph++) {
623 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
624 int height, width_int;
626 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
627 if (needed_size == GDI_ERROR) {
628 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
631 TRACE(" - needed size : %d\n", needed_size);
634 if (needed_size > size) {
636 HeapFree(GetProcessHeap(), 0, bitmap);
637 HeapFree(GetProcessHeap(), 0, gl_bitmap);
638 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
639 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
641 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
642 if (TRACE_ON(opengl)) {
643 unsigned int height, width, bitmask;
644 unsigned char *bitmap_ = (unsigned char *) bitmap;
646 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
647 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
648 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
649 if (needed_size != 0) {
650 TRACE(" - bitmap :\n");
651 for (height = 0; height < gm.gmBlackBoxY; height++) {
653 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
658 if (*bitmap_ & bitmask)
663 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
669 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
670 * glyph for it to be drawn properly.
672 if (needed_size != 0) {
673 width_int = (gm.gmBlackBoxX + 31) / 32;
674 for (height = 0; height < gm.gmBlackBoxY; height++) {
676 for (width = 0; width < width_int; width++) {
677 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
678 ((int *) bitmap)[height * width_int + width];
684 glNewList(listBase++, GL_COMPILE);
685 if (needed_size != 0) {
686 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
687 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
688 gm.gmCellIncX, gm.gmCellIncY,
691 /* This is the case of 'empty' glyphs like the space character */
692 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
699 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
702 HeapFree(GetProcessHeap(), 0, bitmap);
703 HeapFree(GetProcessHeap(), 0, gl_bitmap);
708 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
711 HeapFree(GetProcessHeap(), 0, bitmap);
712 HeapFree(GetProcessHeap(), 0, gl_bitmap);
716 /***********************************************************************
717 * wglUseFontBitmapsA (OPENGL32.@)
719 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
724 Font fid = get_font( hdc );
726 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
729 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
733 /* I assume that the glyphs are at the same position for X and for Windows */
734 glXUseXFont(fid, first, count, listBase);
739 /***********************************************************************
740 * wglUseFontBitmapsW (OPENGL32.@)
742 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
747 Font fid = get_font( hdc );
749 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
752 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
755 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
758 /* I assume that the glyphs are at the same position for X and for Windows */
759 glXUseXFont(fid, first, count, listBase);
764 /***********************************************************************
765 * wglUseFontOutlinesA (OPENGL32.@)
767 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
774 LPGLYPHMETRICSFLOAT lpgmf) {
775 FIXME("(): stub !\n");
780 const GLubyte * internal_glGetString(GLenum name) {
781 const char* GL_Extensions = NULL;
783 if (GL_EXTENSIONS != name) {
784 return glGetString(name);
787 if (NULL == internal_gl_extensions) {
788 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
790 TRACE("GL_EXTENSIONS reported:\n");
791 if (NULL == GL_Extensions) {
792 ERR("GL_EXTENSIONS returns NULL\n");
795 size_t len = strlen(GL_Extensions);
796 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
798 while (*GL_Extensions != 0x00) {
799 const char* Start = GL_Extensions;
802 memset(ThisExtn, 0x00, sizeof(ThisExtn));
803 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
806 memcpy(ThisExtn, Start, (GL_Extensions - Start));
807 TRACE("- %s:", ThisExtn);
809 /* test if supported API is disabled by config */
810 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
811 strcat(internal_gl_extensions, " ");
812 strcat(internal_gl_extensions, ThisExtn);
815 TRACE(" deactived (by config)\n");
818 if (*GL_Extensions == ' ') GL_Extensions++;
822 return (const GLubyte *) internal_gl_extensions;
825 void internal_glGetIntegerv(GLenum pname, GLint* params) {
826 glGetIntegerv(pname, params);
827 if (pname == GL_ALPHA_BITS) {
829 GLXContext gl_ctx = glXGetCurrentContext();
830 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
831 glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
832 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
838 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
839 include all dependencies
842 #define SONAME_LIBGL "libGL.so"
845 /* This is for brain-dead applications that use OpenGL functions before even
846 creating a rendering context.... */
847 static BOOL process_attach(void)
849 XWindowAttributes win_attr;
852 XVisualInfo template;
854 XVisualInfo *vis = NULL;
855 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
856 HMODULE mod = GetModuleHandleA( "winex11.drv" );
858 DWORD size = sizeof(internal_gl_disabled_extensions);
863 ERR("X11DRV not loaded. Cannot create default context.\n");
867 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
868 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
871 default_display = get_display( hdc );
873 if (!default_display)
875 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
881 /* Try to get the visual from the Root Window. We can't use the standard (presumably
882 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
883 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
884 with mismatched visuals. Note that the Root Window visual may not be double
885 buffered, so apps actually attempting to render this way may flicker */
886 if (XGetWindowAttributes( default_display, root, &win_attr ))
888 rootVisual = win_attr.visual;
892 /* Get the default visual, since we can't seem to get the attributes from the
893 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
894 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
897 template.visualid = XVisualIDFromVisual(rootVisual);
898 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
899 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
900 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
904 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
905 if (opengl_handle != NULL) {
906 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
907 wine_dlclose(opengl_handle, NULL, 0);
908 if (p_glXGetProcAddressARB == NULL)
909 TRACE("could not find glXGetProcAddressARB in libGL.\n");
912 internal_gl_disabled_extensions[0] = 0;
913 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
914 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
915 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
920 if (default_cx == NULL) {
921 ERR("Could not create default context.\n");
925 /* After context initialize also the list of supported WGL extensions. */
926 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
932 /**********************************************************************/
934 static void process_detach(void)
936 glXDestroyContext(default_display, default_cx);
938 /* Do not leak memory... */
939 wgl_ext_finalize_extensions();
940 if (NULL != internal_gl_extensions) {
941 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
945 /***********************************************************************
946 * OpenGL initialisation routine
948 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
952 case DLL_PROCESS_ATTACH:
953 opengl32_handle = hinst;
954 DisableThreadLibraryCalls(hinst);
955 return process_attach();
956 case DLL_PROCESS_DETACH: