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 {
69 struct wine_glcontext *next;
70 struct wine_glcontext *prev;
72 static Wine_GLContext *context_list;
74 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
77 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
81 static inline void free_context(Wine_GLContext *context)
83 if (context->next != NULL) context->next->prev = context->prev;
84 if (context->prev != NULL) context->prev->next = context->next;
85 else context_list = context->next;
87 HeapFree(GetProcessHeap(), 0, context);
90 static inline Wine_GLContext *alloc_context(void)
94 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
96 ret->next = context_list;
97 if (context_list) context_list->prev = ret;
103 inline static BOOL is_valid_context( Wine_GLContext *ctx )
106 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
107 return (ptr != NULL);
110 /* retrieve the X display to use on a given DC */
111 inline static Display *get_display( HDC hdc )
114 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
116 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
117 sizeof(display), (LPSTR)&display )) display = NULL;
122 /* retrieve the X drawable to use on a given DC */
123 inline static Drawable get_drawable( HDC hdc )
126 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
128 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
129 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
133 /** for use of wglGetCurrentReadDCARB */
134 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
137 for (ret = context_list; ret; ret = ret->next) {
138 if (d == get_drawable( ret->hdc )) {
145 /* retrieve the X drawable to use on a given DC */
146 inline static Font get_font( HDC hdc )
149 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
151 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
152 sizeof(font), (LPSTR)&font )) font = 0;
157 /***********************************************************************
158 * wglCreateContext (OPENGL32.@)
160 HGLRC WINAPI wglCreateContext(HDC hdc)
165 XVisualInfo template;
166 Display *display = get_display( hdc );
168 TRACE("(%p)\n", hdc);
170 /* First, get the visual in use by the X11DRV */
171 if (!display) return 0;
172 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
173 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
176 ERR("NULL visual !!!\n");
177 /* Need to set errors here */
181 /* The context will be allocated in the wglMakeCurrent call */
183 ret = alloc_context();
186 ret->display = display;
189 TRACE(" creating context %p (GL context creation delayed)\n", ret);
193 /***********************************************************************
194 * wglCreateLayerContext (OPENGL32.@)
196 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
198 TRACE("(%p,%d)\n", hdc, iLayerPlane);
200 if (iLayerPlane == 0) {
201 return wglCreateContext(hdc);
203 FIXME(" no handler for layer %d\n", iLayerPlane);
208 /***********************************************************************
209 * wglCopyContext (OPENGL32.@)
211 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
214 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
219 /***********************************************************************
220 * wglDeleteContext (OPENGL32.@)
222 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
224 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
227 TRACE("(%p)\n", hglrc);
230 /* A game (Half Life not to name it) deletes twice the same context,
231 * so make sure it is valid first */
232 if (is_valid_context( ctx ))
234 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
239 WARN("Error deleting context !\n");
240 SetLastError(ERROR_INVALID_HANDLE);
248 /***********************************************************************
249 * wglDescribeLayerPlane (OPENGL32.@)
251 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
255 LPLAYERPLANEDESCRIPTOR plpd) {
256 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
261 /***********************************************************************
262 * wglGetCurrentContext (OPENGL32.@)
264 HGLRC WINAPI wglGetCurrentContext(void) {
271 gl_ctx = glXGetCurrentContext();
272 ret = get_context_from_GLXContext(gl_ctx);
275 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
280 /***********************************************************************
281 * wglGetCurrentDC (OPENGL32.@)
283 HDC WINAPI wglGetCurrentDC(void) {
290 gl_ctx = glXGetCurrentContext();
291 ret = get_context_from_GLXContext(gl_ctx);
295 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
298 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
303 /***********************************************************************
304 * wglGetLayerPaletteEntries (OPENGL32.@)
306 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
310 const COLORREF *pcr) {
311 FIXME("(): stub !\n");
316 /***********************************************************************
317 * wglGetProcAddress (OPENGL32.@)
319 static int compar(const void *elt_a, const void *elt_b) {
320 return strcmp(((const OpenGL_extension *) elt_a)->name,
321 ((const OpenGL_extension *) elt_b)->name);
324 static int wgl_compar(const void *elt_a, const void *elt_b) {
325 return strcmp(((const WGL_extension *) elt_a)->func_name,
326 ((const WGL_extension *) elt_b)->func_name);
329 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
331 OpenGL_extension ext;
332 OpenGL_extension *ext_ret;
334 TRACE("(%s)\n", lpszProc);
336 /* First, look if it's not already defined in the 'standard' OpenGL functions */
337 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
338 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
342 if (p_glXGetProcAddressARB == NULL) {
343 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
347 /* After that, search in the thunks to find the real name of the extension */
348 ext.name = (char *) lpszProc;
349 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
350 extension_registry_size, sizeof(OpenGL_extension), compar);
352 if (ext_ret == NULL) {
353 WGL_extension wgl_ext, *wgl_ext_ret;
355 /* Try to find the function in the WGL extensions ... */
356 wgl_ext.func_name = (char *) lpszProc;
357 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
358 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
360 if (wgl_ext_ret == NULL) {
361 /* Some sanity checks :-) */
363 local_func = p_glXGetProcAddressARB(lpszProc);
365 if (local_func != NULL) {
366 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
370 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
375 if (wgl_ext_ret->func_init != NULL) {
377 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
378 wgl_ext_ret->context)) == NULL) {
379 ret = wgl_ext_ret->func_address;
381 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
385 ret = wgl_ext_ret->func_address;
389 TRACE(" returning WGL function (%p)\n", ret);
394 local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
397 /* After that, look at the extensions defined in the Linux OpenGL library */
398 if (local_func == NULL) {
402 /* Remove the 3 last letters (EXT, ARB, ...).
404 I know that some extensions have more than 3 letters (MESA, NV,
405 INTEL, ...), but this is only a stop-gap measure to fix buggy
406 OpenGL drivers (moreover, it is only useful for old 1.0 apps
407 that query the glBindTextureEXT extension).
409 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
410 buf[strlen(ext_ret->glx_name) - 3] = '\0';
411 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
413 ret = GetProcAddress(opengl32_handle, buf);
415 TRACE(" found function in main OpenGL library (%p) !\n", ret);
417 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
422 TRACE(" returning function (%p)\n", ext_ret->func);
423 *(ext_ret->func_ptr) = local_func;
425 return ext_ret->func;
430 /***********************************************************************
431 * wglMakeCurrent (OPENGL32.@)
433 BOOL WINAPI wglMakeCurrent(HDC hdc,
437 TRACE("(%p,%p)\n", hdc, hglrc);
441 ret = glXMakeCurrent(default_display, None, NULL);
443 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
444 Drawable drawable = get_drawable( hdc );
446 if (ctx->ctx == NULL) {
447 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
448 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
450 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
453 TRACE(" returning %s\n", (ret ? "True" : "False"));
457 /***********************************************************************
458 * wglMakeContextCurrentARB (OPENGL32.@)
460 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
463 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
467 ret = glXMakeCurrent(default_display, None, NULL);
469 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
470 Drawable d_draw = get_drawable( hDrawDC );
471 Drawable d_read = get_drawable( hReadDC );
473 if (ctx->ctx == NULL) {
474 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
475 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
477 ret = glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
481 TRACE(" returning %s\n", (ret ? "True" : "False"));
485 /***********************************************************************
486 * wglGetCurrentReadDCARB (OPENGL32.@)
488 HDC WINAPI wglGetCurrentReadDCARB(void)
496 gl_d = glXGetCurrentReadDrawable();
497 ret = get_hdc_from_Drawable(gl_d);
500 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
506 /***********************************************************************
507 * wglRealizeLayerPalette (OPENGL32.@)
509 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
517 /***********************************************************************
518 * wglSetLayerPaletteEntries (OPENGL32.@)
520 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
524 const COLORREF *pcr) {
525 FIXME("(): stub !\n");
530 /***********************************************************************
531 * wglShareLists (OPENGL32.@)
533 BOOL WINAPI wglShareLists(HGLRC hglrc1,
535 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
536 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
538 TRACE("(%p, %p)\n", org, dest);
540 if (dest->ctx != NULL) {
541 ERR("Could not share display lists, context already created !\n");
544 if (org->ctx == NULL) {
546 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
548 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
552 /* Create the destination context with display lists shared */
553 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
555 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
561 /***********************************************************************
562 * wglSwapLayerBuffers (OPENGL32.@)
564 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
566 TRACE("(%p, %08x)\n", hdc, fuPlanes);
568 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
569 if (!SwapBuffers(hdc)) return FALSE;
570 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
574 WARN("Following layers unhandled : %08x\n", fuPlanes);
580 static BOOL internal_wglUseFontBitmaps(HDC hdc,
584 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
586 /* We are running using client-side rendering fonts... */
590 void *bitmap = NULL, *gl_bitmap = NULL;
594 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
595 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
598 for (glyph = first; glyph < first + count; glyph++) {
599 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
600 int height, width_int;
602 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
603 if (needed_size == GDI_ERROR) {
604 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
607 TRACE(" - needed size : %d\n", needed_size);
610 if (needed_size > size) {
612 HeapFree(GetProcessHeap(), 0, bitmap);
613 HeapFree(GetProcessHeap(), 0, gl_bitmap);
614 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
615 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
617 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
618 if (TRACE_ON(opengl)) {
619 unsigned int height, width, bitmask;
620 unsigned char *bitmap_ = (unsigned char *) bitmap;
622 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
623 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
624 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
625 if (needed_size != 0) {
626 TRACE(" - bitmap : \n");
627 for (height = 0; height < gm.gmBlackBoxY; height++) {
629 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
634 if (*bitmap_ & bitmask)
639 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
645 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
646 * glyph for it to be drawn properly.
648 if (needed_size != 0) {
649 width_int = (gm.gmBlackBoxX + 31) / 32;
650 for (height = 0; height < gm.gmBlackBoxY; height++) {
652 for (width = 0; width < width_int; width++) {
653 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
654 ((int *) bitmap)[height * width_int + width];
660 glNewList(listBase++, GL_COMPILE);
661 if (needed_size != 0) {
662 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
663 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
664 gm.gmCellIncX, gm.gmCellIncY,
667 /* This is the case of 'empty' glyphs like the space character */
668 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
675 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
678 HeapFree(GetProcessHeap(), 0, bitmap);
679 HeapFree(GetProcessHeap(), 0, gl_bitmap);
684 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
687 HeapFree(GetProcessHeap(), 0, bitmap);
688 HeapFree(GetProcessHeap(), 0, gl_bitmap);
692 /***********************************************************************
693 * wglUseFontBitmapsA (OPENGL32.@)
695 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
700 Font fid = get_font( hdc );
702 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
705 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
709 /* I assume that the glyphs are at the same position for X and for Windows */
710 glXUseXFont(fid, first, count, listBase);
715 /***********************************************************************
716 * wglUseFontBitmapsW (OPENGL32.@)
718 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
723 Font fid = get_font( hdc );
725 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
728 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
731 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
734 /* I assume that the glyphs are at the same position for X and for Windows */
735 glXUseXFont(fid, first, count, listBase);
740 /***********************************************************************
741 * wglUseFontOutlinesA (OPENGL32.@)
743 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
750 LPGLYPHMETRICSFLOAT lpgmf) {
751 FIXME("(): stub !\n");
756 const GLubyte * internal_glGetString(GLenum name) {
757 const char* GL_Extensions = NULL;
759 if (GL_EXTENSIONS != name) {
760 return glGetString(name);
763 if (NULL == internal_gl_extensions) {
764 GL_Extensions = glGetString(GL_EXTENSIONS);
766 TRACE("GL_EXTENSIONS reported:\n");
767 if (NULL == GL_Extensions) {
768 ERR("GL_EXTENSIONS returns NULL\n");
771 size_t len = strlen(GL_Extensions);
772 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
774 while (*GL_Extensions != 0x00) {
775 const char* Start = GL_Extensions;
778 memset(ThisExtn, 0x00, sizeof(ThisExtn));
779 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
782 memcpy(ThisExtn, Start, (GL_Extensions - Start));
783 TRACE("- %s:", ThisExtn);
785 /* test if supported API is disabled by config */
786 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
787 strcat(internal_gl_extensions, " ");
788 strcat(internal_gl_extensions, ThisExtn);
791 TRACE(" deactived (by config)\n");
794 if (*GL_Extensions == ' ') GL_Extensions++;
798 return internal_gl_extensions;
802 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
803 include all dependencies
806 #define SONAME_LIBGL "libGL.so"
809 /* This is for brain-dead applications that use OpenGL functions before even
810 creating a rendering context.... */
811 static BOOL process_attach(void)
813 XWindowAttributes win_attr;
816 XVisualInfo template;
818 XVisualInfo *vis = NULL;
819 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
820 HMODULE mod = GetModuleHandleA( "x11drv.dll" );
822 DWORD size = sizeof(internal_gl_disabled_extensions);
827 ERR("X11DRV not loaded. Cannot create default context.\n");
831 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
832 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
835 default_display = get_display( hdc );
837 if (!default_display)
839 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
845 /* Try to get the visual from the Root Window. We can't use the standard (presumably
846 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
847 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
848 with mismatched visuals. Note that the Root Window visual may not be double
849 buffered, so apps actually attempting to render this way may flicker */
850 if (XGetWindowAttributes( default_display, root, &win_attr ))
852 rootVisual = win_attr.visual;
856 /* Get the default visual, since we can't seem to get the attributes from the
857 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
858 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
861 template.visualid = XVisualIDFromVisual(rootVisual);
862 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
863 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
864 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
868 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
869 if (opengl_handle != NULL) {
870 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
871 wine_dlclose(opengl_handle, NULL, 0);
872 if (p_glXGetProcAddressARB == NULL)
873 TRACE("could not find glXGetProcAddressARB in libGL.\n");
876 internal_gl_disabled_extensions[0] = 0;
877 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
878 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, internal_gl_disabled_extensions, &size)) {
879 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
884 /* Initialize also the list of supported WGL extensions. */
885 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
887 if (default_cx == NULL) {
888 ERR("Could not create default context.\n");
894 /**********************************************************************/
896 static void process_detach(void)
898 glXDestroyContext(default_display, default_cx);
900 /* Do not leak memory... */
901 wgl_ext_finalize_extensions();
902 if (NULL != internal_gl_extensions) {
903 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
907 /***********************************************************************
908 * OpenGL initialisation routine
910 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
914 case DLL_PROCESS_ATTACH:
915 opengl32_handle = hinst;
916 DisableThreadLibraryCalls(hinst);
917 return process_attach();
918 case DLL_PROCESS_DETACH: