Beginning of infrastructure to support WGL extensions.
[wine.git] / dlls / opengl32 / wgl.c
blob71d6f9c42793bf11ca2d823d61b3858285f8f8af
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 void *(*p_glXGetProcAddressARB)(const GLubyte *);
57 typedef struct wine_glcontext {
58 HDC hdc;
59 Display *display;
60 GLXContext ctx;
61 XVisualInfo *vis;
62 struct wine_glcontext *next;
63 struct wine_glcontext *prev;
64 } Wine_GLContext;
65 static Wine_GLContext *context_list;
67 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
69 Wine_GLContext *ret;
70 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
71 return ret;
74 static inline void free_context(Wine_GLContext *context)
76 if (context->next != NULL) context->next->prev = context->prev;
77 if (context->prev != NULL) context->prev->next = context->next;
78 else context_list = context->next;
80 HeapFree(GetProcessHeap(), 0, context);
83 static inline Wine_GLContext *alloc_context(void)
85 Wine_GLContext *ret;
87 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
89 ret->next = context_list;
90 if (context_list) context_list->prev = ret;
91 context_list = ret;
93 return ret;
96 inline static BOOL is_valid_context( Wine_GLContext *ctx )
98 Wine_GLContext *ptr;
99 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
100 return (ptr != NULL);
103 /* retrieve the X display to use on a given DC */
104 inline static Display *get_display( HDC hdc )
106 Display *display;
107 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
109 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
110 sizeof(display), (LPSTR)&display )) display = NULL;
111 return display;
115 /* retrieve the X drawable to use on a given DC */
116 inline static Drawable get_drawable( HDC hdc )
118 Drawable drawable;
119 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
121 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
122 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
123 return drawable;
127 /* retrieve the X drawable to use on a given DC */
128 inline static Font get_font( HDC hdc )
130 Font font;
131 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
133 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
134 sizeof(font), (LPSTR)&font )) font = 0;
135 return font;
139 /***********************************************************************
140 * wglCreateContext (OPENGL32.@)
142 HGLRC WINAPI wglCreateContext(HDC hdc)
144 XVisualInfo *vis;
145 Wine_GLContext *ret;
146 int num;
147 XVisualInfo template;
148 Display *display = get_display( hdc );
150 TRACE("(%p)\n", hdc);
152 /* First, get the visual in use by the X11DRV */
153 if (!display) return 0;
154 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
155 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
157 if (vis == NULL) {
158 ERR("NULL visual !!!\n");
159 /* Need to set errors here */
160 return NULL;
163 /* The context will be allocated in the wglMakeCurrent call */
164 ENTER_GL();
165 ret = alloc_context();
166 LEAVE_GL();
167 ret->hdc = hdc;
168 ret->display = display;
169 ret->vis = vis;
171 TRACE(" creating context %p (GL context creation delayed)\n", ret);
172 return (HGLRC) ret;
175 /***********************************************************************
176 * wglCreateLayerContext (OPENGL32.@)
178 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
179 int iLayerPlane) {
180 TRACE("(%p,%d)\n", hdc, iLayerPlane);
182 if (iLayerPlane == 0) {
183 return wglCreateContext(hdc);
185 FIXME(" no handler for layer %d\n", iLayerPlane);
187 return NULL;
190 /***********************************************************************
191 * wglCopyContext (OPENGL32.@)
193 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
194 HGLRC hglrcDst,
195 UINT mask) {
196 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
198 return FALSE;
201 /***********************************************************************
202 * wglDeleteContext (OPENGL32.@)
204 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
206 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
207 BOOL ret = TRUE;
209 TRACE("(%p)\n", hglrc);
211 ENTER_GL();
212 /* A game (Half Life not to name it) deletes twice the same context,
213 * so make sure it is valid first */
214 if (is_valid_context( ctx ))
216 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
217 free_context(ctx);
219 else
221 WARN("Error deleting context !\n");
222 SetLastError(ERROR_INVALID_HANDLE);
223 ret = FALSE;
225 LEAVE_GL();
227 return ret;
230 /***********************************************************************
231 * wglDescribeLayerPlane (OPENGL32.@)
233 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
234 int iPixelFormat,
235 int iLayerPlane,
236 UINT nBytes,
237 LPLAYERPLANEDESCRIPTOR plpd) {
238 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
240 return FALSE;
243 /***********************************************************************
244 * wglGetCurrentContext (OPENGL32.@)
246 HGLRC WINAPI wglGetCurrentContext(void) {
247 GLXContext gl_ctx;
248 Wine_GLContext *ret;
250 TRACE("()\n");
252 ENTER_GL();
253 gl_ctx = glXGetCurrentContext();
254 ret = get_context_from_GLXContext(gl_ctx);
255 LEAVE_GL();
257 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
259 return ret;
262 /***********************************************************************
263 * wglGetCurrentDC (OPENGL32.@)
265 HDC WINAPI wglGetCurrentDC(void) {
266 GLXContext gl_ctx;
267 Wine_GLContext *ret;
269 TRACE("()\n");
271 ENTER_GL();
272 gl_ctx = glXGetCurrentContext();
273 ret = get_context_from_GLXContext(gl_ctx);
274 LEAVE_GL();
276 if (ret) {
277 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
278 return ret->hdc;
279 } else {
280 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
281 return 0;
285 /***********************************************************************
286 * wglGetLayerPaletteEntries (OPENGL32.@)
288 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
289 int iLayerPlane,
290 int iStart,
291 int cEntries,
292 const COLORREF *pcr) {
293 FIXME("(): stub !\n");
295 return 0;
298 /***********************************************************************
299 * wglGetProcAddress (OPENGL32.@)
301 static int compar(const void *elt_a, const void *elt_b) {
302 return strcmp(((OpenGL_extension *) elt_a)->name,
303 ((OpenGL_extension *) elt_b)->name);
306 static int wgl_compar(const void *elt_a, const void *elt_b) {
307 return strcmp(((WGL_extension *) elt_a)->func_name,
308 ((WGL_extension *) elt_b)->func_name);
311 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
312 void *local_func;
313 static HMODULE hm = 0;
314 OpenGL_extension ext;
315 OpenGL_extension *ext_ret;
318 TRACE("(%s)\n", lpszProc);
320 if (hm == 0)
321 hm = GetModuleHandleA("opengl32");
323 /* First, look if it's not already defined in the 'standard' OpenGL functions */
324 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
325 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
326 return local_func;
329 if (p_glXGetProcAddressARB == NULL) {
330 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
331 return NULL;
334 /* After that, search in the thunks to find the real name of the extension */
335 ext.name = (char *) lpszProc;
336 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
337 extension_registry_size, sizeof(OpenGL_extension), compar);
339 if (ext_ret == NULL) {
340 WGL_extension wgl_ext, *wgl_ext_ret;
342 /* Try to find the function in the WGL extensions ... */
343 wgl_ext.func_name = (char *) lpszProc;
344 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
345 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
347 if (wgl_ext_ret == NULL) {
348 /* Some sanity checks :-) */
349 ENTER_GL();
350 local_func = p_glXGetProcAddressARB(lpszProc);
351 LEAVE_GL();
352 if (local_func != NULL) {
353 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
354 return NULL;
357 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
358 return NULL;
359 } else {
360 void *ret = NULL;
362 if (wgl_ext_ret->func_init != NULL) {
363 const char *err_msg;
364 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
365 wgl_ext_ret->context)) == NULL) {
366 ret = wgl_ext_ret->func_address;
367 } else {
368 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
369 return NULL;
371 } else {
372 ret = wgl_ext_ret->func_address;
375 if (ret)
376 TRACE(" returning WGL function (%p)\n", ret);
377 return ret;
379 } else {
380 ENTER_GL();
381 local_func = p_glXGetProcAddressARB(ext_ret->glx_name);
382 LEAVE_GL();
384 /* After that, look at the extensions defined in the Linux OpenGL library */
385 if (local_func == NULL) {
386 char buf[256];
387 void *ret = NULL;
389 /* Remove the 3 last letters (EXT, ARB, ...).
391 I know that some extensions have more than 3 letters (MESA, NV,
392 INTEL, ...), but this is only a stop-gap measure to fix buggy
393 OpenGL drivers (moreover, it is only useful for old 1.0 apps
394 that query the glBindTextureEXT extension).
396 strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
397 buf[strlen(ext_ret->glx_name) - 3] = '\0';
398 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
400 ret = GetProcAddress(hm, buf);
401 if (ret != NULL) {
402 TRACE(" found function in main OpenGL library (%p) !\n", ret);
403 } else {
404 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
407 return ret;
408 } else {
409 TRACE(" returning function (%p)\n", ext_ret->func);
410 *(ext_ret->func_ptr) = local_func;
412 return ext_ret->func;
417 /***********************************************************************
418 * wglMakeCurrent (OPENGL32.@)
420 BOOL WINAPI wglMakeCurrent(HDC hdc,
421 HGLRC hglrc) {
422 BOOL ret;
424 TRACE("(%p,%p)\n", hdc, hglrc);
426 ENTER_GL();
427 if (hglrc == NULL) {
428 ret = glXMakeCurrent(default_display, None, NULL);
429 } else {
430 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
431 Drawable drawable = get_drawable( hdc );
433 if (ctx->ctx == NULL) {
434 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, True);
435 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
437 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
439 LEAVE_GL();
440 TRACE(" returning %s\n", (ret ? "True" : "False"));
441 return ret;
444 /***********************************************************************
445 * wglRealizeLayerPalette (OPENGL32.@)
447 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
448 int iLayerPlane,
449 BOOL bRealize) {
450 FIXME("()\n");
452 return FALSE;
455 /***********************************************************************
456 * wglSetLayerPaletteEntries (OPENGL32.@)
458 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
459 int iLayerPlane,
460 int iStart,
461 int cEntries,
462 const COLORREF *pcr) {
463 FIXME("(): stub !\n");
465 return 0;
468 /***********************************************************************
469 * wglShareLists (OPENGL32.@)
471 BOOL WINAPI wglShareLists(HGLRC hglrc1,
472 HGLRC hglrc2) {
473 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
474 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
476 TRACE("(%p, %p)\n", org, dest);
478 if (dest->ctx != NULL) {
479 ERR("Could not share display lists, context already created !\n");
480 return FALSE;
481 } else {
482 if (org->ctx == NULL) {
483 ENTER_GL();
484 org->ctx = glXCreateContext(org->display, org->vis, NULL, True);
485 LEAVE_GL();
486 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
489 ENTER_GL();
490 /* Create the destination context with display lists shared */
491 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, True);
492 LEAVE_GL();
493 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
496 return TRUE;
499 /***********************************************************************
500 * wglSwapLayerBuffers (OPENGL32.@)
502 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
503 UINT fuPlanes) {
504 TRACE("(%p, %08x)\n", hdc, fuPlanes);
506 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
507 if (!SwapBuffers(hdc)) return FALSE;
508 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
511 if (fuPlanes) {
512 WARN("Following layers unhandled : %08x\n", fuPlanes);
515 return TRUE;
518 static BOOL internal_wglUseFontBitmaps(HDC hdc,
519 DWORD first,
520 DWORD count,
521 DWORD listBase,
522 DWORD WINAPI (*GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
524 /* We are running using client-side rendering fonts... */
525 GLYPHMETRICS gm;
526 static const MAT2 id = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
527 int glyph;
528 int size = 0;
529 void *bitmap = NULL, *gl_bitmap = NULL;
530 int org_alignment;
532 ENTER_GL();
533 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
534 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
535 LEAVE_GL();
537 for (glyph = first; glyph < first + count; glyph++) {
538 int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, &id);
539 int height, width_int;
541 if (needed_size == GDI_ERROR) goto error;
542 if (needed_size > size) {
543 size = needed_size;
544 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
545 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
546 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
547 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
549 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, &id) == GDI_ERROR) goto error;
550 if (TRACE_ON(opengl)) {
551 unsigned int height, width, bitmask;
552 unsigned char *bitmap_ = (unsigned char *) bitmap;
554 DPRINTF("Glyph : %d\n", glyph);
555 DPRINTF(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
556 DPRINTF(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
557 DPRINTF(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
558 DPRINTF(" - size : %d\n", needed_size);
559 DPRINTF(" - bitmap : \n");
560 for (height = 0; height < gm.gmBlackBoxY; height++) {
561 DPRINTF(" ");
562 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
563 if (bitmask == 0) {
564 bitmap_ += 1;
565 bitmask = 0x80;
567 if (*bitmap_ & bitmask)
568 DPRINTF("*");
569 else
570 DPRINTF(" ");
572 bitmap_ += (4 - (((unsigned int) bitmap_) & 0x03));
573 DPRINTF("\n");
577 /* For some obscure reasons, I seem to need to rotate the glyph for OpenGL to be happy.
578 As Wine does not seem to support the MAT2 field, I need to do it myself.... */
579 width_int = (gm.gmBlackBoxX + 31) / 32;
580 for (height = 0; height < gm.gmBlackBoxY; height++) {
581 int width;
582 for (width = 0; width < width_int; width++) {
583 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
584 ((int *) bitmap)[height * width_int + width];
588 ENTER_GL();
589 glNewList(listBase++, GL_COMPILE);
590 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, gm.gmptGlyphOrigin.x,
591 gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap);
592 glEndList();
593 LEAVE_GL();
596 ENTER_GL();
597 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
598 LEAVE_GL();
600 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
601 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
602 return TRUE;
604 error:
605 ENTER_GL();
606 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
607 LEAVE_GL();
609 if (bitmap) HeapFree(GetProcessHeap(), 0, bitmap);
610 if (gl_bitmap) HeapFree(GetProcessHeap(), 0, gl_bitmap);
611 return FALSE;
614 /***********************************************************************
615 * wglUseFontBitmapsA (OPENGL32.@)
617 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
618 DWORD first,
619 DWORD count,
620 DWORD listBase)
622 Font fid = get_font( hdc );
624 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
626 if (fid == 0) {
627 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
630 ENTER_GL();
631 /* I assume that the glyphs are at the same position for X and for Windows */
632 glXUseXFont(fid, first, count, listBase);
633 LEAVE_GL();
634 return TRUE;
637 /***********************************************************************
638 * wglUseFontBitmapsW (OPENGL32.@)
640 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
641 DWORD first,
642 DWORD count,
643 DWORD listBase)
645 Font fid = get_font( hdc );
647 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
649 if (fid == 0) {
650 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
653 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
655 ENTER_GL();
656 /* I assume that the glyphs are at the same position for X and for Windows */
657 glXUseXFont(fid, first, count, listBase);
658 LEAVE_GL();
659 return TRUE;
662 /***********************************************************************
663 * wglUseFontOutlinesA (OPENGL32.@)
665 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
666 DWORD first,
667 DWORD count,
668 DWORD listBase,
669 FLOAT deviation,
670 FLOAT extrusion,
671 int format,
672 LPGLYPHMETRICSFLOAT lpgmf) {
673 FIXME("(): stub !\n");
675 return FALSE;
678 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
679 include all dependencies
681 #ifndef SONAME_LIBGL
682 #define SONAME_LIBGL "libGL.so"
683 #endif
685 /* This is for brain-dead applications that use OpenGL functions before even
686 creating a rendering context.... */
687 static BOOL process_attach(void)
689 XWindowAttributes win_attr;
690 Visual *rootVisual;
691 int num;
692 XVisualInfo template;
693 HDC hdc;
694 XVisualInfo *vis = NULL;
695 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
696 HMODULE mod = GetModuleHandleA( "x11drv.dll" );
697 void *opengl_handle;
699 if (!root || !mod)
701 ERR("X11DRV not loaded. Cannot create default context.\n");
702 return FALSE;
705 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
706 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
708 hdc = GetDC(0);
709 default_display = get_display( hdc );
710 ReleaseDC( 0, hdc );
711 if (!default_display)
713 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
714 return FALSE;
717 ENTER_GL();
719 /* Try to get the visual from the Root Window. We can't use the standard (presumably
720 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
721 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
722 with mismatched visuals. Note that the Root Window visual may not be double
723 buffered, so apps actually attempting to render this way may flicker */
724 if (XGetWindowAttributes( default_display, root, &win_attr ))
726 rootVisual = win_attr.visual;
728 else
730 /* Get the default visual, since we can't seem to get the attributes from the
731 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
732 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
735 template.visualid = XVisualIDFromVisual(rootVisual);
736 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
737 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
738 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
739 XFree(vis);
740 LEAVE_GL();
742 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
743 if (opengl_handle != NULL) {
744 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
745 wine_dlclose(opengl_handle, NULL, 0);
746 if (p_glXGetProcAddressARB == NULL)
747 TRACE("could not find glXGetProcAddressARB in libGL.\n");
750 /* Initialize also the list of supported WGL extensions. */
751 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display));
753 if (default_cx == NULL) {
754 ERR("Could not create default context.\n");
756 return TRUE;
760 /**********************************************************************/
762 static void process_detach(void)
764 glXDestroyContext(default_display, default_cx);
766 /* Do not leak memory... */
767 wgl_ext_finalize_extensions();
770 /***********************************************************************
771 * OpenGL initialisation routine
773 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
775 switch(reason)
777 case DLL_PROCESS_ATTACH:
778 DisableThreadLibraryCalls(hinst);
779 return process_attach();
780 case DLL_PROCESS_DETACH:
781 process_detach();
782 break;
784 return TRUE;