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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
36 #include "opengl_ext.h"
37 #include "wine/library.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
42 /** global glx object */
45 /* x11drv GDI escapes */
46 #define X11DRV_ESCAPE 6789
47 enum x11drv_escape_codes
49 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
50 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
51 X11DRV_GET_FONT, /* get current X font for a DC */
52 X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
53 X11DRV_START_EXPOSURES, /* start graphics exposures */
54 X11DRV_END_EXPOSURES, /* end graphics exposures */
55 X11DRV_GET_DCE, /* get the DCE pointer */
56 X11DRV_SET_DCE, /* set the DCE pointer */
57 X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
58 X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
61 void (*wine_tsx11_lock_ptr)(void) = NULL;
62 void (*wine_tsx11_unlock_ptr)(void) = NULL;
64 static GLXContext default_cx = NULL;
65 static Display *default_display; /* display to use for default context */
67 static HMODULE opengl32_handle;
69 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
71 static char internal_gl_disabled_extensions[512];
72 static char* internal_gl_extensions = NULL;
74 typedef struct wine_glcontext {
80 struct wine_glcontext *next;
81 struct wine_glcontext *prev;
83 static Wine_GLContext *context_list;
85 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx)
88 for (ret = context_list; ret; ret = ret->next) if (ctx == ret->ctx) break;
96 enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
98 wine_tsx11_lock_ptr();
99 gl_ctx = glXGetCurrentContext();
101 ctx = get_context_from_GLXContext(gl_ctx);
102 wine_tsx11_unlock_ptr(); /* unlock before calling GDI apis */
104 if(ctx && GetObjectType(ctx->hdc) == OBJ_MEMDC)
105 ExtEscape(ctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
107 wine_tsx11_lock_ptr();
111 static inline void free_context(Wine_GLContext *context)
113 if (context->next != NULL) context->next->prev = context->prev;
114 if (context->prev != NULL) context->prev->next = context->next;
115 else context_list = context->next;
117 HeapFree(GetProcessHeap(), 0, context);
120 static inline Wine_GLContext *alloc_context(void)
124 if ((ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext))))
126 ret->next = context_list;
127 if (context_list) context_list->prev = ret;
133 inline static BOOL is_valid_context( Wine_GLContext *ctx )
136 for (ptr = context_list; ptr; ptr = ptr->next) if (ptr == ctx) break;
137 return (ptr != NULL);
140 /* retrieve the X display to use on a given DC */
141 inline static Display *get_display( HDC hdc )
144 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
146 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
147 sizeof(display), (LPSTR)&display )) display = NULL;
152 /* retrieve the GLX drawable to use on a given DC */
153 inline static Drawable get_drawable( HDC hdc )
155 GLXDrawable drawable;
156 enum x11drv_escape_codes escape = X11DRV_GET_GLX_DRAWABLE;
158 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
159 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
163 /** for use of wglGetCurrentReadDCARB */
164 inline static HDC get_hdc_from_Drawable(GLXDrawable d)
167 for (ret = context_list; ret; ret = ret->next) {
168 if (d == get_drawable( ret->hdc )) {
175 /* retrieve the X font to use on a given DC */
176 inline static Font get_font( HDC hdc )
179 enum x11drv_escape_codes escape = X11DRV_GET_FONT;
181 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
182 sizeof(font), (LPSTR)&font )) font = 0;
187 /***********************************************************************
188 * wglCreateContext (OPENGL32.@)
190 HGLRC WINAPI wglCreateContext(HDC hdc)
194 XVisualInfo template;
195 XVisualInfo *vis = NULL;
196 Display *display = get_display( hdc );
197 int hdcPF = GetPixelFormat(hdc);
200 TRACE("(%p)->(PF:%d)\n", hdc, hdcPF);
202 /* First, get the visual in use by the X11DRV */
203 if (!display) return 0;
204 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
205 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
208 ERR("NULL visual !!!\n");
209 /* Need to set errors here */
213 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
219 GLXFBConfig* cfgs_fmt = NULL;
222 cfgs_fmt = wine_glx.p_glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt);
223 if (NULL == cfgs_fmt || 0 == nCfgs_fmt) {
224 ERR("Cannot get FB Configs, expect problems.\n");
225 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
228 if (nCfgs_fmt < hdcPF) {
229 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, nCfgs_fmt);
230 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
233 cur_cfg = cfgs_fmt[hdcPF - 1];
234 gl_test = wine_glx.p_glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value);
236 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
237 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
243 /* The context will be allocated in the wglMakeCurrent call */
245 ret = alloc_context();
248 ret->display = display;
249 ret->fb_conf = cur_cfg;
251 ret->vis = wine_glx.p_glXGetVisualFromFBConfig(display, cur_cfg);
253 TRACE(" creating context %p (GL context creation delayed)\n", ret);
257 /***********************************************************************
258 * wglCreateLayerContext (OPENGL32.@)
260 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
262 TRACE("(%p,%d)\n", hdc, iLayerPlane);
264 if (iLayerPlane == 0) {
265 return wglCreateContext(hdc);
267 FIXME(" no handler for layer %d\n", iLayerPlane);
272 /***********************************************************************
273 * wglCopyContext (OPENGL32.@)
275 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
278 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
283 /***********************************************************************
284 * wglDeleteContext (OPENGL32.@)
286 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
288 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
291 TRACE("(%p)\n", hglrc);
294 /* A game (Half Life not to name it) deletes twice the same context,
295 * so make sure it is valid first */
296 if (is_valid_context( ctx ))
298 if (ctx->ctx) glXDestroyContext(ctx->display, ctx->ctx);
303 WARN("Error deleting context !\n");
304 SetLastError(ERROR_INVALID_HANDLE);
312 /***********************************************************************
313 * wglDescribeLayerPlane (OPENGL32.@)
315 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
319 LPLAYERPLANEDESCRIPTOR plpd) {
320 FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
325 /***********************************************************************
326 * wglGetCurrentContext (OPENGL32.@)
328 HGLRC WINAPI wglGetCurrentContext(void) {
335 gl_ctx = glXGetCurrentContext();
336 ret = get_context_from_GLXContext(gl_ctx);
339 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
344 /***********************************************************************
345 * wglGetCurrentDC (OPENGL32.@)
347 HDC WINAPI wglGetCurrentDC(void) {
354 gl_ctx = glXGetCurrentContext();
355 ret = get_context_from_GLXContext(gl_ctx);
359 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
362 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
367 /***********************************************************************
368 * wglGetLayerPaletteEntries (OPENGL32.@)
370 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
374 const COLORREF *pcr) {
375 FIXME("(): stub !\n");
380 /***********************************************************************
381 * wglGetProcAddress (OPENGL32.@)
383 static int compar(const void *elt_a, const void *elt_b) {
384 return strcmp(((const OpenGL_extension *) elt_a)->name,
385 ((const OpenGL_extension *) elt_b)->name);
388 static int wgl_compar(const void *elt_a, const void *elt_b) {
389 return strcmp(((const WGL_extension *) elt_a)->func_name,
390 ((const WGL_extension *) elt_b)->func_name);
393 PROC WINAPI wglGetProcAddress(LPCSTR lpszProc) {
395 OpenGL_extension ext;
396 OpenGL_extension *ext_ret;
398 TRACE("(%s)\n", lpszProc);
400 /* First, look if it's not already defined in the 'standard' OpenGL functions */
401 if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
402 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
406 if (p_glXGetProcAddressARB == NULL) {
407 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
411 /* After that, search in the thunks to find the real name of the extension */
412 ext.name = (char *) lpszProc;
413 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
414 extension_registry_size, sizeof(OpenGL_extension), compar);
416 if (ext_ret == NULL) {
417 WGL_extension wgl_ext, *wgl_ext_ret;
419 /* Try to find the function in the WGL extensions ... */
420 wgl_ext.func_name = (char *) lpszProc;
421 wgl_ext_ret = (WGL_extension *) bsearch(&wgl_ext, wgl_extension_registry,
422 wgl_extension_registry_size, sizeof(WGL_extension), wgl_compar);
424 if (wgl_ext_ret == NULL) {
425 /* Some sanity checks :-) */
427 local_func = p_glXGetProcAddressARB( (const GLubyte *) lpszProc);
429 if (local_func != NULL) {
430 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc);
434 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
439 if (wgl_ext_ret->func_init != NULL) {
441 if ((err_msg = wgl_ext_ret->func_init(p_glXGetProcAddressARB,
442 wgl_ext_ret->context)) == NULL) {
443 ret = wgl_ext_ret->func_address;
445 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc), err_msg);
449 ret = wgl_ext_ret->func_address;
453 TRACE(" returning WGL function (%p)\n", ret);
458 local_func = p_glXGetProcAddressARB( (const GLubyte*) ext_ret->glx_name);
461 /* After that, look at the extensions defined in the Linux OpenGL library */
462 if (local_func == NULL) {
466 /* Remove the 3 last letters (EXT, ARB, ...).
468 I know that some extensions have more than 3 letters (MESA, NV,
469 INTEL, ...), but this is only a stop-gap measure to fix buggy
470 OpenGL drivers (moreover, it is only useful for old 1.0 apps
471 that query the glBindTextureEXT extension).
473 memcpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
474 buf[strlen(ext_ret->glx_name) - 3] = '\0';
475 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
477 ret = GetProcAddress(opengl32_handle, buf);
479 TRACE(" found function in main OpenGL library (%p) !\n", ret);
481 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
486 TRACE(" returning function (%p)\n", ext_ret->func);
487 *(ext_ret->func_ptr) = local_func;
489 return ext_ret->func;
494 static int describeContext(Wine_GLContext* ctx) {
497 TRACE(" Context %p have (vis:%p):\n", ctx, ctx->vis);
498 wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_FBCONFIG_ID, &tmp);
499 TRACE(" - FBCONFIG_ID 0x%x\n", tmp);
500 wine_glx.p_glXGetFBConfigAttrib(ctx->display, ctx->fb_conf, GLX_VISUAL_ID, &tmp);
501 TRACE(" - VISUAL_ID 0x%x\n", tmp);
506 static int describeDrawable(Wine_GLContext* ctx, Drawable drawable) {
509 if (3 > wine_glx.version || NULL == wine_glx.p_glXQueryDrawable) {
510 /** glXQueryDrawable not available so returns not supported */
513 TRACE(" Drawable %p have :\n", (void*) drawable);
514 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_FBCONFIG_ID, (unsigned int*) &tmp);
515 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp);
516 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_VISUAL_ID, (unsigned int*) &tmp);
517 TRACE(" - VISUAL_ID as 0x%x\n", tmp);
519 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_WIDTH, (unsigned int*) &tmp);
520 TRACE(" - WIDTH as %d\n", tmp);
521 wine_glx.p_glXQueryDrawable(ctx->display, drawable, GLX_HEIGHT, (unsigned int*) &tmp);
522 TRACE(" - HEIGHT as %d\n", tmp);
526 /***********************************************************************
527 * wglMakeCurrent (OPENGL32.@)
529 BOOL WINAPI wglMakeCurrent(HDC hdc,
532 DWORD type = GetObjectType(hdc);
534 TRACE("(%p,%p)\n", hdc, hglrc);
538 ret = glXMakeCurrent(default_display, None, NULL);
540 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
541 Drawable drawable = get_drawable( hdc );
542 if (ctx->ctx == NULL) {
543 int draw_vis_id, ctx_vis_id;
544 VisualID visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
545 TRACE(" Wine desktop VISUAL_ID is 0x%x\n", (unsigned int) visualid);
546 draw_vis_id = describeDrawable(ctx, drawable);
547 ctx_vis_id = describeContext(ctx);
549 if (-1 == draw_vis_id || (draw_vis_id == visualid && draw_vis_id != ctx_vis_id)) {
551 * Inherits from root window so reuse desktop visual
553 XVisualInfo template;
556 template.visualid = visualid;
557 vis = XGetVisualInfo(ctx->display, VisualIDMask, &template, &num);
559 TRACE(" Creating GLX Context\n");
560 ctx->ctx = glXCreateContext(ctx->display, vis, NULL, type == OBJ_MEMDC ? False : True);
562 TRACE(" Creating GLX Context\n");
563 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, type == OBJ_MEMDC ? False : True);
565 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
567 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx->display, (void*) drawable, ctx->ctx);
568 ret = glXMakeCurrent(ctx->display, drawable, ctx->ctx);
569 if(ret && type == OBJ_MEMDC)
570 glDrawBuffer(GL_FRONT_LEFT);
573 TRACE(" returning %s\n", (ret ? "True" : "False"));
577 /***********************************************************************
578 * wglMakeContextCurrentARB (OPENGL32.@)
580 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
583 TRACE("(%p,%p,%p)\n", hDrawDC, hReadDC, hglrc);
587 ret = glXMakeCurrent(default_display, None, NULL);
589 if (NULL == wine_glx.p_glXMakeContextCurrent) {
592 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
593 Drawable d_draw = get_drawable( hDrawDC );
594 Drawable d_read = get_drawable( hReadDC );
596 if (ctx->ctx == NULL) {
597 ctx->ctx = glXCreateContext(ctx->display, ctx->vis, NULL, GetObjectType(hDrawDC) == OBJ_MEMDC ? False : True);
598 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
600 ret = wine_glx.p_glXMakeContextCurrent(ctx->display, d_draw, d_read, ctx->ctx);
605 TRACE(" returning %s\n", (ret ? "True" : "False"));
609 /***********************************************************************
610 * wglGetCurrentReadDCARB (OPENGL32.@)
612 HDC WINAPI wglGetCurrentReadDCARB(void)
620 gl_d = glXGetCurrentReadDrawable();
621 ret = get_hdc_from_Drawable(gl_d);
624 TRACE(" returning %p (GL drawable %lu)\n", ret, gl_d);
630 /***********************************************************************
631 * wglRealizeLayerPalette (OPENGL32.@)
633 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
641 /***********************************************************************
642 * wglSetLayerPaletteEntries (OPENGL32.@)
644 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
648 const COLORREF *pcr) {
649 FIXME("(): stub !\n");
654 /***********************************************************************
655 * wglShareLists (OPENGL32.@)
657 BOOL WINAPI wglShareLists(HGLRC hglrc1,
659 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
660 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
662 TRACE("(%p, %p)\n", org, dest);
664 if (NULL != dest && dest->ctx != NULL) {
665 ERR("Could not share display lists, context already created !\n");
668 if (org->ctx == NULL) {
670 describeContext(org);
671 org->ctx = glXCreateContext(org->display, org->vis, NULL, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
673 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
677 describeContext(dest);
678 /* Create the destination context with display lists shared */
679 dest->ctx = glXCreateContext(org->display, dest->vis, org->ctx, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True);
681 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
688 /***********************************************************************
689 * wglSwapLayerBuffers (OPENGL32.@)
691 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
693 TRACE("(%p, %08x)\n", hdc, fuPlanes);
695 if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
696 if (!SwapBuffers(hdc)) return FALSE;
697 fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
701 WARN("Following layers unhandled : %08x\n", fuPlanes);
707 static BOOL internal_wglUseFontBitmaps(HDC hdc,
711 DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
713 /* We are running using client-side rendering fonts... */
717 void *bitmap = NULL, *gl_bitmap = NULL;
721 glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
722 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
725 for (glyph = first; glyph < first + count; glyph++) {
726 unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
727 int height, width_int;
729 TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
730 if (needed_size == GDI_ERROR) {
731 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size);
734 TRACE(" - needed size : %d\n", needed_size);
737 if (needed_size > size) {
739 HeapFree(GetProcessHeap(), 0, bitmap);
740 HeapFree(GetProcessHeap(), 0, gl_bitmap);
741 bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
742 gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
744 if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
745 if (TRACE_ON(opengl)) {
746 unsigned int height, width, bitmask;
747 unsigned char *bitmap_ = (unsigned char *) bitmap;
749 TRACE(" - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
750 TRACE(" - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
751 TRACE(" - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
752 if (needed_size != 0) {
753 TRACE(" - bitmap :\n");
754 for (height = 0; height < gm.gmBlackBoxY; height++) {
756 for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
761 if (*bitmap_ & bitmask)
766 bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
772 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
773 * glyph for it to be drawn properly.
775 if (needed_size != 0) {
776 width_int = (gm.gmBlackBoxX + 31) / 32;
777 for (height = 0; height < gm.gmBlackBoxY; height++) {
779 for (width = 0; width < width_int; width++) {
780 ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
781 ((int *) bitmap)[height * width_int + width];
787 glNewList(listBase++, GL_COMPILE);
788 if (needed_size != 0) {
789 glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
790 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
791 gm.gmCellIncX, gm.gmCellIncY,
794 /* This is the case of 'empty' glyphs like the space character */
795 glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
802 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
805 HeapFree(GetProcessHeap(), 0, bitmap);
806 HeapFree(GetProcessHeap(), 0, gl_bitmap);
811 glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
814 HeapFree(GetProcessHeap(), 0, bitmap);
815 HeapFree(GetProcessHeap(), 0, gl_bitmap);
819 /***********************************************************************
820 * wglUseFontBitmapsA (OPENGL32.@)
822 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
827 Font fid = get_font( hdc );
829 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
832 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
836 /* I assume that the glyphs are at the same position for X and for Windows */
837 glXUseXFont(fid, first, count, listBase);
842 /***********************************************************************
843 * wglUseFontBitmapsW (OPENGL32.@)
845 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
850 Font fid = get_font( hdc );
852 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
855 return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
858 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
861 /* I assume that the glyphs are at the same position for X and for Windows */
862 glXUseXFont(fid, first, count, listBase);
867 /***********************************************************************
868 * wglUseFontOutlinesA (OPENGL32.@)
870 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
877 LPGLYPHMETRICSFLOAT lpgmf) {
878 FIXME("(): stub !\n");
883 const GLubyte * internal_glGetString(GLenum name) {
884 const char* GL_Extensions = NULL;
886 if (GL_EXTENSIONS != name) {
887 return glGetString(name);
890 if (NULL == internal_gl_extensions) {
891 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
893 TRACE("GL_EXTENSIONS reported:\n");
894 if (NULL == GL_Extensions) {
895 ERR("GL_EXTENSIONS returns NULL\n");
898 size_t len = strlen(GL_Extensions);
899 internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
901 while (*GL_Extensions != 0x00) {
902 const char* Start = GL_Extensions;
905 memset(ThisExtn, 0x00, sizeof(ThisExtn));
906 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
909 memcpy(ThisExtn, Start, (GL_Extensions - Start));
910 TRACE("- %s:", ThisExtn);
912 /* test if supported API is disabled by config */
913 if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
914 strcat(internal_gl_extensions, " ");
915 strcat(internal_gl_extensions, ThisExtn);
918 TRACE(" deactived (by config)\n");
921 if (*GL_Extensions == ' ') GL_Extensions++;
925 return (const GLubyte *) internal_gl_extensions;
928 void internal_glGetIntegerv(GLenum pname, GLint* params) {
929 glGetIntegerv(pname, params);
930 if (pname == GL_DEPTH_BITS) {
931 GLXContext gl_ctx = glXGetCurrentContext();
932 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
933 /*TRACE("returns Wine Ctx as %p\n", ret);*/
935 * if we cannot find a Wine Context
936 * we only have the default wine desktop context,
937 * so if we have only a 24 depth say we have 32
939 if (NULL == ret && 24 == *params) {
942 TRACE("returns GL_DEPTH_BITS as '%d'\n", *params);
944 if (pname == GL_ALPHA_BITS) {
946 GLXContext gl_ctx = glXGetCurrentContext();
947 Wine_GLContext* ret = get_context_from_GLXContext(gl_ctx);
948 glXGetFBConfigAttrib(ret->display, ret->fb_conf, GLX_ALPHA_SIZE, &tmp);
949 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp);
955 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
956 include all dependencies
959 #define SONAME_LIBGL "libGL.so"
962 static void wgl_initialize_glx(Display *display, int screen, glXGetProcAddressARB_t proc)
964 const char *server_glx_version = glXQueryServerString(display, screen, GLX_VERSION);
965 const char *server_glx_extensions = glXQueryServerString(display, screen, GLX_EXTENSIONS);
967 const char *client_glx_version = glXGetClientString(display, GLX_VERSION);
968 const char *client_glx_extensions = glXGetClientString(display, GLX_EXTENSIONS);
969 const char *glx_extensions = glXQueryExtensionsString(display, screen);
972 memset(&wine_glx, 0, sizeof(wine_glx));
974 if (!strcmp("1.2", server_glx_version)) {
975 wine_glx.version = 2;
977 wine_glx.version = 3;
980 if (2 < wine_glx.version) {
981 wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfig");
982 wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttrib");
983 wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfig");
985 /*wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");*/
986 wine_glx.p_glXQueryDrawable = proc( (const GLubyte *) "glXQueryDrawable");
988 if (NULL != strstr(server_glx_extensions, "GLX_SGIX_fbconfig")) {
989 wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfigSGIX");
990 wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttribSGIX");
991 wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfigSGIX");
993 ERR(" glx_version as %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", server_glx_version);
996 /** try anyway to retrieve that calls, maybe they works using glx client tricks */
997 wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");
998 wine_glx.p_glXMakeContextCurrent = proc( (const GLubyte *) "glXMakeContextCurrent");
1001 /* This is for brain-dead applications that use OpenGL functions before even
1002 creating a rendering context.... */
1003 static BOOL process_attach(void)
1005 XWindowAttributes win_attr;
1008 XVisualInfo template;
1010 XVisualInfo *vis = NULL;
1011 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
1012 HMODULE mod = GetModuleHandleA( "winex11.drv" );
1013 void *opengl_handle;
1014 DWORD size = sizeof(internal_gl_disabled_extensions);
1019 ERR("X11DRV not loaded. Cannot create default context.\n");
1023 wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
1024 wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
1027 default_display = get_display( hdc );
1028 ReleaseDC( 0, hdc );
1029 if (!default_display)
1031 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
1037 /* Try to get the visual from the Root Window. We can't use the standard (presumably
1038 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
1039 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
1040 with mismatched visuals. Note that the Root Window visual may not be double
1041 buffered, so apps actually attempting to render this way may flicker */
1042 if (XGetWindowAttributes( default_display, root, &win_attr ))
1044 rootVisual = win_attr.visual;
1048 /* Get the default visual, since we can't seem to get the attributes from the
1049 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
1050 rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
1053 template.visualid = XVisualIDFromVisual(rootVisual);
1054 vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
1055 if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
1056 if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
1060 opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
1061 if (opengl_handle != NULL) {
1062 p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
1063 wine_dlclose(opengl_handle, NULL, 0);
1064 if (p_glXGetProcAddressARB == NULL)
1065 TRACE("could not find glXGetProcAddressARB in libGL.\n");
1068 internal_gl_disabled_extensions[0] = 0;
1069 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
1070 if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
1071 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
1076 if (default_cx == NULL) {
1077 ERR("Could not create default context.\n");
1081 /* After context initialize also the list of supported WGL extensions. */
1082 wgl_initialize_glx(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB);
1083 wgl_ext_initialize_extensions(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB, internal_gl_disabled_extensions);
1089 /**********************************************************************/
1091 static void process_detach(void)
1093 glXDestroyContext(default_display, default_cx);
1095 /* Do not leak memory... */
1096 wgl_ext_finalize_extensions();
1097 if (NULL != internal_gl_extensions) {
1098 HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
1102 /***********************************************************************
1103 * OpenGL initialisation routine
1105 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1109 case DLL_PROCESS_ATTACH:
1110 opengl32_handle = hinst;
1111 DisableThreadLibraryCalls(hinst);
1112 return process_attach();
1113 case DLL_PROCESS_DETACH: