You can make an invisible window the active window.
[wine/dcerpc.git] / dlls / opengl32 / wgl.c
blobce627f9f6aeee8ad750922020cc20d059d1dea8d
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 "wgl_ext.h"
34 #include "opengl_ext.h"
35 #include "wine/library.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
40 /* x11drv GDI escapes */
41 #define X11DRV_ESCAPE 6789
42 enum x11drv_escape_codes
44 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
45 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
46 X11DRV_GET_FONT, /* get current X font for a DC */
49 void (*wine_tsx11_lock_ptr)(void) = NULL;
50 void (*wine_tsx11_unlock_ptr)(void) = NULL;
52 static GLXContext default_cx = NULL;
53 static Display *default_display; /* display to use for default context */
55 static HMODULE opengl32_handle;
57 static void *(*p_glXGetProcAddressARB)(const GLubyte *);
59 typedef struct wine_glcontext {
60 HDC hdc;
61 Display *display;
62 GLXContext ctx;
63 XVisualInfo *vis;
64 struct wine_glcontext *next;
65 struct wine_glcontext *prev;
66 } Wine_GLContext;
67 static Wine_GLContext *context_list;
69 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
71 Wine_GLContext *ret;
72 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
73 return ret;
76 static inline void free_context(Wine_GLContext *context)
78 if (context->next != NULL) context->next->prev = context->prev;
79 if (context->prev != NULL) context->prev->next = context->next;
80 else context_list = context->next;
82 HeapFree(GetProcessHeap(), 0, context);
85 static inline Wine_GLContext *alloc_context(void)
87 Wine_GLContext *ret;
89 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
91 ret->next = context_list;
92 if (context_list) context_list->prev = ret;
93 context_list = ret;
95 return ret;
98 inline static BOOL is_valid_context( Wine_GLContext *ctx )
100 Wine_GLContext *ptr;
101 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
102 return (ptr != NULL);
105 /* retrieve the X display to use on a given DC */
106 inline static Display *get_display( HDC hdc )
108 Display *display;
109 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
111 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
112 sizeof(display), (LPSTR)&display )) display = NULL;
113 return display;
117 /* retrieve the X drawable to use on a given DC */
118 inline static Drawable get_drawable( HDC hdc )
120 Drawable drawable;
121 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
123 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
124 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
125 return drawable;
129 /* retrieve the X drawable to use on a given DC */
130 inline static Font get_font( HDC hdc )
132 Font font;
133 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
135 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
136 sizeof(font), (LPSTR)&font )) font = 0;
137 return font;
141 /***********************************************************************
142 * wglCreateContext (OPENGL32.@)
144 HGLRC WINAPI wglCreateContext(HDC hdc)
146 XVisualInfo *vis;
147 Wine_GLContext *ret;
148 int num;
149 XVisualInfo template;
150 Display *display = get_display( hdc );
152 TRACE("(%p)\n", hdc);
154 /* First, get the visual in use by the X11DRV */
155 if (!display) return 0;
156 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
157 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
159 if (vis == NULL) {
160 ERR("NULL visual !!!\n");
161 /* Need to set errors here */
162 return NULL;
165 /* The context will be allocated in the wglMakeCurrent call */
166 ENTER_GL();
167 ret = alloc_context();
168 LEAVE_GL();
169 ret->hdc = hdc;
170 ret->display = display;
171 ret->vis = vis;
173 TRACE(" creating context %p (GL context creation delayed)\n", ret);
174 return (HGLRC) ret;
177 /***********************************************************************
178 * wglCreateLayerContext (OPENGL32.@)
180 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
181 int iLayerPlane) {
182 TRACE("(%p,%d)\n", hdc, iLayerPlane);
184 if (iLayerPlane == 0) {
185 return wglCreateContext(hdc);
187 FIXME(" no handler for layer %d\n", iLayerPlane);
189 return NULL;
192 /***********************************************************************
193 * wglCopyContext (OPENGL32.@)
195 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
196 HGLRC hglrcDst,
197 UINT mask) {
198 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
200 return FALSE;
203 /***********************************************************************
204 * wglDeleteContext (OPENGL32.@)
206 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
208 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
209 BOOL ret = TRUE;
211 TRACE("(%p)\n", hglrc);
213 ENTER_GL();
214 /* A game (Half Life not to name it) deletes twice the same context,
215 * so make sure it is valid first */
216 if (is_valid_context( ctx ))
218 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
219 free_context(ctx);
221 else
223 WARN("Error deleting context !\n");
224 SetLastError(ERROR_INVALID_HANDLE);
225 ret = FALSE;
227 LEAVE_GL();
229 return ret;
232 /***********************************************************************
233 * wglDescribeLayerPlane (OPENGL32.@)
235 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
236 int iPixelFormat,
237 int iLayerPlane,
238 UINT nBytes,
239 LPLAYERPLANEDESCRIPTOR plpd) {
240 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
242 return FALSE;
245 /***********************************************************************
246 * wglGetCurrentContext (OPENGL32.@)
248 HGLRC WINAPI wglGetCurrentContext(void) {
249 GLXContext gl_ctx;
250 Wine_GLContext *ret;
252 TRACE("()\n");
254 ENTER_GL();
255 gl_ctx = glXGetCurrentContext();
256 ret = get_context_from_GLXContext(gl_ctx);
257 LEAVE_GL();
259 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
261 return (HGLRC)ret;
264 /***********************************************************************
265 * wglGetCurrentDC (OPENGL32.@)
267 HDC WINAPI wglGetCurrentDC(void) {
268 GLXContext gl_ctx;
269 Wine_GLContext *ret;
271 TRACE("()\n");
273 ENTER_GL();
274 gl_ctx = glXGetCurrentContext();
275 ret = get_context_from_GLXContext(gl_ctx);
276 LEAVE_GL();
278 if (ret) {
279 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
280 return ret->hdc;
281 } else {
282 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
283 return 0;
287 /***********************************************************************
288 * wglGetLayerPaletteEntries (OPENGL32.@)
290 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
291 int iLayerPlane,
292 int iStart,
293 int cEntries,
294 const COLORREF *pcr) {
295 FIXME("(): stub !\n");
297 return 0;
300 /***********************************************************************
301 * wglGetProcAddress (OPENGL32.@)
303 static int compar(const void *elt_a, const void *elt_b) {
304 return strcmp(((const OpenGL_extension *) elt_a)->name,
305 ((const OpenGL_extension *) elt_b)->name);
308 static int wgl_compar(const void *elt_a, const void *elt_b) {
309 return strcmp(((const WGL_extension *) elt_a)->func_name,
310 ((const WGL_extension *) elt_b)->func_name);
313 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
314 void *local_func;
315 OpenGL_extension ext;
316 OpenGL_extension *ext_ret;
318 TRACE("(%s)\n", lpszProc);
320 /* First, look if it's not already defined in the 'standard' OpenGL functions */
321 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
322 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
323 return local_func;
326 if (p_glXGetProcAddressARB == NULL) {
327 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
328 return NULL;
331 /* After that, search in the thunks to find the real name of the extension */
332 ext.name = (char *) lpszProc;
333 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
334 extension_registry_size, sizeof(OpenGL_extension), compar);
336 if (ext_ret == NULL) {
337 WGL_extension wgl_ext, *wgl_ext_ret;
339 /* Try to find the function in the WGL extensions ... */
340 wgl_ext.func_name = (char *) lpszProc;
341 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
342 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
344 if (wgl_ext_ret == NULL) {
345 /* Some sanity checks :-) */
346 ENTER_GL();
347 local_func = p_glXGetProcAddressARB(lpszProc);
348 LEAVE_GL();
349 if (local_func != NULL) {
350 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
351 return NULL;
354 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
355 return NULL;
356 } else {
357 void *ret = NULL;
359 if (wgl_ext_ret->func_init != NULL) {
360 const char *err_msg;
361 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
362 wgl_ext_ret->context)) == NULL) {
363 ret = wgl_ext_ret->func_address;
364 } else {
365 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
366 return NULL;
368 } else {
369 ret = wgl_ext_ret->func_address;
372 if (ret)
373 TRACE(" returning WGL function (%p)\n", ret);
374 return ret;
376 } else {
377 ENTER_GL();
378 local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
379 LEAVE_GL();
381 /* After that, look at the extensions defined in the Linux OpenGL library */
382 if (local_func == NULL) {
383 char buf[256];
384 void *ret = NULL;
386 /* Remove the 3 last letters (EXT, ARB, ...).
388 I know that some extensions have more than 3 letters (MESA, NV,
389 INTEL, ...), but this is only a stop-gap measure to fix buggy
390 OpenGL drivers (moreover, it is only useful for old 1.0 apps
391 that query the glBindTextureEXT extension).
393 strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
394 buf[strlen(ext_ret->glx_name) - 3] = '\0';
395 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
397 ret = GetProcAddress(opengl32_handle, buf);
398 if (ret != NULL) {
399 TRACE(" found function in main OpenGL library (%p) !\n", ret);
400 } else {
401 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
404 return ret;
405 } else {
406 TRACE(" returning function (%p)\n", ext_ret->func);
407 *(ext_ret->func_ptr) = local_func;
409 return ext_ret->func;
414 /***********************************************************************
415 * wglMakeCurrent (OPENGL32.@)
417 BOOL WINAPI wglMakeCurrent(HDC hdc,
418 HGLRC hglrc) {
419 BOOL ret;
421 TRACE("(%p,%p)\n", hdc, hglrc);
423 ENTER_GL();
424 if (hglrc == NULL) {
425 ret = glXMakeCurrent(default_display, None, NULL);
426 } else {
427 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
428 Drawable drawable = get_drawable( hdc );
430 if (ctx->ctx == NULL) {
431 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
432 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
434 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
436 LEAVE_GL();
437 TRACE(" returning %s\n", (ret ? "True" : "False"));
438 return ret;
441 /***********************************************************************
442 * wglRealizeLayerPalette (OPENGL32.@)
444 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
445 int iLayerPlane,
446 BOOL bRealize) {
447 FIXME("()\n");
449 return FALSE;
452 /***********************************************************************
453 * wglSetLayerPaletteEntries (OPENGL32.@)
455 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
456 int iLayerPlane,
457 int iStart,
458 int cEntries,
459 const COLORREF *pcr) {
460 FIXME("(): stub !\n");
462 return 0;
465 /***********************************************************************
466 * wglShareLists (OPENGL32.@)
468 BOOL WINAPI wglShareLists(HGLRC hglrc1,
469 HGLRC hglrc2) {
470 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
471 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
473 TRACE("(%p, %p)\n", org, dest);
475 if (dest->ctx != NULL) {
476 ERR("Could not share display lists, context already created !\n");
477 return FALSE;
478 } else {
479 if (org->ctx == NULL) {
480 ENTER_GL();
481 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
482 LEAVE_GL();
483 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
486 ENTER_GL();
487 /* Create the destination context with display lists shared */
488 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
489 LEAVE_GL();
490 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
493 return TRUE;
496 /***********************************************************************
497 * wglSwapLayerBuffers (OPENGL32.@)
499 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
500 UINT fuPlanes) {
501 TRACE("(%p, %08x)\n", hdc, fuPlanes);
503 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
504 if (!SwapBuffers(hdc)) return FALSE;
505 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
508 if (fuPlanes) {
509 WARN("Following layers unhandled : %08x\n", fuPlanes);
512 return TRUE;
515 static BOOL internal_wglUseFontBitmaps(HDC hdc,
516 DWORD first,
517 DWORD count,
518 DWORD listBase,
519 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
521 /* We are running using client-side rendering fonts... */
522 GLYPHMETRICS gm;
523 unsigned int glyph;
524 int size = 0;
525 void *bitmap = NULL, *gl_bitmap = NULL;
526 int org_alignment;
528 ENTER_GL();
529 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
530 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
531 LEAVE_GL();
533 for (glyph = first; glyph < first + count; glyph++) {
534 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
535 int height, width_int;
537 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
538 if (needed_size == GDI_ERROR) {
539 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
540 goto error;
541 } else {
542 TRACE(" - needed size : %d\n", needed_size);
545 if (needed_size > size) {
546 size = needed_size;
547 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
548 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
549 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
550 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
552 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
553 if (TRACE_ON(opengl)) {
554 unsigned int height, width, bitmask;
555 unsigned char *bitmap_ = (unsigned char *) bitmap;
557 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
558 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
559 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
560 if (needed_size != 0) {
561 TRACE(" - bitmap : \n");
562 for (height = 0; height < gm.gmBlackBoxY; height++) {
563 TRACE(" ");
564 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
565 if (bitmask == 0) {
566 bitmap_ += 1;
567 bitmask = 0x80;
569 if (*bitmap_ & bitmask)
570 DPRINTF("*");
571 else
572 DPRINTF(" ");
574 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
575 DPRINTF("\n");
580 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
581 * glyph for it to be drawn properly.
583 if (needed_size != 0) {
584 width_int = (gm.gmBlackBoxX + 31) / 32;
585 for (height = 0; height < gm.gmBlackBoxY; height++) {
586 int width;
587 for (width = 0; width < width_int; width++) {
588 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
589 ((int *) bitmap)[height * width_int + width];
594 ENTER_GL();
595 glNewList(listBase++, GL_COMPILE);
596 if (needed_size != 0) {
597 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
598 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
599 gm.gmCellIncX, gm.gmCellIncY,
600 gl_bitmap);
601 } else {
602 /* This is the case of 'empty' glyphs like the space character */
603 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
605 glEndList();
606 LEAVE_GL();
609 ENTER_GL();
610 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
611 LEAVE_GL();
613 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
614 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
615 return TRUE;
617 error:
618 ENTER_GL();
619 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
620 LEAVE_GL();
622 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
623 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
624 return FALSE;
627 /***********************************************************************
628 * wglUseFontBitmapsA (OPENGL32.@)
630 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
631 DWORD first,
632 DWORD count,
633 DWORD listBase)
635 Font fid = get_font( hdc );
637 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
639 if (fid == 0) {
640 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
643 ENTER_GL();
644 /* I assume that the glyphs are at the same position for X and for Windows */
645 glXUseXFont(fid, first, count, listBase);
646 LEAVE_GL();
647 return TRUE;
650 /***********************************************************************
651 * wglUseFontBitmapsW (OPENGL32.@)
653 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
654 DWORD first,
655 DWORD count,
656 DWORD listBase)
658 Font fid = get_font( hdc );
660 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
662 if (fid == 0) {
663 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
666 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
668 ENTER_GL();
669 /* I assume that the glyphs are at the same position for X and for Windows */
670 glXUseXFont(fid, first, count, listBase);
671 LEAVE_GL();
672 return TRUE;
675 /***********************************************************************
676 * wglUseFontOutlinesA (OPENGL32.@)
678 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
679 DWORD first,
680 DWORD count,
681 DWORD listBase,
682 FLOAT deviation,
683 FLOAT extrusion,
684 int format,
685 LPGLYPHMETRICSFLOAT lpgmf) {
686 FIXME("(): stub !\n");
688 return FALSE;
691 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
692 include all dependencies
694 #ifndef SONAME_LIBGL
695 #define SONAME_LIBGL "libGL.so"
696 #endif
698 /* This is for brain-dead applications that use OpenGL functions before even
699 creating a rendering context.... */
700 static BOOL process_attach(void)
702 XWindowAttributes win_attr;
703 Visual *rootVisual;
704 int num;
705 XVisualInfo template;
706 HDC hdc;
707 XVisualInfo *vis = NULL;
708 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
709 HMODULE mod = GetModuleHandleA( "x11drv.dll" );
710 void *opengl_handle;
712 if (!root || !mod)
714 ERR("X11DRV not loaded. Cannot create default context.\n");
715 return FALSE;
718 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
719 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
721 hdc = GetDC(0);
722 default_display = get_display( hdc );
723 ReleaseDC( 0, hdc );
724 if (!default_display)
726 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
727 return FALSE;
730 ENTER_GL();
732 /* Try to get the visual from the Root Window. We can't use the standard (presumably
733 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
734 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
735 with mismatched visuals. Note that the Root Window visual may not be double
736 buffered, so apps actually attempting to render this way may flicker */
737 if (XGetWindowAttributes( default_display, root, &win_attr ))
739 rootVisual = win_attr.visual;
741 else
743 /* Get the default visual, since we can't seem to get the attributes from the
744 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
745 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
748 template.visualid = XVisualIDFromVisual(rootVisual);
749 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
750 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
751 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
752 XFree(vis);
753 LEAVE_GL();
755 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
756 if (opengl_handle != NULL) {
757 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
758 wine_dlclose(opengl_handle, NULL, 0);
759 if (p_glXGetProcAddressARB == NULL)
760 TRACE("could not find glXGetProcAddressARB in libGL.\n");
763 /* Initialize also the list of supported WGL extensions. */
764 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display));
766 if (default_cx == NULL) {
767 ERR("Could not create default context.\n");
769 return TRUE;
773 /**********************************************************************/
775 static void process_detach(void)
777 glXDestroyContext(default_display, default_cx);
779 /* Do not leak memory... */
780 wgl_ext_finalize_extensions();
783 /***********************************************************************
784 * OpenGL initialisation routine
786 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
788 switch(reason)
790 case DLL_PROCESS_ATTACH:
791 opengl32_handle = hinst;
792 DisableThreadLibraryCalls(hinst);
793 return process_attach();
794 case DLL_PROCESS_DETACH:
795 process_detach();
796 break;
798 return TRUE;