Implement wglUseFontBitmapsW.
[wine/gsoc_dplay.git] / dlls / opengl32 / wgl.c
blob989f4bbd5b11086c99923e84279414a0c44601d0
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"
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winerror.h"
31 #include "wgl.h"
32 #include "opengl_ext.h"
33 #include "wine/debug.h"
34 #include "wine/port.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
38 /* x11drv GDI escapes */
39 #define X11DRV_ESCAPE 6789
40 enum x11drv_escape_codes
42 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
43 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
44 X11DRV_GET_FONT, /* get current X font for a DC */
47 void (*wine_tsx11_lock_ptr)(void) = NULL;
48 void (*wine_tsx11_unlock_ptr)(void) = NULL;
50 static GLXContext default_cx = NULL;
51 static Display *default_display; /* display to use for default context */
53 static void *(*p_glXGetProcAddressARB)(const GLubyte *);
55 typedef struct wine_glcontext {
56 HDC hdc;
57 Display *display;
58 GLXContext ctx;
59 XVisualInfo *vis;
60 struct wine_glcontext *next;
61 struct wine_glcontext *prev;
62 } Wine_GLContext;
63 static Wine_GLContext *context_list;
65 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
67 Wine_GLContext *ret;
68 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
69 return ret;
72 static inline void free_context(Wine_GLContext *context)
74 if (context->next != NULL) context->next->prev = context->prev;
75 if (context->prev != NULL) context->prev->next = context->next;
76 else context_list = context->next;
78 HeapFree(GetProcessHeap(), 0, context);
81 static inline Wine_GLContext *alloc_context(void)
83 Wine_GLContext *ret;
85 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
87 ret->next = context_list;
88 if (context_list) context_list->prev = ret;
89 context_list = ret;
91 return ret;
94 inline static BOOL is_valid_context( Wine_GLContext *ctx )
96 Wine_GLContext *ptr;
97 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
98 return (ptr != NULL);
101 /* retrieve the X display to use on a given DC */
102 inline static Display *get_display( HDC hdc )
104 Display *display;
105 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
107 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
108 sizeof(display), (LPSTR)&display )) display = NULL;
109 return display;
113 /* retrieve the X drawable to use on a given DC */
114 inline static Drawable get_drawable( HDC hdc )
116 Drawable drawable;
117 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
119 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
120 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
121 return drawable;
125 /* retrieve the X drawable to use on a given DC */
126 inline static Font get_font( HDC hdc )
128 Font font;
129 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
131 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
132 sizeof(font), (LPSTR)&font )) font = 0;
133 return font;
137 /***********************************************************************
138 * wglCreateContext (OPENGL32.@)
140 HGLRC WINAPI wglCreateContext(HDC hdc)
142 XVisualInfo *vis;
143 Wine_GLContext *ret;
144 int num;
145 XVisualInfo template;
146 Display *display = get_display( hdc );
148 TRACE("(%p)\n", hdc);
150 /* First, get the visual in use by the X11DRV */
151 if (!display) return 0;
152 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
153 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
155 if (vis == NULL) {
156 ERR("NULL visual !!!\n");
157 /* Need to set errors here */
158 return NULL;
161 /* The context will be allocated in the wglMakeCurrent call */
162 ENTER_GL();
163 ret = alloc_context();
164 LEAVE_GL();
165 ret->hdc = hdc;
166 ret->display = display;
167 ret->vis = vis;
169 TRACE(" creating context %p (GL context creation delayed)\n", ret);
170 return (HGLRC) ret;
173 /***********************************************************************
174 * wglCreateLayerContext (OPENGL32.@)
176 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
177 int iLayerPlane) {
178 TRACE("(%p,%d)\n", hdc, iLayerPlane);
180 if (iLayerPlane == 0) {
181 return wglCreateContext(hdc);
183 FIXME(" no handler for layer %d\n", iLayerPlane);
185 return NULL;
188 /***********************************************************************
189 * wglCopyContext (OPENGL32.@)
191 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
192 HGLRC hglrcDst,
193 UINT mask) {
194 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
196 return FALSE;
199 /***********************************************************************
200 * wglDeleteContext (OPENGL32.@)
202 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
204 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
205 BOOL ret = TRUE;
207 TRACE("(%p)\n", hglrc);
209 ENTER_GL();
210 /* A game (Half Life not to name it) deletes twice the same context,
211 * so make sure it is valid first */
212 if (is_valid_context( ctx ))
214 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
215 free_context(ctx);
217 else
219 WARN("Error deleting context !\n");
220 SetLastError(ERROR_INVALID_HANDLE);
221 ret = FALSE;
223 LEAVE_GL();
225 return ret;
228 /***********************************************************************
229 * wglDescribeLayerPlane (OPENGL32.@)
231 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
232 int iPixelFormat,
233 int iLayerPlane,
234 UINT nBytes,
235 LPLAYERPLANEDESCRIPTOR plpd) {
236 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
238 return FALSE;
241 /***********************************************************************
242 * wglGetCurrentContext (OPENGL32.@)
244 HGLRC WINAPI wglGetCurrentContext(void) {
245 GLXContext gl_ctx;
246 Wine_GLContext *ret;
248 TRACE("()\n");
250 ENTER_GL();
251 gl_ctx = glXGetCurrentContext();
252 ret = get_context_from_GLXContext(gl_ctx);
253 LEAVE_GL();
255 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
257 return ret;
260 /***********************************************************************
261 * wglGetCurrentDC (OPENGL32.@)
263 HDC WINAPI wglGetCurrentDC(void) {
264 GLXContext gl_ctx;
265 Wine_GLContext *ret;
267 TRACE("()\n");
269 ENTER_GL();
270 gl_ctx = glXGetCurrentContext();
271 ret = get_context_from_GLXContext(gl_ctx);
272 LEAVE_GL();
274 if (ret) {
275 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
276 return ret->hdc;
277 } else {
278 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
279 return 0;
283 /***********************************************************************
284 * wglGetLayerPaletteEntries (OPENGL32.@)
286 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
287 int iLayerPlane,
288 int iStart,
289 int cEntries,
290 const COLORREF *pcr) {
291 FIXME("(): stub !\n");
293 return 0;
296 /***********************************************************************
297 * wglGetProcAddress (OPENGL32.@)
299 static int compar(const void *elt_a, const void *elt_b) {
300 return strcmp(((OpenGL_extension *) elt_a)->name,
301 ((OpenGL_extension *) elt_b)->name);
304 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
305 void *local_func;
306 static HMODULE hm = 0;
307 OpenGL_extension ext;
308 OpenGL_extension *ext_ret;
311 TRACE("(%s)\n", lpszProc);
313 if (hm == 0)
314 hm = GetModuleHandleA("opengl32");
316 /* First, look if it's not already defined in the 'standard' OpenGL functions */
317 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
318 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
319 return local_func;
322 if (p_glXGetProcAddressARB == NULL) {
323 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
324 return NULL;
327 /* After that, search in the thunks to find the real name of the extension */
328 ext.name = (char *) lpszProc;
329 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
330 extension_registry_size, sizeof(OpenGL_extension), compar);
332 if (ext_ret == NULL) {
333 /* Some sanity checks :-) */
334 ENTER_GL();
335 local_func = p_glXGetProcAddressARB(lpszProc);
336 LEAVE_GL();
337 if (local_func != NULL) {
338 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
339 return NULL;
342 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
343 return NULL;
344 } else {
345 ENTER_GL();
346 local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
347 LEAVE_GL();
349 /* After that, look at the extensions defined in the Linux OpenGL library */
350 if (local_func == NULL) {
351 char buf[256];
352 void *ret = NULL;
354 /* Remove the 3 last letters (EXT, ARB, ...).
356 I know that some extensions have more than 3 letters (MESA, NV,
357 INTEL, ...), but this is only a stop-gap measure to fix buggy
358 OpenGL drivers (moreover, it is only useful for old 1.0 apps
359 that query the glBindTextureEXT extension).
361 strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
362 buf[strlen(ext_ret->glx_name) - 3] = '\0';
363 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
365 ret = GetProcAddress(hm, buf);
366 if (ret != NULL) {
367 TRACE(" found function in main OpenGL library (%p) !\n", ret);
368 } else {
369 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
372 return ret;
373 } else {
374 TRACE(" returning function (%p)\n", ext_ret->func);
375 *(ext_ret->func_ptr) = local_func;
377 return ext_ret->func;
382 /***********************************************************************
383 * wglMakeCurrent (OPENGL32.@)
385 BOOL WINAPI wglMakeCurrent(HDC hdc,
386 HGLRC hglrc) {
387 BOOL ret;
389 TRACE("(%p,%p)\n", hdc, hglrc);
391 ENTER_GL();
392 if (hglrc == NULL) {
393 ret = glXMakeCurrent(default_display, None, NULL);
394 } else {
395 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
396 Drawable drawable = get_drawable( hdc );
398 if (ctx->ctx == NULL) {
399 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
400 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
402 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
404 LEAVE_GL();
405 TRACE(" returning %s\n", (ret ? "True" : "False"));
406 return ret;
409 /***********************************************************************
410 * wglRealizeLayerPalette (OPENGL32.@)
412 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
413 int iLayerPlane,
414 BOOL bRealize) {
415 FIXME("()\n");
417 return FALSE;
420 /***********************************************************************
421 * wglSetLayerPaletteEntries (OPENGL32.@)
423 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
424 int iLayerPlane,
425 int iStart,
426 int cEntries,
427 const COLORREF *pcr) {
428 FIXME("(): stub !\n");
430 return 0;
433 /***********************************************************************
434 * wglShareLists (OPENGL32.@)
436 BOOL WINAPI wglShareLists(HGLRC hglrc1,
437 HGLRC hglrc2) {
438 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
439 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
441 TRACE("(%p, %p)\n", org, dest);
443 if (dest->ctx != NULL) {
444 ERR("Could not share display lists, context already created !\n");
445 return FALSE;
446 } else {
447 if (org->ctx == NULL) {
448 ENTER_GL();
449 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
450 LEAVE_GL();
451 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
454 ENTER_GL();
455 /* Create the destination context with display lists shared */
456 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
457 LEAVE_GL();
458 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
461 return TRUE;
464 /***********************************************************************
465 * wglSwapLayerBuffers (OPENGL32.@)
467 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
468 UINT fuPlanes) {
469 TRACE("(%p, %08x)\n", hdc, fuPlanes);
471 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
472 if (!SwapBuffers(hdc)) return FALSE;
473 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
476 if (fuPlanes) {
477 WARN("Following layers unhandled : %08x\n", fuPlanes);
480 return TRUE;
483 static BOOL internal_wglUseFontBitmaps(HDC hdc,
484 DWORD first,
485 DWORD count,
486 DWORD listBase,
487 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
489 /* We are running using client-side rendering fonts... */
490 GLYPHMETRICS gm;
491 static const MAT2 id = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
492 int glyph;
493 int size = 0;
494 void *bitmap = NULL, *gl_bitmap = NULL;
495 int org_alignment;
497 ENTER_GL();
498 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
499 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
500 LEAVE_GL();
502 for (glyph = first; glyph < first + count; glyph++) {
503 int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &id);
504 int height, width_int;
506 if (needed_size == GDI_ERROR) goto error;
507 if (needed_size > size) {
508 size = needed_size;
509 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
510 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
511 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
512 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
514 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &id) == GDI_ERROR) goto error;
515 if (TRACE_ON(opengl)) {
516 unsigned int height, width, bitmask;
517 unsigned char *bitmap_ = (unsigned char *) bitmap;
519 DPRINTF("Glyph : %d\n", glyph);
520 DPRINTF(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
521 DPRINTF(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
522 DPRINTF(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
523 DPRINTF(" - size : %d\n", needed_size);
524 DPRINTF(" - bitmap : \n");
525 for (height = 0; height < gm.gmBlackBoxY; height++) {
526 DPRINTF(" ");
527 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
528 if (bitmask == 0) {
529 bitmap_ += 1;
530 bitmask = 0x80;
532 if (*bitmap_ & bitmask)
533 DPRINTF("*");
534 else
535 DPRINTF(" ");
537 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
538 DPRINTF("\n");
542 /* For some obscure reasons, I seem to need to rotate the glyph for OpenGL to be happy.
543 As Wine does not seem to support the MAT2 field, I need to do it myself.... */
544 width_int = (gm.gmBlackBoxX + 31) / 32;
545 for (height = 0; height < gm.gmBlackBoxY; height++) {
546 int width;
547 for (width = 0; width < width_int; width++) {
548 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
549 ((int *) bitmap)[height * width_int + width];
553 ENTER_GL();
554 glNewList(listBase++, GL_COMPILE);
555 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmptGlyphOrigin.x,
556 gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap);
557 glEndList();
558 LEAVE_GL();
561 ENTER_GL();
562 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
563 LEAVE_GL();
565 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
566 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
567 return TRUE;
569 error:
570 ENTER_GL();
571 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
572 LEAVE_GL();
574 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
575 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
576 return FALSE;
579 /***********************************************************************
580 * wglUseFontBitmapsA (OPENGL32.@)
582 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
583 DWORD first,
584 DWORD count,
585 DWORD listBase)
587 Font fid = get_font( hdc );
589 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
591 if (fid == 0) {
592 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
595 ENTER_GL();
596 /* I assume that the glyphs are at the same position for X and for Windows */
597 glXUseXFont(fid, first, count, listBase);
598 LEAVE_GL();
599 return TRUE;
602 /***********************************************************************
603 * wglUseFontBitmapsW (OPENGL32.@)
605 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
606 DWORD first,
607 DWORD count,
608 DWORD listBase)
610 Font fid = get_font( hdc );
612 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
614 if (fid == 0) {
615 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
618 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
620 ENTER_GL();
621 /* I assume that the glyphs are at the same position for X and for Windows */
622 glXUseXFont(fid, first, count, listBase);
623 LEAVE_GL();
624 return TRUE;
627 /***********************************************************************
628 * wglUseFontOutlinesA (OPENGL32.@)
630 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
631 DWORD first,
632 DWORD count,
633 DWORD listBase,
634 FLOAT deviation,
635 FLOAT extrusion,
636 int format,
637 LPGLYPHMETRICSFLOAT lpgmf) {
638 FIXME("(): stub !\n");
640 return FALSE;
643 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
644 include all dependencies
646 #ifndef SONAME_LIBGL
647 #define SONAME_LIBGL "libGL.so"
648 #endif
650 /* This is for brain-dead applications that use OpenGL functions before even
651 creating a rendering context.... */
652 static BOOL process_attach(void)
654 XWindowAttributes win_attr;
655 Visual *rootVisual;
656 int num;
657 XVisualInfo template;
658 HDC hdc;
659 XVisualInfo *vis = NULL;
660 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
661 HMODULE mod = GetModuleHandleA( "x11drv.dll" );
662 void *opengl_handle;
664 if (!root || !mod)
666 ERR("X11DRV not loaded. Cannot create default context.\n");
667 return FALSE;
670 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
671 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
673 hdc = GetDC(0);
674 default_display = get_display( hdc );
675 ReleaseDC( 0, hdc );
676 if (!default_display)
678 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
679 return FALSE;
682 ENTER_GL();
684 /* Try to get the visual from the Root Window. We can't use the standard (presumably
685 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
686 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
687 with mismatched visuals. Note that the Root Window visual may not be double
688 buffered, so apps actually attempting to render this way may flicker */
689 if (XGetWindowAttributes( default_display, root, &win_attr ))
691 rootVisual = win_attr.visual;
693 else
695 /* Get the default visual, since we can't seem to get the attributes from the
696 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
697 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
700 template.visualid = XVisualIDFromVisual(rootVisual);
701 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
702 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
703 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
704 XFree(vis);
705 LEAVE_GL();
707 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
708 if (opengl_handle != NULL) {
709 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
710 wine_dlclose(opengl_handle, NULL, 0);
711 if (p_glXGetProcAddressARB == NULL)
712 TRACE("could not find glXGetProcAddressARB in libGL.\n");
715 if (default_cx == NULL) {
716 ERR("Could not create default context.\n");
718 return TRUE;
721 /**********************************************************************/
723 /* Some WGL extensions... */
724 static const char *WGL_extensions = "WGL_ARB_extensions_string WGL_EXT_extensions_string";
726 /**********************************************************************/
728 const char * WINAPI wglGetExtensionsStringEXT(void) {
729 TRACE("() returning \"%s\"\n", WGL_extensions);
731 return WGL_extensions;
734 /**********************************************************************/
736 static void process_detach(void)
738 glXDestroyContext(default_display, default_cx);
741 /***********************************************************************
742 * wglGetExtensionsStringARB(OPENGL32.@)
744 const char * WINAPI wglGetExtensionsStringARB(HDC hdc) {
746 return wglGetExtensionsStringEXT();
750 /***********************************************************************
751 * OpenGL initialisation routine
753 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
755 switch(reason)
757 case DLL_PROCESS_ATTACH:
758 DisableThreadLibraryCalls(hinst);
759 return process_attach();
760 case DLL_PROCESS_DETACH:
761 process_detach();
762 break;
764 return TRUE;