There is no need for a private heap in comctl32, memory allocations
[wine/testsucceed.git] / dlls / opengl32 / wgl.c
blobe87f5ebe60e40e23fe64785eaab8421853f96978
1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "config.h"
21 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winerror.h"
32 #include "wgl.h"
33 #include "opengl_ext.h"
34 #include "wine/library.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
39 /* x11drv GDI escapes */
40 #define X11DRV_ESCAPE 6789
41 enum x11drv_escape_codes
43 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
44 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
45 X11DRV_GET_FONT, /* get current X font for a DC */
48 void (*wine_tsx11_lock_ptr)(void) = NULL;
49 void (*wine_tsx11_unlock_ptr)(void) = NULL;
51 static GLXContext default_cx = NULL;
52 static Display *default_display; /* display to use for default context */
54 static void *(*p_glXGetProcAddressARB)(const GLubyte *);
56 typedef struct wine_glcontext {
57 HDC hdc;
58 Display *display;
59 GLXContext ctx;
60 XVisualInfo *vis;
61 struct wine_glcontext *next;
62 struct wine_glcontext *prev;
63 } Wine_GLContext;
64 static Wine_GLContext *context_list;
66 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
68 Wine_GLContext *ret;
69 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
70 return ret;
73 static inline void free_context(Wine_GLContext *context)
75 if (context->next != NULL) context->next->prev = context->prev;
76 if (context->prev != NULL) context->prev->next = context->next;
77 else context_list = context->next;
79 HeapFree(GetProcessHeap(), 0, context);
82 static inline Wine_GLContext *alloc_context(void)
84 Wine_GLContext *ret;
86 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
88 ret->next = context_list;
89 if (context_list) context_list->prev = ret;
90 context_list = ret;
92 return ret;
95 inline static BOOL is_valid_context( Wine_GLContext *ctx )
97 Wine_GLContext *ptr;
98 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
99 return (ptr != NULL);
102 /* retrieve the X display to use on a given DC */
103 inline static Display *get_display( HDC hdc )
105 Display *display;
106 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
108 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
109 sizeof(display), (LPSTR)&display )) display = NULL;
110 return display;
114 /* retrieve the X drawable to use on a given DC */
115 inline static Drawable get_drawable( HDC hdc )
117 Drawable drawable;
118 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
120 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
121 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
122 return drawable;
126 /* retrieve the X drawable to use on a given DC */
127 inline static Font get_font( HDC hdc )
129 Font font;
130 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
132 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
133 sizeof(font), (LPSTR)&font )) font = 0;
134 return font;
138 /***********************************************************************
139 * wglCreateContext (OPENGL32.@)
141 HGLRC WINAPI wglCreateContext(HDC hdc)
143 XVisualInfo *vis;
144 Wine_GLContext *ret;
145 int num;
146 XVisualInfo template;
147 Display *display = get_display( hdc );
149 TRACE("(%p)\n", hdc);
151 /* First, get the visual in use by the X11DRV */
152 if (!display) return 0;
153 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
154 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
156 if (vis == NULL) {
157 ERR("NULL visual !!!\n");
158 /* Need to set errors here */
159 return NULL;
162 /* The context will be allocated in the wglMakeCurrent call */
163 ENTER_GL();
164 ret = alloc_context();
165 LEAVE_GL();
166 ret->hdc = hdc;
167 ret->display = display;
168 ret->vis = vis;
170 TRACE(" creating context %p (GL context creation delayed)\n", ret);
171 return (HGLRC) ret;
174 /***********************************************************************
175 * wglCreateLayerContext (OPENGL32.@)
177 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
178 int iLayerPlane) {
179 TRACE("(%p,%d)\n", hdc, iLayerPlane);
181 if (iLayerPlane == 0) {
182 return wglCreateContext(hdc);
184 FIXME(" no handler for layer %d\n", iLayerPlane);
186 return NULL;
189 /***********************************************************************
190 * wglCopyContext (OPENGL32.@)
192 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
193 HGLRC hglrcDst,
194 UINT mask) {
195 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
197 return FALSE;
200 /***********************************************************************
201 * wglDeleteContext (OPENGL32.@)
203 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
205 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
206 BOOL ret = TRUE;
208 TRACE("(%p)\n", hglrc);
210 ENTER_GL();
211 /* A game (Half Life not to name it) deletes twice the same context,
212 * so make sure it is valid first */
213 if (is_valid_context( ctx ))
215 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
216 free_context(ctx);
218 else
220 WARN("Error deleting context !\n");
221 SetLastError(ERROR_INVALID_HANDLE);
222 ret = FALSE;
224 LEAVE_GL();
226 return ret;
229 /***********************************************************************
230 * wglDescribeLayerPlane (OPENGL32.@)
232 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
233 int iPixelFormat,
234 int iLayerPlane,
235 UINT nBytes,
236 LPLAYERPLANEDESCRIPTOR plpd) {
237 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
239 return FALSE;
242 /***********************************************************************
243 * wglGetCurrentContext (OPENGL32.@)
245 HGLRC WINAPI wglGetCurrentContext(void) {
246 GLXContext gl_ctx;
247 Wine_GLContext *ret;
249 TRACE("()\n");
251 ENTER_GL();
252 gl_ctx = glXGetCurrentContext();
253 ret = get_context_from_GLXContext(gl_ctx);
254 LEAVE_GL();
256 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
258 return ret;
261 /***********************************************************************
262 * wglGetCurrentDC (OPENGL32.@)
264 HDC WINAPI wglGetCurrentDC(void) {
265 GLXContext gl_ctx;
266 Wine_GLContext *ret;
268 TRACE("()\n");
270 ENTER_GL();
271 gl_ctx = glXGetCurrentContext();
272 ret = get_context_from_GLXContext(gl_ctx);
273 LEAVE_GL();
275 if (ret) {
276 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
277 return ret->hdc;
278 } else {
279 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
280 return 0;
284 /***********************************************************************
285 * wglGetLayerPaletteEntries (OPENGL32.@)
287 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
288 int iLayerPlane,
289 int iStart,
290 int cEntries,
291 const COLORREF *pcr) {
292 FIXME("(): stub !\n");
294 return 0;
297 /***********************************************************************
298 * wglGetProcAddress (OPENGL32.@)
300 static int compar(const void *elt_a, const void *elt_b) {
301 return strcmp(((OpenGL_extension *) elt_a)->name,
302 ((OpenGL_extension *) elt_b)->name);
305 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
306 void *local_func;
307 static HMODULE hm = 0;
308 OpenGL_extension ext;
309 OpenGL_extension *ext_ret;
312 TRACE("(%s)\n", lpszProc);
314 if (hm == 0)
315 hm = GetModuleHandleA("opengl32");
317 /* First, look if it's not already defined in the 'standard' OpenGL functions */
318 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
319 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
320 return local_func;
323 if (p_glXGetProcAddressARB == NULL) {
324 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
325 return NULL;
328 /* After that, search in the thunks to find the real name of the extension */
329 ext.name = (char *) lpszProc;
330 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
331 extension_registry_size, sizeof(OpenGL_extension), compar);
333 if (ext_ret == NULL) {
334 /* Some sanity checks :-) */
335 ENTER_GL();
336 local_func = p_glXGetProcAddressARB(lpszProc);
337 LEAVE_GL();
338 if (local_func != NULL) {
339 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
340 return NULL;
343 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
344 return NULL;
345 } else {
346 ENTER_GL();
347 local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
348 LEAVE_GL();
350 /* After that, look at the extensions defined in the Linux OpenGL library */
351 if (local_func == NULL) {
352 char buf[256];
353 void *ret = NULL;
355 /* Remove the 3 last letters (EXT, ARB, ...).
357 I know that some extensions have more than 3 letters (MESA, NV,
358 INTEL, ...), but this is only a stop-gap measure to fix buggy
359 OpenGL drivers (moreover, it is only useful for old 1.0 apps
360 that query the glBindTextureEXT extension).
362 strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
363 buf[strlen(ext_ret->glx_name) - 3] = '\0';
364 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
366 ret = GetProcAddress(hm, buf);
367 if (ret != NULL) {
368 TRACE(" found function in main OpenGL library (%p) !\n", ret);
369 } else {
370 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
373 return ret;
374 } else {
375 TRACE(" returning function (%p)\n", ext_ret->func);
376 *(ext_ret->func_ptr) = local_func;
378 return ext_ret->func;
383 /***********************************************************************
384 * wglMakeCurrent (OPENGL32.@)
386 BOOL WINAPI wglMakeCurrent(HDC hdc,
387 HGLRC hglrc) {
388 BOOL ret;
390 TRACE("(%p,%p)\n", hdc, hglrc);
392 ENTER_GL();
393 if (hglrc == NULL) {
394 ret = glXMakeCurrent(default_display, None, NULL);
395 } else {
396 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
397 Drawable drawable = get_drawable( hdc );
399 if (ctx->ctx == NULL) {
400 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
401 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
403 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
405 LEAVE_GL();
406 TRACE(" returning %s\n", (ret ? "True" : "False"));
407 return ret;
410 /***********************************************************************
411 * wglRealizeLayerPalette (OPENGL32.@)
413 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
414 int iLayerPlane,
415 BOOL bRealize) {
416 FIXME("()\n");
418 return FALSE;
421 /***********************************************************************
422 * wglSetLayerPaletteEntries (OPENGL32.@)
424 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
425 int iLayerPlane,
426 int iStart,
427 int cEntries,
428 const COLORREF *pcr) {
429 FIXME("(): stub !\n");
431 return 0;
434 /***********************************************************************
435 * wglShareLists (OPENGL32.@)
437 BOOL WINAPI wglShareLists(HGLRC hglrc1,
438 HGLRC hglrc2) {
439 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
440 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
442 TRACE("(%p, %p)\n", org, dest);
444 if (dest->ctx != NULL) {
445 ERR("Could not share display lists, context already created !\n");
446 return FALSE;
447 } else {
448 if (org->ctx == NULL) {
449 ENTER_GL();
450 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
451 LEAVE_GL();
452 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
455 ENTER_GL();
456 /* Create the destination context with display lists shared */
457 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
458 LEAVE_GL();
459 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
462 return TRUE;
465 /***********************************************************************
466 * wglSwapLayerBuffers (OPENGL32.@)
468 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
469 UINT fuPlanes) {
470 TRACE("(%p, %08x)\n", hdc, fuPlanes);
472 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
473 if (!SwapBuffers(hdc)) return FALSE;
474 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
477 if (fuPlanes) {
478 WARN("Following layers unhandled : %08x\n", fuPlanes);
481 return TRUE;
484 static BOOL internal_wglUseFontBitmaps(HDC hdc,
485 DWORD first,
486 DWORD count,
487 DWORD listBase,
488 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
490 /* We are running using client-side rendering fonts... */
491 GLYPHMETRICS gm;
492 static const MAT2 id = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
493 int glyph;
494 int size = 0;
495 void *bitmap = NULL, *gl_bitmap = NULL;
496 int org_alignment;
498 ENTER_GL();
499 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
500 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
501 LEAVE_GL();
503 for (glyph = first; glyph < first + count; glyph++) {
504 int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &id);
505 int height, width_int;
507 if (needed_size == GDI_ERROR) goto error;
508 if (needed_size > size) {
509 size = needed_size;
510 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
511 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
512 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
513 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
515 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &id) == GDI_ERROR) goto error;
516 if (TRACE_ON(opengl)) {
517 unsigned int height, width, bitmask;
518 unsigned char *bitmap_ = (unsigned char *) bitmap;
520 DPRINTF("Glyph : %d\n", glyph);
521 DPRINTF(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
522 DPRINTF(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
523 DPRINTF(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
524 DPRINTF(" - size : %d\n", needed_size);
525 DPRINTF(" - bitmap : \n");
526 for (height = 0; height < gm.gmBlackBoxY; height++) {
527 DPRINTF(" ");
528 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
529 if (bitmask == 0) {
530 bitmap_ += 1;
531 bitmask = 0x80;
533 if (*bitmap_ & bitmask)
534 DPRINTF("*");
535 else
536 DPRINTF(" ");
538 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
539 DPRINTF("\n");
543 /* For some obscure reasons, I seem to need to rotate the glyph for OpenGL to be happy.
544 As Wine does not seem to support the MAT2 field, I need to do it myself.... */
545 width_int = (gm.gmBlackBoxX + 31) / 32;
546 for (height = 0; height < gm.gmBlackBoxY; height++) {
547 int width;
548 for (width = 0; width < width_int; width++) {
549 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
550 ((int *) bitmap)[height * width_int + width];
554 ENTER_GL();
555 glNewList(listBase++, GL_COMPILE);
556 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmptGlyphOrigin.x,
557 gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap);
558 glEndList();
559 LEAVE_GL();
562 ENTER_GL();
563 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
564 LEAVE_GL();
566 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
567 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
568 return TRUE;
570 error:
571 ENTER_GL();
572 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
573 LEAVE_GL();
575 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
576 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
577 return FALSE;
580 /***********************************************************************
581 * wglUseFontBitmapsA (OPENGL32.@)
583 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
584 DWORD first,
585 DWORD count,
586 DWORD listBase)
588 Font fid = get_font( hdc );
590 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
592 if (fid == 0) {
593 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
596 ENTER_GL();
597 /* I assume that the glyphs are at the same position for X and for Windows */
598 glXUseXFont(fid, first, count, listBase);
599 LEAVE_GL();
600 return TRUE;
603 /***********************************************************************
604 * wglUseFontBitmapsW (OPENGL32.@)
606 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
607 DWORD first,
608 DWORD count,
609 DWORD listBase)
611 Font fid = get_font( hdc );
613 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
615 if (fid == 0) {
616 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
619 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
621 ENTER_GL();
622 /* I assume that the glyphs are at the same position for X and for Windows */
623 glXUseXFont(fid, first, count, listBase);
624 LEAVE_GL();
625 return TRUE;
628 /***********************************************************************
629 * wglUseFontOutlinesA (OPENGL32.@)
631 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
632 DWORD first,
633 DWORD count,
634 DWORD listBase,
635 FLOAT deviation,
636 FLOAT extrusion,
637 int format,
638 LPGLYPHMETRICSFLOAT lpgmf) {
639 FIXME("(): stub !\n");
641 return FALSE;
644 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
645 include all dependencies
647 #ifndef SONAME_LIBGL
648 #define SONAME_LIBGL "libGL.so"
649 #endif
651 /* This is for brain-dead applications that use OpenGL functions before even
652 creating a rendering context.... */
653 static BOOL process_attach(void)
655 XWindowAttributes win_attr;
656 Visual *rootVisual;
657 int num;
658 XVisualInfo template;
659 HDC hdc;
660 XVisualInfo *vis = NULL;
661 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
662 HMODULE mod = GetModuleHandleA( "x11drv.dll" );
663 void *opengl_handle;
665 if (!root || !mod)
667 ERR("X11DRV not loaded. Cannot create default context.\n");
668 return FALSE;
671 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
672 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
674 hdc = GetDC(0);
675 default_display = get_display( hdc );
676 ReleaseDC( 0, hdc );
677 if (!default_display)
679 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
680 return FALSE;
683 ENTER_GL();
685 /* Try to get the visual from the Root Window. We can't use the standard (presumably
686 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
687 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
688 with mismatched visuals. Note that the Root Window visual may not be double
689 buffered, so apps actually attempting to render this way may flicker */
690 if (XGetWindowAttributes( default_display, root, &win_attr ))
692 rootVisual = win_attr.visual;
694 else
696 /* Get the default visual, since we can't seem to get the attributes from the
697 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
698 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
701 template.visualid = XVisualIDFromVisual(rootVisual);
702 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
703 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
704 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
705 XFree(vis);
706 LEAVE_GL();
708 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
709 if (opengl_handle != NULL) {
710 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
711 wine_dlclose(opengl_handle, NULL, 0);
712 if (p_glXGetProcAddressARB == NULL)
713 TRACE("could not find glXGetProcAddressARB in libGL.\n");
716 if (default_cx == NULL) {
717 ERR("Could not create default context.\n");
719 return TRUE;
722 /**********************************************************************/
724 /* Some WGL extensions... */
725 static const char *WGL_extensions = "WGL_ARB_extensions_string WGL_EXT_extensions_string";
727 /**********************************************************************/
729 const char * WINAPI wglGetExtensionsStringEXT(void) {
730 TRACE("() returning \"%s\"\n", WGL_extensions);
732 return WGL_extensions;
735 /**********************************************************************/
737 static void process_detach(void)
739 glXDestroyContext(default_display, default_cx);
742 /***********************************************************************
743 * wglGetExtensionsStringARB(OPENGL32.@)
745 const char * WINAPI wglGetExtensionsStringARB(HDC hdc) {
747 return wglGetExtensionsStringEXT();
751 /***********************************************************************
752 * OpenGL initialisation routine
754 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
756 switch(reason)
758 case DLL_PROCESS_ATTACH:
759 DisableThreadLibraryCalls(hinst);
760 return process_attach();
761 case DLL_PROCESS_DETACH:
762 process_detach();
763 break;
765 return TRUE;