shell32: Fix the file version string of the version resource.
[wine/multimedia.git] / dlls / opengl32 / wgl.c
blob178cb6b1b9aecce0e220557b47839c0ad373696e
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winternl.h"
35 #include "winnt.h"
37 #include "wgl_ext.h"
38 #include "opengl_ext.h"
39 #ifdef HAVE_GL_GLU_H
40 #undef far
41 #undef near
42 #include <GL/glu.h>
43 #endif
44 #include "wine/library.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
48 WINE_DECLARE_DEBUG_CHANNEL(opengl);
50 /** global glx object */
51 wine_glx_t wine_glx;
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
57 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
58 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
59 X11DRV_GET_FONT, /* get current X font for a DC */
60 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
61 X11DRV_START_EXPOSURES, /* start graphics exposures */
62 X11DRV_END_EXPOSURES, /* end graphics exposures */
63 X11DRV_GET_DCE, /* get the DCE pointer */
64 X11DRV_SET_DCE, /* set the DCE pointer */
65 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
66 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
69 void (*wine_tsx11_lock_ptr)(void) = NULL;
70 void (*wine_tsx11_unlock_ptr)(void) = NULL;
72 static GLXContext default_cx = NULL;
73 static Display *default_display; /* display to use for default context */
75 static HMODULE opengl32_handle;
77 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
79 static char internal_gl_disabled_extensions[512];
80 static char* internal_gl_extensions = NULL;
82 typedef struct wine_glcontext {
83 HDC hdc;
84 Display *display;
85 XVisualInfo *vis;
86 GLXFBConfig fb_conf;
87 GLXContext ctx;
88 BOOL do_escape;
89 struct wine_glcontext *next;
90 struct wine_glcontext *prev;
91 } Wine_GLContext;
92 static Wine_GLContext *context_list;
94 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
96 Wine_GLContext *ret;
97 if (!ctx) return NULL;
98 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
99 return ret;
102 void enter_gl(void)
104 Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
106 if (curctx && curctx->do_escape)
108 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
109 ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
112 wine_tsx11_lock_ptr();
113 return;
116 static inline void free_context(Wine_GLContext *context)
118 if (context->next != NULL) context->next->prev = context->prev;
119 if (context->prev != NULL) context->prev->next = context->next;
120 else context_list = context->next;
122 HeapFree(GetProcessHeap(), 0, context);
125 static inline Wine_GLContext *alloc_context(void)
127 Wine_GLContext *ret;
129 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
131 ret->next = context_list;
132 if (context_list) context_list->prev = ret;
133 context_list = ret;
135 return ret;
138 inline static BOOL is_valid_context( Wine_GLContext *ctx )
140 Wine_GLContext *ptr;
141 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
142 return (ptr != NULL);
145 /* retrieve the X display to use on a given DC */
146 inline static Display *get_display( HDC hdc )
148 Display *display;
149 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
151 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
152 sizeof(display), (LPSTR)&display )) display = NULL;
153 return display;
157 /* retrieve the GLX drawable to use on a given DC */
158 inline static Drawable get_drawable( HDC hdc )
160 GLXDrawable drawable;
161 enum x11drv_escape_codes escape = X11DRV_GET_GLX_DRAWABLE;
163 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
164 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
165 return drawable;
168 /** for use of wglGetCurrentReadDCARB */
169 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
171 Wine_GLContext *ret;
172 for (ret = context_list; ret; ret = ret->next) {
173 if (d == get_drawable( ret->hdc )) {
174 return ret->hdc;
177 return NULL;
180 /* retrieve the X font to use on a given DC */
181 inline static Font get_font( HDC hdc )
183 Font font;
184 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
186 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
187 sizeof(font), (LPSTR)&font )) font = 0;
188 return font;
192 /***********************************************************************
193 * wglCreateContext (OPENGL32.@)
195 HGLRC WINAPI wglCreateContext(HDC hdc)
197 Wine_GLContext *ret;
198 int num;
199 XVisualInfo template;
200 XVisualInfo *vis = NULL;
201 Display *display = get_display( hdc );
202 int hdcPF = GetPixelFormat(hdc);
203 GLXFBConfig cur_cfg;
205 TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);
207 /* First, get the visual in use by the X11DRV */
208 if (!display) return 0;
209 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
210 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
212 if (vis == NULL) {
213 ERR("NULL visual !!!\n");
214 /* Need to set errors here */
215 return NULL;
217 if (0 >= hdcPF) {
218 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
219 return NULL;
223 int nCfgs_fmt = 0;
224 GLXFBConfig* cfgs_fmt = NULL;
225 int value;
226 int gl_test = 0;
227 cfgs_fmt = wine_glx.p_glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
228 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
229 ERR("Cannot get FB Configs, expect problems.\n");
230 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
231 return NULL;
233 if (nCfgs_fmt < hdcPF) {
234 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, nCfgs_fmt);
235 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
236 return NULL;
238 cur_cfg = cfgs_fmt[hdcPF - 1];
239 gl_test = wine_glx.p_glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
240 if (gl_test) {
241 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
242 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
243 return NULL;
245 XFree(cfgs_fmt);
248 /* The context will be allocated in the wglMakeCurrent call */
249 ENTER_GL();
250 ret = alloc_context();
251 LEAVE_GL();
252 ret->hdc = hdc;
253 ret->display = display;
254 ret->fb_conf = cur_cfg;
255 /*ret->vis = vis;*/
256 ret->vis = wine_glx.p_glXGetVisualFromFBConfig(display, cur_cfg);
258 TRACE(" creating context %p (GL context creation delayed)\n", ret);
259 return (HGLRC) ret;
262 /***********************************************************************
263 * wglCreateLayerContext (OPENGL32.@)
265 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
266 int iLayerPlane) {
267 TRACE("(%p,%d)\n", hdc, iLayerPlane);
269 if (iLayerPlane == 0) {
270 return wglCreateContext(hdc);
272 FIXME(" no handler for layer %d\n", iLayerPlane);
274 return NULL;
277 /***********************************************************************
278 * wglCopyContext (OPENGL32.@)
280 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
281 HGLRC hglrcDst,
282 UINT mask) {
283 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
285 return FALSE;
288 /***********************************************************************
289 * wglDeleteContext (OPENGL32.@)
291 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
293 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
294 BOOL ret = TRUE;
296 TRACE("(%p)\n", hglrc);
298 ENTER_GL();
299 /* A game (Half Life not to name it) deletes twice the same context,
300 * so make sure it is valid first */
301 if (is_valid_context( ctx ))
303 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
304 free_context(ctx);
306 else
308 WARN("Error deleting context !\n");
309 SetLastError(ERROR_INVALID_HANDLE);
310 ret = FALSE;
312 LEAVE_GL();
314 return ret;
317 /***********************************************************************
318 * wglDescribeLayerPlane (OPENGL32.@)
320 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
321 int iPixelFormat,
322 int iLayerPlane,
323 UINT nBytes,
324 LPLAYERPLANEDESCRIPTOR plpd) {
325 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
327 return FALSE;
330 /***********************************************************************
331 * wglGetCurrentContext (OPENGL32.@)
333 HGLRC WINAPI wglGetCurrentContext(void) {
334 GLXContext gl_ctx;
335 Wine_GLContext *ret;
337 TRACE("()\n");
339 ENTER_GL();
340 gl_ctx = glXGetCurrentContext();
341 ret = get_context_from_GLXContext(gl_ctx);
342 LEAVE_GL();
344 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
346 return (HGLRC)ret;
349 /***********************************************************************
350 * wglGetCurrentDC (OPENGL32.@)
352 HDC WINAPI wglGetCurrentDC(void) {
353 GLXContext gl_ctx;
354 Wine_GLContext *ret;
356 TRACE("()\n");
358 ENTER_GL();
359 gl_ctx = glXGetCurrentContext();
360 ret = get_context_from_GLXContext(gl_ctx);
361 LEAVE_GL();
363 if (ret) {
364 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
365 return ret->hdc;
366 } else {
367 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
368 return 0;
372 /***********************************************************************
373 * wglGetLayerPaletteEntries (OPENGL32.@)
375 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
376 int iLayerPlane,
377 int iStart,
378 int cEntries,
379 const COLORREF *pcr) {
380 FIXME("(): stub !\n");
382 return 0;
385 /***********************************************************************
386 * wglGetProcAddress (OPENGL32.@)
388 static int compar(const void *elt_a, const void *elt_b) {
389 return strcmp(((const OpenGL_extension *) elt_a)->name,
390 ((const OpenGL_extension *) elt_b)->name);
393 static int wgl_compar(const void *elt_a, const void *elt_b) {
394 return strcmp(((const WGL_extension *) elt_a)->func_name,
395 ((const WGL_extension *) elt_b)->func_name);
398 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
399 void *local_func;
400 OpenGL_extension ext;
401 const OpenGL_extension *ext_ret;
403 TRACE("(%s)\n", lpszProc);
405 /* First, look if it's not already defined in the 'standard' OpenGL functions */
406 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
407 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
408 return local_func;
411 if (p_glXGetProcAddressARB == NULL) {
412 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
413 return NULL;
416 /* After that, search in the thunks to find the real name of the extension */
417 ext.name = lpszProc;
418 ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
419 extension_registry_size, sizeof(OpenGL_extension), compar);
421 if (ext_ret == NULL) {
422 WGL_extension wgl_ext, *wgl_ext_ret;
424 /* Try to find the function in the WGL extensions ... */
425 wgl_ext.func_name = (char *) lpszProc;
426 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
427 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
429 if (wgl_ext_ret == NULL) {
430 /* Some sanity checks :-) */
431 ENTER_GL();
432 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
433 LEAVE_GL();
434 if (local_func != NULL) {
435 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
436 return NULL;
439 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
440 return NULL;
441 } else {
442 void *ret = NULL;
444 if (wgl_ext_ret->func_init != NULL) {
445 const char *err_msg;
446 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
447 wgl_ext_ret->context)) == NULL) {
448 ret = wgl_ext_ret->func_address;
449 } else {
450 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
451 return NULL;
453 } else {
454 ret = wgl_ext_ret->func_address;
457 if (ret)
458 TRACE(" returning WGL function (%p)\n", ret);
459 return ret;
461 } else {
462 const char *glx_name = ext_ret->glx_name ? ext_ret->glx_name : ext_ret->name;
463 ENTER_GL();
464 local_func = p_glXGetProcAddressARB( (const GLubyte*)glx_name);
465 LEAVE_GL();
467 /* After that, look at the extensions defined in the Linux OpenGL library */
468 if (local_func == NULL) {
469 char buf[256];
470 void *ret = NULL;
472 /* Remove the 3 last letters (EXT, ARB, ...).
474 I know that some extensions have more than 3 letters (MESA, NV,
475 INTEL, ...), but this is only a stop-gap measure to fix buggy
476 OpenGL drivers (moreover, it is only useful for old 1.0 apps
477 that query the glBindTextureEXT extension).
479 memcpy(buf, glx_name, strlen(glx_name) - 3);
480 buf[strlen(glx_name) - 3] = '\0';
481 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
483 ret = GetProcAddress(opengl32_handle, buf);
484 if (ret != NULL) {
485 TRACE(" found function in main OpenGL library (%p) !\n", ret);
486 } else {
487 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, glx_name);
490 return ret;
491 } else {
492 TRACE(" returning function (%p)\n", ext_ret->func);
493 extension_funcs[ext_ret - extension_registry] = local_func;
495 return ext_ret->func;
500 static int describeContext(Wine_GLContext* ctx) {
501 int tmp;
502 int ctx_vis_id;
503 TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis);
504 wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_FBCONFIG_ID, &tmp);
505 TRACE(" - FBCONFIG_ID 0x%x\n", tmp);
506 wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_VISUAL_ID, &tmp);
507 TRACE(" - VISUAL_ID 0x%x\n", tmp);
508 ctx_vis_id = tmp;
509 return ctx_vis_id;
512 static int describeDrawable(Wine_GLContext* ctx, Drawable drawable) {
513 int tmp;
514 int nElements;
515 int attribList[3] = { GLX_FBCONFIG_ID, 0, None };
516 GLXFBConfig *fbCfgs;
518 if (3 > wine_glx.version || NULL == wine_glx.p_glXQueryDrawable) {
519 /** glXQueryDrawable not available so returns not supported */
520 return -1;
523 TRACE(" Drawable %p have :\n", (void*) drawable);
524 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_WIDTH, (unsigned int*) &tmp);
525 TRACE(" - WIDTH as %d\n", tmp);
526 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_HEIGHT, (unsigned int*) &tmp);
527 TRACE(" - HEIGHT as %d\n", tmp);
528 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &tmp);
529 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
531 attribList[1] = tmp;
532 fbCfgs = wine_glx.p_glXChooseFBConfig(ctx->display, DefaultScreen(ctx->display), attribList, &nElements);
533 if (fbCfgs == NULL) {
534 return -1;
537 wine_glx.p_glXGetFBConfigAttrib(ctx->display, fbCfgs[0], GLX_VISUAL_ID, &tmp);
538 TRACE(" - VISUAL_ID as 0x%x\n", tmp);
540 XFree(fbCfgs);
542 return tmp;
545 /***********************************************************************
546 * wglMakeCurrent (OPENGL32.@)
548 BOOL WINAPI wglMakeCurrent(HDC hdc,
549 HGLRC hglrc) {
550 BOOL ret;
551 DWORD type = GetObjectType(hdc);
553 TRACE("(%p,%p)\n", hdc, hglrc);
555 ENTER_GL();
556 if (hglrc == NULL) {
557 ret = glXMakeCurrent(default_display, None, NULL);
558 NtCurrentTeb()->glContext = NULL;
559 } else {
560 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
561 Drawable drawable = get_drawable( hdc );
562 if (ctx->ctx == NULL) {
563 int draw_vis_id, ctx_vis_id;
564 VisualID visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
565 TRACE(" Wine desktop VISUAL_ID is 0x%x\n", (unsigned int) visualid);
566 draw_vis_id = describeDrawable(ctx, drawable);
567 ctx_vis_id = describeContext(ctx);
569 if (-1 == draw_vis_id || (draw_vis_id == visualid && draw_vis_id != ctx_vis_id)) {
571 * Inherits from root window so reuse desktop visual
573 XVisualInfo template;
574 XVisualInfo *vis;
575 int num;
576 template.visualid = visualid;
577 vis = XGetVisualInfo(ctx->display, VisualIDMask, &template, &num);
579 TRACE(" Creating GLX Context\n");
580 ctx->ctx = glXCreateContext(ctx->display, vis, NULL, type == OBJ_MEMDC ? False : True);
581 } else {
582 TRACE(" Creating GLX Context\n");
583 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True);
585 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
587 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
588 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
589 NtCurrentTeb()->glContext = ctx;
590 if(ret && type == OBJ_MEMDC)
592 ctx->do_escape = TRUE;
593 glDrawBuffer(GL_FRONT_LEFT);
596 LEAVE_GL();
597 TRACE(" returning %s\n", (ret ? "True" : "False"));
598 return ret;
601 /***********************************************************************
602 * wglMakeContextCurrentARB (OPENGL32.@)
604 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
606 BOOL ret;
607 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
609 ENTER_GL();
610 if (hglrc == NULL) {
611 ret = glXMakeCurrent(default_display, None, NULL);
612 } else {
613 if (NULL == wine_glx.p_glXMakeContextCurrent) {
614 ret = FALSE;
615 } else {
616 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
617 Drawable d_draw = get_drawable( hDrawDC );
618 Drawable d_read = get_drawable( hReadDC );
620 if (ctx->ctx == NULL) {
621 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, GetObjectType(hDrawDC) == OBJ_MEMDC ? False : True);
622 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
624 ret = wine_glx.p_glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
627 LEAVE_GL();
629 TRACE(" returning %s\n", (ret ? "True" : "False"));
630 return ret;
633 /***********************************************************************
634 * wglGetCurrentReadDCARB (OPENGL32.@)
636 HDC WINAPI wglGetCurrentReadDCARB(void)
638 GLXDrawable gl_d;
639 HDC ret;
641 TRACE("()\n");
643 ENTER_GL();
644 gl_d = glXGetCurrentReadDrawable();
645 ret = get_hdc_from_Drawable(gl_d);
646 LEAVE_GL();
648 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
649 return ret;
654 /***********************************************************************
655 * wglRealizeLayerPalette (OPENGL32.@)
657 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
658 int iLayerPlane,
659 BOOL bRealize) {
660 FIXME("()\n");
662 return FALSE;
665 /***********************************************************************
666 * wglSetLayerPaletteEntries (OPENGL32.@)
668 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
669 int iLayerPlane,
670 int iStart,
671 int cEntries,
672 const COLORREF *pcr) {
673 FIXME("(): stub !\n");
675 return 0;
678 /***********************************************************************
679 * wglShareLists (OPENGL32.@)
681 BOOL WINAPI wglShareLists(HGLRC hglrc1,
682 HGLRC hglrc2) {
683 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
684 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
686 TRACE("(%p, %p)\n", org, dest);
688 if (NULL != dest && dest->ctx != NULL) {
689 ERR("Could not share display lists, context already created !\n");
690 return FALSE;
691 } else {
692 if (org->ctx == NULL) {
693 ENTER_GL();
694 describeContext(org);
695 org->ctx = glXCreateContext(org->display, org->vis, NULL, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
696 LEAVE_GL();
697 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
699 if (NULL != dest) {
700 ENTER_GL();
701 describeContext(dest);
702 /* Create the destination context with display lists shared */
703 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
704 LEAVE_GL();
705 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
706 return TRUE;
709 return FALSE;
712 /***********************************************************************
713 * wglSwapLayerBuffers (OPENGL32.@)
715 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
716 UINT fuPlanes) {
717 TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
719 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
720 if (!SwapBuffers(hdc)) return FALSE;
721 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
724 if (fuPlanes) {
725 WARN("Following layers unhandled : %08x\n", fuPlanes);
728 return TRUE;
731 static BOOL internal_wglUseFontBitmaps(HDC hdc,
732 DWORD first,
733 DWORD count,
734 DWORD listBase,
735 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
737 /* We are running using client-side rendering fonts... */
738 GLYPHMETRICS gm;
739 unsigned int glyph;
740 int size = 0;
741 void *bitmap = NULL, *gl_bitmap = NULL;
742 int org_alignment;
744 ENTER_GL();
745 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
746 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
747 LEAVE_GL();
749 for (glyph = first; glyph < first + count; glyph++) {
750 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
751 int height, width_int;
753 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
754 if (needed_size == GDI_ERROR) {
755 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
756 goto error;
757 } else {
758 TRACE(" - needed size : %d\n", needed_size);
761 if (needed_size > size) {
762 size = needed_size;
763 HeapFree(GetProcessHeap(), 0, bitmap);
764 HeapFree(GetProcessHeap(), 0, gl_bitmap);
765 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
766 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
768 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
769 if (TRACE_ON(opengl)) {
770 unsigned int height, width, bitmask;
771 unsigned char *bitmap_ = (unsigned char *) bitmap;
773 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
774 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
775 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
776 if (needed_size != 0) {
777 TRACE(" - bitmap :\n");
778 for (height = 0; height < gm.gmBlackBoxY; height++) {
779 TRACE(" ");
780 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
781 if (bitmask == 0) {
782 bitmap_ += 1;
783 bitmask = 0x80;
785 if (*bitmap_ & bitmask)
786 TRACE("*");
787 else
788 TRACE(" ");
790 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
791 TRACE("\n");
796 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
797 * glyph for it to be drawn properly.
799 if (needed_size != 0) {
800 width_int = (gm.gmBlackBoxX + 31) / 32;
801 for (height = 0; height < gm.gmBlackBoxY; height++) {
802 int width;
803 for (width = 0; width < width_int; width++) {
804 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
805 ((int *) bitmap)[height * width_int + width];
810 ENTER_GL();
811 glNewList(listBase++, GL_COMPILE);
812 if (needed_size != 0) {
813 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
814 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
815 gm.gmCellIncX, gm.gmCellIncY,
816 gl_bitmap);
817 } else {
818 /* This is the case of 'empty' glyphs like the space character */
819 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
821 glEndList();
822 LEAVE_GL();
825 ENTER_GL();
826 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
827 LEAVE_GL();
829 HeapFree(GetProcessHeap(), 0, bitmap);
830 HeapFree(GetProcessHeap(), 0, gl_bitmap);
831 return TRUE;
833 error:
834 ENTER_GL();
835 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
836 LEAVE_GL();
838 HeapFree(GetProcessHeap(), 0, bitmap);
839 HeapFree(GetProcessHeap(), 0, gl_bitmap);
840 return FALSE;
843 /***********************************************************************
844 * wglUseFontBitmapsA (OPENGL32.@)
846 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
847 DWORD first,
848 DWORD count,
849 DWORD listBase)
851 Font fid = get_font( hdc );
853 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
855 if (fid == 0) {
856 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
859 ENTER_GL();
860 /* I assume that the glyphs are at the same position for X and for Windows */
861 glXUseXFont(fid, first, count, listBase);
862 LEAVE_GL();
863 return TRUE;
866 /***********************************************************************
867 * wglUseFontBitmapsW (OPENGL32.@)
869 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
870 DWORD first,
871 DWORD count,
872 DWORD listBase)
874 Font fid = get_font( hdc );
876 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
878 if (fid == 0) {
879 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
882 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
884 ENTER_GL();
885 /* I assume that the glyphs are at the same position for X and for Windows */
886 glXUseXFont(fid, first, count, listBase);
887 LEAVE_GL();
888 return TRUE;
891 #ifdef HAVE_GL_GLU_H
893 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
895 vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
896 vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
897 vertex[2] = 0.0;
900 static void tess_callback_vertex(GLvoid *vertex)
902 GLdouble *dbl = vertex;
903 TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
904 glVertex3dv(vertex);
907 static void tess_callback_begin(GLenum which)
909 TRACE("%d\n", which);
910 glBegin(which);
913 static void tess_callback_end(void)
915 TRACE("\n");
916 glEnd();
919 /***********************************************************************
920 * wglUseFontOutlines_common
922 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
923 DWORD first,
924 DWORD count,
925 DWORD listBase,
926 FLOAT deviation,
927 FLOAT extrusion,
928 int format,
929 LPGLYPHMETRICSFLOAT lpgmf,
930 BOOL unicode)
932 UINT glyph;
933 const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
934 GLUtesselator *tess;
935 LOGFONTW lf;
936 HFONT old_font, unscaled_font;
937 UINT em_size = 1024;
938 RECT rc;
940 TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
941 listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
944 ENTER_GL();
945 tess = gluNewTess();
946 if(tess)
948 gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
949 gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
950 gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
952 LEAVE_GL();
954 if(!tess) return FALSE;
956 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
957 rc.left = rc.right = rc.bottom = 0;
958 rc.top = em_size;
959 DPtoLP(hdc, (POINT*)&rc, 2);
960 lf.lfHeight = -abs(rc.top - rc.bottom);
961 lf.lfOrientation = lf.lfEscapement = 0;
962 unscaled_font = CreateFontIndirectW(&lf);
963 old_font = SelectObject(hdc, unscaled_font);
965 for (glyph = first; glyph < first + count; glyph++)
967 DWORD needed;
968 GLYPHMETRICS gm;
969 BYTE *buf;
970 TTPOLYGONHEADER *pph;
971 TTPOLYCURVE *ppc;
972 GLdouble *vertices;
974 if(unicode)
975 needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
976 else
977 needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
979 if(needed == GDI_ERROR)
980 goto error;
982 buf = HeapAlloc(GetProcessHeap(), 0, needed);
983 vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
985 if(unicode)
986 GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
987 else
988 GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
990 TRACE("glyph %d\n", glyph);
992 if(lpgmf)
994 lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
995 lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
996 lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
997 lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
998 lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
999 lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
1001 TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
1002 lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
1003 lpgmf++;
1006 ENTER_GL();
1007 glNewList(listBase++, GL_COMPILE);
1008 gluTessBeginPolygon(tess, NULL);
1010 pph = (TTPOLYGONHEADER*)buf;
1011 while((BYTE*)pph < buf + needed)
1013 TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
1015 gluTessBeginContour(tess);
1017 fixed_to_double(pph->pfxStart, em_size, vertices);
1018 gluTessVertex(tess, vertices, vertices);
1019 vertices += 3;
1021 ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
1022 while((char*)ppc < (char*)pph + pph->cb)
1024 int i;
1026 switch(ppc->wType) {
1027 case TT_PRIM_LINE:
1028 for(i = 0; i < ppc->cpfx; i++)
1030 TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
1031 fixed_to_double(ppc->apfx[i], em_size, vertices);
1032 gluTessVertex(tess, vertices, vertices);
1033 vertices += 3;
1035 break;
1037 case TT_PRIM_QSPLINE:
1038 for(i = 0; i < ppc->cpfx/2; i++)
1040 /* FIXME just connecting the control points for now */
1041 TRACE("\t\tcurve %d,%d %d,%d\n",
1042 ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
1043 ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
1044 fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
1045 gluTessVertex(tess, vertices, vertices);
1046 vertices += 3;
1047 fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
1048 gluTessVertex(tess, vertices, vertices);
1049 vertices += 3;
1051 break;
1052 default:
1053 ERR("\t\tcurve type = %d\n", ppc->wType);
1054 gluTessEndContour(tess);
1055 goto error_in_list;
1058 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
1059 (ppc->cpfx - 1) * sizeof(POINTFX));
1061 gluTessEndContour(tess);
1062 pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
1065 error_in_list:
1066 gluTessEndPolygon(tess);
1067 glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
1068 glEndList();
1069 LEAVE_GL();
1070 HeapFree(GetProcessHeap(), 0, buf);
1071 HeapFree(GetProcessHeap(), 0, vertices);
1074 error:
1075 DeleteObject(SelectObject(hdc, old_font));
1076 gluDeleteTess(tess);
1077 return TRUE;
1081 #else /* HAVE_GL_GLU_H */
1083 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
1084 DWORD first,
1085 DWORD count,
1086 DWORD listBase,
1087 FLOAT deviation,
1088 FLOAT extrusion,
1089 int format,
1090 LPGLYPHMETRICSFLOAT lpgmf,
1091 BOOL unicode)
1093 FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
1094 return FALSE;
1097 #endif /* HAVE_GL_GLU_H */
1099 /***********************************************************************
1100 * wglUseFontOutlinesA (OPENGL32.@)
1102 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
1103 DWORD first,
1104 DWORD count,
1105 DWORD listBase,
1106 FLOAT deviation,
1107 FLOAT extrusion,
1108 int format,
1109 LPGLYPHMETRICSFLOAT lpgmf)
1111 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
1114 /***********************************************************************
1115 * wglUseFontOutlinesW (OPENGL32.@)
1117 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
1118 DWORD first,
1119 DWORD count,
1120 DWORD listBase,
1121 FLOAT deviation,
1122 FLOAT extrusion,
1123 int format,
1124 LPGLYPHMETRICSFLOAT lpgmf)
1126 return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
1129 const GLubyte * internal_glGetString(GLenum name) {
1130 const char* GL_Extensions = NULL;
1132 if (GL_EXTENSIONS != name) {
1133 return glGetString(name);
1136 if (NULL == internal_gl_extensions) {
1137 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
1139 TRACE("GL_EXTENSIONS reported:\n");
1140 if (NULL == GL_Extensions) {
1141 ERR("GL_EXTENSIONS returns NULL\n");
1142 return NULL;
1143 } else {
1144 size_t len = strlen(GL_Extensions);
1145 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
1147 while (*GL_Extensions != 0x00) {
1148 const char* Start = GL_Extensions;
1149 char ThisExtn[256];
1151 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1152 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
1153 GL_Extensions++;
1155 memcpy(ThisExtn, Start, (GL_Extensions - Start));
1156 TRACE("- %s:", ThisExtn);
1158 /* test if supported API is disabled by config */
1159 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
1160 strcat(internal_gl_extensions, " ");
1161 strcat(internal_gl_extensions, ThisExtn);
1162 TRACE(" active\n");
1163 } else {
1164 TRACE(" deactived (by config)\n");
1167 if (*GL_Extensions == ' ') GL_Extensions++;
1171 return (const GLubyte *) internal_gl_extensions;
1174 void internal_glGetIntegerv(GLenum pname, GLint* params) {
1175 glGetIntegerv(pname, params);
1176 if (pname == GL_DEPTH_BITS) {
1177 GLXContext gl_ctx = glXGetCurrentContext();
1178 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
1179 /*TRACE("returns Wine Ctx as %p\n", ret);*/
1180 /**
1181 * if we cannot find a Wine Context
1182 * we only have the default wine desktop context,
1183 * so if we have only a 24 depth say we have 32
1185 if (NULL == ret && 24 == *params) {
1186 *params = 32;
1188 TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
1190 if (pname == GL_ALPHA_BITS) {
1191 GLint tmp;
1192 GLXContext gl_ctx = glXGetCurrentContext();
1193 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
1194 glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
1195 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
1196 *params = tmp;
1201 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
1202 include all dependencies
1204 #ifndef SONAME_LIBGL
1205 #define SONAME_LIBGL "libGL.so"
1206 #endif
1208 static void wgl_initialize_glx(Display *display, int screen, glXGetProcAddressARB_t proc)
1210 const char *server_glx_version = glXQueryServerString(display, screen, GLX_VERSION);
1211 const char *server_glx_extensions = glXQueryServerString(display, screen, GLX_EXTENSIONS);
1213 const char *client_glx_version = glXGetClientString(display, GLX_VERSION);
1214 const char *client_glx_extensions = glXGetClientString(display, GLX_EXTENSIONS);
1215 const char *glx_extensions = glXQueryExtensionsString(display, screen);
1218 memset(&wine_glx, 0, sizeof(wine_glx));
1220 if (!strcmp("1.2", server_glx_version)) {
1221 wine_glx.version = 2;
1222 } else {
1223 wine_glx.version = 3;
1226 if (2 < wine_glx.version) {
1227 wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfig");
1228 wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttrib");
1229 wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfig");
1231 /*wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");*/
1232 wine_glx.p_glXQueryDrawable = proc( (const GLubyte *) "glXQueryDrawable");
1233 } else {
1234 if (NULL != strstr(server_glx_extensions, "GLX_SGIX_fbconfig")) {
1235 wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfigSGIX");
1236 wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttribSGIX");
1237 wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfigSGIX");
1238 } else {
1239 ERR(" glx_version as %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", server_glx_version);
1242 /** try anyway to retrieve that calls, maybe they works using glx client tricks */
1243 wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");
1244 wine_glx.p_glXMakeContextCurrent = proc( (const GLubyte *) "glXMakeContextCurrent");
1247 /* This is for brain-dead applications that use OpenGL functions before even
1248 creating a rendering context.... */
1249 static BOOL process_attach(void)
1251 XWindowAttributes win_attr;
1252 Visual *rootVisual;
1253 int num;
1254 XVisualInfo template;
1255 HDC hdc;
1256 XVisualInfo *vis = NULL;
1257 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
1258 HMODULE mod = GetModuleHandleA( "winex11.drv" );
1259 void *opengl_handle;
1260 DWORD size = sizeof(internal_gl_disabled_extensions);
1261 HKEY hkey = 0;
1263 if (!root || !mod)
1265 ERR("X11DRV not loaded. Cannot create default context.\n");
1266 return FALSE;
1269 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
1270 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
1272 hdc = GetDC(0);
1273 default_display = get_display( hdc );
1274 ReleaseDC( 0, hdc );
1275 if (!default_display)
1277 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
1278 return FALSE;
1281 ENTER_GL();
1283 /* Try to get the visual from the Root Window. We can't use the standard (presumably
1284 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
1285 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
1286 with mismatched visuals. Note that the Root Window visual may not be double
1287 buffered, so apps actually attempting to render this way may flicker */
1288 if (XGetWindowAttributes( default_display, root, &win_attr ))
1290 rootVisual = win_attr.visual;
1292 else
1294 /* Get the default visual, since we can't seem to get the attributes from the
1295 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
1296 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
1299 template.visualid = XVisualIDFromVisual(rootVisual);
1300 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
1301 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
1302 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
1303 XFree(vis);
1304 LEAVE_GL();
1306 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
1307 if (opengl_handle != NULL) {
1308 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
1309 wine_dlclose(opengl_handle, NULL, 0);
1310 if (p_glXGetProcAddressARB == NULL)
1311 TRACE("could not find glXGetProcAddressARB in libGL.\n");
1314 internal_gl_disabled_extensions[0] = 0;
1315 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
1316 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
1317 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
1319 RegCloseKey(hkey);
1322 if (default_cx == NULL) {
1323 ERR("Could not create default context.\n");
1325 else
1327 /* After context initialize also the list of supported WGL extensions. */
1328 wgl_initialize_glx(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB);
1329 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
1331 return TRUE;
1335 /**********************************************************************/
1337 static void process_detach(void)
1339 glXDestroyContext(default_display, default_cx);
1341 /* Do not leak memory... */
1342 wgl_ext_finalize_extensions();
1343 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
1346 /***********************************************************************
1347 * OpenGL initialisation routine
1349 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1351 switch(reason)
1353 case DLL_PROCESS_ATTACH:
1354 opengl32_handle = hinst;
1355 DisableThreadLibraryCalls(hinst);
1356 return process_attach();
1357 case DLL_PROCESS_DETACH:
1358 process_detach();
1359 break;
1361 return TRUE;