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 */
60 void (*wine_tsx11_lock_ptr
)(void) = NULL
;
61 void (*wine_tsx11_unlock_ptr
)(void) = NULL
;
63 static GLXContext default_cx
= NULL
;
64 static Display
*default_display
; /* display to use for default context */
66 static HMODULE opengl32_handle
;
68 static glXGetProcAddressARB_t p_glXGetProcAddressARB
= NULL
;
70 static char internal_gl_disabled_extensions
[512];
71 static char* internal_gl_extensions
= NULL
;
73 typedef struct wine_glcontext
{
79 struct wine_glcontext
*next
;
80 struct wine_glcontext
*prev
;
82 static Wine_GLContext
*context_list
;
84 static inline Wine_GLContext
*get_context_from_GLXContext(GLXContext ctx
)
87 for (ret
= context_list
; ret
; ret
= ret
->next
) if (ctx
== ret
->ctx
) break;
91 static inline void free_context(Wine_GLContext
*context
)
93 if (context
->next
!= NULL
) context
->next
->prev
= context
->prev
;
94 if (context
->prev
!= NULL
) context
->prev
->next
= context
->next
;
95 else context_list
= context
->next
;
97 HeapFree(GetProcessHeap(), 0, context
);
100 static inline Wine_GLContext
*alloc_context(void)
104 if ((ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(Wine_GLContext
))))
106 ret
->next
= context_list
;
107 if (context_list
) context_list
->prev
= ret
;
113 inline static BOOL
is_valid_context( Wine_GLContext
*ctx
)
116 for (ptr
= context_list
; ptr
; ptr
= ptr
->next
) if (ptr
== ctx
) break;
117 return (ptr
!= NULL
);
120 /* retrieve the X display to use on a given DC */
121 inline static Display
*get_display( HDC hdc
)
124 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
126 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
127 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
132 /* retrieve the GLX drawable to use on a given DC */
133 inline static Drawable
get_drawable( HDC hdc
)
135 GLXDrawable drawable
;
136 enum x11drv_escape_codes escape
= X11DRV_GET_GLX_DRAWABLE
;
138 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
139 sizeof(drawable
), (LPSTR
)&drawable
)) drawable
= 0;
143 /** for use of wglGetCurrentReadDCARB */
144 inline static HDC
get_hdc_from_Drawable(GLXDrawable d
)
147 for (ret
= context_list
; ret
; ret
= ret
->next
) {
148 if (d
== get_drawable( ret
->hdc
)) {
155 /* retrieve the X font to use on a given DC */
156 inline static Font
get_font( HDC hdc
)
159 enum x11drv_escape_codes escape
= X11DRV_GET_FONT
;
161 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
162 sizeof(font
), (LPSTR
)&font
)) font
= 0;
167 /***********************************************************************
168 * wglCreateContext (OPENGL32.@)
170 HGLRC WINAPI
wglCreateContext(HDC hdc
)
174 XVisualInfo
template;
175 XVisualInfo
*vis
= NULL
;
176 Display
*display
= get_display( hdc
);
177 int hdcPF
= GetPixelFormat(hdc
);
180 TRACE("(%p)->(PF:%d)\n", hdc
, hdcPF
);
182 /* First, get the visual in use by the X11DRV */
183 if (!display
) return 0;
184 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
185 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
188 ERR("NULL visual !!!\n");
189 /* Need to set errors here */
193 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
199 GLXFBConfig
* cfgs_fmt
= NULL
;
202 cfgs_fmt
= wine_glx
.p_glXGetFBConfigs(display
, DefaultScreen(display
), &nCfgs_fmt
);
203 if (NULL
== cfgs_fmt
|| 0 == nCfgs_fmt
) {
204 ERR("Cannot get FB Configs, expect problems.\n");
205 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
208 if (nCfgs_fmt
< hdcPF
) {
209 ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc
, hdcPF
, nCfgs_fmt
);
210 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
213 cur_cfg
= cfgs_fmt
[hdcPF
- 1];
214 gl_test
= wine_glx
.p_glXGetFBConfigAttrib(display
, cur_cfg
, GLX_FBCONFIG_ID
, &value
);
216 ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n");
217 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
223 /* The context will be allocated in the wglMakeCurrent call */
225 ret
= alloc_context();
228 ret
->display
= display
;
229 ret
->fb_conf
= cur_cfg
;
231 ret
->vis
= wine_glx
.p_glXGetVisualFromFBConfig(display
, cur_cfg
);
233 TRACE(" creating context %p (GL context creation delayed)\n", ret
);
237 /***********************************************************************
238 * wglCreateLayerContext (OPENGL32.@)
240 HGLRC WINAPI
wglCreateLayerContext(HDC hdc
,
242 TRACE("(%p,%d)\n", hdc
, iLayerPlane
);
244 if (iLayerPlane
== 0) {
245 return wglCreateContext(hdc
);
247 FIXME(" no handler for layer %d\n", iLayerPlane
);
252 /***********************************************************************
253 * wglCopyContext (OPENGL32.@)
255 BOOL WINAPI
wglCopyContext(HGLRC hglrcSrc
,
258 FIXME("(%p,%p,%d)\n", hglrcSrc
, hglrcDst
, mask
);
263 /***********************************************************************
264 * wglDeleteContext (OPENGL32.@)
266 BOOL WINAPI
wglDeleteContext(HGLRC hglrc
)
268 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
271 TRACE("(%p)\n", hglrc
);
274 /* A game (Half Life not to name it) deletes twice the same context,
275 * so make sure it is valid first */
276 if (is_valid_context( ctx
))
278 if (ctx
->ctx
) glXDestroyContext(ctx
->display
, ctx
->ctx
);
283 WARN("Error deleting context !\n");
284 SetLastError(ERROR_INVALID_HANDLE
);
292 /***********************************************************************
293 * wglDescribeLayerPlane (OPENGL32.@)
295 BOOL WINAPI
wglDescribeLayerPlane(HDC hdc
,
299 LPLAYERPLANEDESCRIPTOR plpd
) {
300 FIXME("(%p,%d,%d,%d,%p)\n", hdc
, iPixelFormat
, iLayerPlane
, nBytes
, plpd
);
305 /***********************************************************************
306 * wglGetCurrentContext (OPENGL32.@)
308 HGLRC WINAPI
wglGetCurrentContext(void) {
315 gl_ctx
= glXGetCurrentContext();
316 ret
= get_context_from_GLXContext(gl_ctx
);
319 TRACE(" returning %p (GL context %p)\n", ret
, gl_ctx
);
324 /***********************************************************************
325 * wglGetCurrentDC (OPENGL32.@)
327 HDC WINAPI
wglGetCurrentDC(void) {
334 gl_ctx
= glXGetCurrentContext();
335 ret
= get_context_from_GLXContext(gl_ctx
);
339 TRACE(" returning %p (GL context %p - Wine context %p)\n", ret
->hdc
, gl_ctx
, ret
);
342 TRACE(" no Wine context found for GLX context %p\n", gl_ctx
);
347 /***********************************************************************
348 * wglGetLayerPaletteEntries (OPENGL32.@)
350 int WINAPI
wglGetLayerPaletteEntries(HDC hdc
,
354 const COLORREF
*pcr
) {
355 FIXME("(): stub !\n");
360 /***********************************************************************
361 * wglGetProcAddress (OPENGL32.@)
363 static int compar(const void *elt_a
, const void *elt_b
) {
364 return strcmp(((const OpenGL_extension
*) elt_a
)->name
,
365 ((const OpenGL_extension
*) elt_b
)->name
);
368 static int wgl_compar(const void *elt_a
, const void *elt_b
) {
369 return strcmp(((const WGL_extension
*) elt_a
)->func_name
,
370 ((const WGL_extension
*) elt_b
)->func_name
);
373 PROC WINAPI
wglGetProcAddress(LPCSTR lpszProc
) {
375 OpenGL_extension ext
;
376 OpenGL_extension
*ext_ret
;
378 TRACE("(%s)\n", lpszProc
);
380 /* First, look if it's not already defined in the 'standard' OpenGL functions */
381 if ((local_func
= GetProcAddress(opengl32_handle
, lpszProc
)) != NULL
) {
382 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func
);
386 if (p_glXGetProcAddressARB
== NULL
) {
387 ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
391 /* After that, search in the thunks to find the real name of the extension */
392 ext
.name
= (char *) lpszProc
;
393 ext_ret
= (OpenGL_extension
*) bsearch(&ext
, extension_registry
,
394 extension_registry_size
, sizeof(OpenGL_extension
), compar
);
396 if (ext_ret
== NULL
) {
397 WGL_extension wgl_ext
, *wgl_ext_ret
;
399 /* Try to find the function in the WGL extensions ... */
400 wgl_ext
.func_name
= (char *) lpszProc
;
401 wgl_ext_ret
= (WGL_extension
*) bsearch(&wgl_ext
, wgl_extension_registry
,
402 wgl_extension_registry_size
, sizeof(WGL_extension
), wgl_compar
);
404 if (wgl_ext_ret
== NULL
) {
405 /* Some sanity checks :-) */
407 local_func
= p_glXGetProcAddressARB( (const GLubyte
*) lpszProc
);
409 if (local_func
!= NULL
) {
410 WARN("Extension %s defined in the OpenGL library but NOT in opengl_ext.c...\n", lpszProc
);
414 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc
);
419 if (wgl_ext_ret
->func_init
!= NULL
) {
421 if ((err_msg
= wgl_ext_ret
->func_init(p_glXGetProcAddressARB
,
422 wgl_ext_ret
->context
)) == NULL
) {
423 ret
= wgl_ext_ret
->func_address
;
425 WARN("Error when getting WGL extension '%s' : %s.\n", debugstr_a(lpszProc
), err_msg
);
429 ret
= wgl_ext_ret
->func_address
;
433 TRACE(" returning WGL function (%p)\n", ret
);
438 local_func
= p_glXGetProcAddressARB( (const GLubyte
*) ext_ret
->glx_name
);
441 /* After that, look at the extensions defined in the Linux OpenGL library */
442 if (local_func
== NULL
) {
446 /* Remove the 3 last letters (EXT, ARB, ...).
448 I know that some extensions have more than 3 letters (MESA, NV,
449 INTEL, ...), but this is only a stop-gap measure to fix buggy
450 OpenGL drivers (moreover, it is only useful for old 1.0 apps
451 that query the glBindTextureEXT extension).
453 memcpy(buf
, ext_ret
->glx_name
, strlen(ext_ret
->glx_name
) - 3);
454 buf
[strlen(ext_ret
->glx_name
) - 3] = '\0';
455 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf
);
457 ret
= GetProcAddress(opengl32_handle
, buf
);
459 TRACE(" found function in main OpenGL library (%p) !\n", ret
);
461 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc
, ext_ret
->glx_name
);
466 TRACE(" returning function (%p)\n", ext_ret
->func
);
467 *(ext_ret
->func_ptr
) = local_func
;
469 return ext_ret
->func
;
474 static int describeContext(Wine_GLContext
* ctx
) {
477 TRACE(" Context %p have (vis:%p):\n", ctx
, ctx
->vis
);
478 wine_glx
.p_glXGetFBConfigAttrib(ctx
->display
, ctx
->fb_conf
, GLX_FBCONFIG_ID
, &tmp
);
479 TRACE(" - FBCONFIG_ID 0x%x\n", tmp
);
480 wine_glx
.p_glXGetFBConfigAttrib(ctx
->display
, ctx
->fb_conf
, GLX_VISUAL_ID
, &tmp
);
481 TRACE(" - VISUAL_ID 0x%x\n", tmp
);
486 static int describeDrawable(Wine_GLContext
* ctx
, Drawable drawable
) {
489 if (3 > wine_glx
.version
|| NULL
== wine_glx
.p_glXQueryDrawable
) {
490 /** glXQueryDrawable not available so returns not supported */
493 TRACE(" Drawable %p have :\n", (void*) drawable
);
494 wine_glx
.p_glXQueryDrawable(ctx
->display
, drawable
, GLX_FBCONFIG_ID
, (unsigned int*) &tmp
);
495 TRACE(" - FBCONFIG_ID as 0x%x\n", tmp
);
496 wine_glx
.p_glXQueryDrawable(ctx
->display
, drawable
, GLX_VISUAL_ID
, (unsigned int*) &tmp
);
497 TRACE(" - VISUAL_ID as 0x%x\n", tmp
);
499 wine_glx
.p_glXQueryDrawable(ctx
->display
, drawable
, GLX_WIDTH
, (unsigned int*) &tmp
);
500 TRACE(" - WIDTH as %d\n", tmp
);
501 wine_glx
.p_glXQueryDrawable(ctx
->display
, drawable
, GLX_HEIGHT
, (unsigned int*) &tmp
);
502 TRACE(" - HEIGHT as %d\n", tmp
);
506 /***********************************************************************
507 * wglMakeCurrent (OPENGL32.@)
509 BOOL WINAPI
wglMakeCurrent(HDC hdc
,
512 DWORD type
= GetObjectType(hdc
);
514 TRACE("(%p,%p)\n", hdc
, hglrc
);
518 ret
= glXMakeCurrent(default_display
, None
, NULL
);
520 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
521 Drawable drawable
= get_drawable( hdc
);
522 if (ctx
->ctx
== NULL
) {
523 int draw_vis_id
, ctx_vis_id
;
524 VisualID visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
525 TRACE(" Wine desktop VISUAL_ID is 0x%x\n", (unsigned int) visualid
);
526 draw_vis_id
= describeDrawable(ctx
, drawable
);
527 ctx_vis_id
= describeContext(ctx
);
529 if (-1 == draw_vis_id
|| (draw_vis_id
== visualid
&& draw_vis_id
!= ctx_vis_id
)) {
531 * Inherits from root window so reuse desktop visual
533 XVisualInfo
template;
536 template.visualid
= visualid
;
537 vis
= XGetVisualInfo(ctx
->display
, VisualIDMask
, &template, &num
);
539 TRACE(" Creating GLX Context\n");
540 ctx
->ctx
= glXCreateContext(ctx
->display
, vis
, NULL
, True
);
542 TRACE(" Creating GLX Context\n");
543 ctx
->ctx
= glXCreateContext(ctx
->display
, ctx
->vis
, NULL
, True
);
545 TRACE(" created a delayed OpenGL context (%p)\n", ctx
->ctx
);
547 TRACE(" make current for dis %p, drawable %p, ctx %p\n", ctx
->display
, (void*) drawable
, ctx
->ctx
);
548 ret
= glXMakeCurrent(ctx
->display
, drawable
, ctx
->ctx
);
549 if(ret
&& type
== OBJ_MEMDC
)
550 glDrawBuffer(GL_FRONT_LEFT
);
553 TRACE(" returning %s\n", (ret
? "True" : "False"));
557 /***********************************************************************
558 * wglMakeContextCurrentARB (OPENGL32.@)
560 BOOL WINAPI
wglMakeContextCurrentARB(HDC hDrawDC
, HDC hReadDC
, HGLRC hglrc
)
563 TRACE("(%p,%p,%p)\n", hDrawDC
, hReadDC
, hglrc
);
567 ret
= glXMakeCurrent(default_display
, None
, NULL
);
569 if (NULL
== wine_glx
.p_glXMakeContextCurrent
) {
572 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
573 Drawable d_draw
= get_drawable( hDrawDC
);
574 Drawable d_read
= get_drawable( hReadDC
);
576 if (ctx
->ctx
== NULL
) {
577 ctx
->ctx
= glXCreateContext(ctx
->display
, ctx
->vis
, NULL
, True
);
578 TRACE(" created a delayed OpenGL context (%p)\n", ctx
->ctx
);
580 ret
= wine_glx
.p_glXMakeContextCurrent(ctx
->display
, d_draw
, d_read
, ctx
->ctx
);
585 TRACE(" returning %s\n", (ret
? "True" : "False"));
589 /***********************************************************************
590 * wglGetCurrentReadDCARB (OPENGL32.@)
592 HDC WINAPI
wglGetCurrentReadDCARB(void)
600 gl_d
= glXGetCurrentReadDrawable();
601 ret
= get_hdc_from_Drawable(gl_d
);
604 TRACE(" returning %p (GL drawable %lu)\n", ret
, gl_d
);
610 /***********************************************************************
611 * wglRealizeLayerPalette (OPENGL32.@)
613 BOOL WINAPI
wglRealizeLayerPalette(HDC hdc
,
621 /***********************************************************************
622 * wglSetLayerPaletteEntries (OPENGL32.@)
624 int WINAPI
wglSetLayerPaletteEntries(HDC hdc
,
628 const COLORREF
*pcr
) {
629 FIXME("(): stub !\n");
634 /***********************************************************************
635 * wglShareLists (OPENGL32.@)
637 BOOL WINAPI
wglShareLists(HGLRC hglrc1
,
639 Wine_GLContext
*org
= (Wine_GLContext
*) hglrc1
;
640 Wine_GLContext
*dest
= (Wine_GLContext
*) hglrc2
;
642 TRACE("(%p, %p)\n", org
, dest
);
644 if (NULL
!= dest
&& dest
->ctx
!= NULL
) {
645 ERR("Could not share display lists, context already created !\n");
648 if (org
->ctx
== NULL
) {
650 describeContext(org
);
651 org
->ctx
= glXCreateContext(org
->display
, org
->vis
, NULL
, True
);
653 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org
->ctx
, org
);
657 describeContext(dest
);
658 /* Create the destination context with display lists shared */
659 dest
->ctx
= glXCreateContext(org
->display
, dest
->vis
, org
->ctx
, True
);
661 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest
->ctx
, dest
, org
->ctx
);
668 /***********************************************************************
669 * wglSwapLayerBuffers (OPENGL32.@)
671 BOOL WINAPI
wglSwapLayerBuffers(HDC hdc
,
673 TRACE("(%p, %08x)\n", hdc
, fuPlanes
);
675 if (fuPlanes
& WGL_SWAP_MAIN_PLANE
) {
676 if (!SwapBuffers(hdc
)) return FALSE
;
677 fuPlanes
&= ~WGL_SWAP_MAIN_PLANE
;
681 WARN("Following layers unhandled : %08x\n", fuPlanes
);
687 static BOOL
internal_wglUseFontBitmaps(HDC hdc
,
691 DWORD (WINAPI
*GetGlyphOutline_ptr
)(HDC
,UINT
,UINT
,LPGLYPHMETRICS
,DWORD
,LPVOID
,const MAT2
*))
693 /* We are running using client-side rendering fonts... */
697 void *bitmap
= NULL
, *gl_bitmap
= NULL
;
701 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &org_alignment
);
702 glPixelStorei(GL_UNPACK_ALIGNMENT
, 4);
705 for (glyph
= first
; glyph
< first
+ count
; glyph
++) {
706 unsigned int needed_size
= GetGlyphOutline_ptr(hdc
, glyph
, GGO_BITMAP
, &gm
, 0, NULL
, NULL
);
707 int height
, width_int
;
709 TRACE("Glyph : %3d / List : %ld\n", glyph
, listBase
);
710 if (needed_size
== GDI_ERROR
) {
711 TRACE(" - needed size : %d (GDI_ERROR)\n", needed_size
);
714 TRACE(" - needed size : %d\n", needed_size
);
717 if (needed_size
> size
) {
719 HeapFree(GetProcessHeap(), 0, bitmap
);
720 HeapFree(GetProcessHeap(), 0, gl_bitmap
);
721 bitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
722 gl_bitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
724 if (GetGlyphOutline_ptr(hdc
, glyph
, GGO_BITMAP
, &gm
, size
, bitmap
, NULL
) == GDI_ERROR
) goto error
;
725 if (TRACE_ON(opengl
)) {
726 unsigned int height
, width
, bitmask
;
727 unsigned char *bitmap_
= (unsigned char *) bitmap
;
729 TRACE(" - bbox : %d x %d\n", gm
.gmBlackBoxX
, gm
.gmBlackBoxY
);
730 TRACE(" - origin : (%ld , %ld)\n", gm
.gmptGlyphOrigin
.x
, gm
.gmptGlyphOrigin
.y
);
731 TRACE(" - increment : %d - %d\n", gm
.gmCellIncX
, gm
.gmCellIncY
);
732 if (needed_size
!= 0) {
733 TRACE(" - bitmap :\n");
734 for (height
= 0; height
< gm
.gmBlackBoxY
; height
++) {
736 for (width
= 0, bitmask
= 0x80; width
< gm
.gmBlackBoxX
; width
++, bitmask
>>= 1) {
741 if (*bitmap_
& bitmask
)
746 bitmap_
+= (4 - ((UINT_PTR
)bitmap_
& 0x03));
752 /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
753 * glyph for it to be drawn properly.
755 if (needed_size
!= 0) {
756 width_int
= (gm
.gmBlackBoxX
+ 31) / 32;
757 for (height
= 0; height
< gm
.gmBlackBoxY
; height
++) {
759 for (width
= 0; width
< width_int
; width
++) {
760 ((int *) gl_bitmap
)[(gm
.gmBlackBoxY
- height
- 1) * width_int
+ width
] =
761 ((int *) bitmap
)[height
* width_int
+ width
];
767 glNewList(listBase
++, GL_COMPILE
);
768 if (needed_size
!= 0) {
769 glBitmap(gm
.gmBlackBoxX
, gm
.gmBlackBoxY
,
770 0 - (int) gm
.gmptGlyphOrigin
.x
, (int) gm
.gmBlackBoxY
- (int) gm
.gmptGlyphOrigin
.y
,
771 gm
.gmCellIncX
, gm
.gmCellIncY
,
774 /* This is the case of 'empty' glyphs like the space character */
775 glBitmap(0, 0, 0, 0, gm
.gmCellIncX
, gm
.gmCellIncY
, NULL
);
782 glPixelStorei(GL_UNPACK_ALIGNMENT
, org_alignment
);
785 HeapFree(GetProcessHeap(), 0, bitmap
);
786 HeapFree(GetProcessHeap(), 0, gl_bitmap
);
791 glPixelStorei(GL_UNPACK_ALIGNMENT
, org_alignment
);
794 HeapFree(GetProcessHeap(), 0, bitmap
);
795 HeapFree(GetProcessHeap(), 0, gl_bitmap
);
799 /***********************************************************************
800 * wglUseFontBitmapsA (OPENGL32.@)
802 BOOL WINAPI
wglUseFontBitmapsA(HDC hdc
,
807 Font fid
= get_font( hdc
);
809 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc
, first
, count
, listBase
, fid
);
812 return internal_wglUseFontBitmaps(hdc
, first
, count
, listBase
, GetGlyphOutlineA
);
816 /* I assume that the glyphs are at the same position for X and for Windows */
817 glXUseXFont(fid
, first
, count
, listBase
);
822 /***********************************************************************
823 * wglUseFontBitmapsW (OPENGL32.@)
825 BOOL WINAPI
wglUseFontBitmapsW(HDC hdc
,
830 Font fid
= get_font( hdc
);
832 TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc
, first
, count
, listBase
, fid
);
835 return internal_wglUseFontBitmaps(hdc
, first
, count
, listBase
, GetGlyphOutlineW
);
838 WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
841 /* I assume that the glyphs are at the same position for X and for Windows */
842 glXUseXFont(fid
, first
, count
, listBase
);
847 /***********************************************************************
848 * wglUseFontOutlinesA (OPENGL32.@)
850 BOOL WINAPI
wglUseFontOutlinesA(HDC hdc
,
857 LPGLYPHMETRICSFLOAT lpgmf
) {
858 FIXME("(): stub !\n");
863 const GLubyte
* internal_glGetString(GLenum name
) {
864 const char* GL_Extensions
= NULL
;
866 if (GL_EXTENSIONS
!= name
) {
867 return glGetString(name
);
870 if (NULL
== internal_gl_extensions
) {
871 GL_Extensions
= (const char *) glGetString(GL_EXTENSIONS
);
873 TRACE("GL_EXTENSIONS reported:\n");
874 if (NULL
== GL_Extensions
) {
875 ERR("GL_EXTENSIONS returns NULL\n");
878 size_t len
= strlen(GL_Extensions
);
879 internal_gl_extensions
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
+ 2);
881 while (*GL_Extensions
!= 0x00) {
882 const char* Start
= GL_Extensions
;
885 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
886 while (*GL_Extensions
!= ' ' && *GL_Extensions
!= 0x00) {
889 memcpy(ThisExtn
, Start
, (GL_Extensions
- Start
));
890 TRACE("- %s:", ThisExtn
);
892 /* test if supported API is disabled by config */
893 if (NULL
== strstr(internal_gl_disabled_extensions
, ThisExtn
)) {
894 strcat(internal_gl_extensions
, " ");
895 strcat(internal_gl_extensions
, ThisExtn
);
898 TRACE(" deactived (by config)\n");
901 if (*GL_Extensions
== ' ') GL_Extensions
++;
905 return (const GLubyte
*) internal_gl_extensions
;
908 void internal_glGetIntegerv(GLenum pname
, GLint
* params
) {
909 glGetIntegerv(pname
, params
);
910 if (pname
== GL_DEPTH_BITS
) {
911 GLXContext gl_ctx
= glXGetCurrentContext();
912 Wine_GLContext
* ret
= get_context_from_GLXContext(gl_ctx
);
913 /*TRACE("returns Wine Ctx as %p\n", ret);*/
915 * if we cannot find a Wine Context
916 * we only have the default wine desktop context,
917 * so if we have only a 24 depth say we have 32
919 if (NULL
== ret
&& 24 == *params
) {
922 TRACE("returns GL_DEPTH_BITS as '%d'\n", *params
);
924 if (pname
== GL_ALPHA_BITS
) {
926 GLXContext gl_ctx
= glXGetCurrentContext();
927 Wine_GLContext
* ret
= get_context_from_GLXContext(gl_ctx
);
928 glXGetFBConfigAttrib(ret
->display
, ret
->fb_conf
, GLX_ALPHA_SIZE
, &tmp
);
929 TRACE("returns GL_ALPHA_BITS as '%d'\n", tmp
);
935 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
936 include all dependencies
939 #define SONAME_LIBGL "libGL.so"
942 static void wgl_initialize_glx(Display
*display
, int screen
, glXGetProcAddressARB_t proc
)
944 const char *server_glx_version
= glXQueryServerString(display
, screen
, GLX_VERSION
);
945 const char *server_glx_extensions
= glXQueryServerString(display
, screen
, GLX_EXTENSIONS
);
947 const char *client_glx_version = glXGetClientString(display, GLX_VERSION);
948 const char *client_glx_extensions = glXGetClientString(display, GLX_EXTENSIONS);
949 const char *glx_extensions = glXQueryExtensionsString(display, screen);
952 memset(&wine_glx
, 0, sizeof(wine_glx
));
954 if (!strcmp("1.2", server_glx_version
)) {
955 wine_glx
.version
= 2;
957 wine_glx
.version
= 3;
960 if (2 < wine_glx
.version
) {
961 wine_glx
.p_glXChooseFBConfig
= proc( (const GLubyte
*) "glXChooseFBConfig");
962 wine_glx
.p_glXGetFBConfigAttrib
= proc( (const GLubyte
*) "glXGetFBConfigAttrib");
963 wine_glx
.p_glXGetVisualFromFBConfig
= proc( (const GLubyte
*) "glXGetVisualFromFBConfig");
965 /*wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");*/
966 wine_glx
.p_glXQueryDrawable
= proc( (const GLubyte
*) "glXQueryDrawable");
968 if (NULL
!= strstr(server_glx_extensions
, "GLX_SGIX_fbconfig")) {
969 wine_glx
.p_glXChooseFBConfig
= proc( (const GLubyte
*) "glXChooseFBConfigSGIX");
970 wine_glx
.p_glXGetFBConfigAttrib
= proc( (const GLubyte
*) "glXGetFBConfigAttribSGIX");
971 wine_glx
.p_glXGetVisualFromFBConfig
= proc( (const GLubyte
*) "glXGetVisualFromFBConfigSGIX");
973 ERR(" glx_version as %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", server_glx_version
);
976 /** try anyway to retrieve that calls, maybe they works using glx client tricks */
977 wine_glx
.p_glXGetFBConfigs
= proc( (const GLubyte
*) "glXGetFBConfigs");
978 wine_glx
.p_glXMakeContextCurrent
= proc( (const GLubyte
*) "glXMakeContextCurrent");
981 /* This is for brain-dead applications that use OpenGL functions before even
982 creating a rendering context.... */
983 static BOOL
process_attach(void)
985 XWindowAttributes win_attr
;
988 XVisualInfo
template;
990 XVisualInfo
*vis
= NULL
;
991 Window root
= (Window
)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
992 HMODULE mod
= GetModuleHandleA( "winex11.drv" );
994 DWORD size
= sizeof(internal_gl_disabled_extensions
);
999 ERR("X11DRV not loaded. Cannot create default context.\n");
1003 wine_tsx11_lock_ptr
= (void *)GetProcAddress( mod
, "wine_tsx11_lock" );
1004 wine_tsx11_unlock_ptr
= (void *)GetProcAddress( mod
, "wine_tsx11_unlock" );
1007 default_display
= get_display( hdc
);
1008 ReleaseDC( 0, hdc
);
1009 if (!default_display
)
1011 ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
1017 /* Try to get the visual from the Root Window. We can't use the standard (presumably
1018 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
1019 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
1020 with mismatched visuals. Note that the Root Window visual may not be double
1021 buffered, so apps actually attempting to render this way may flicker */
1022 if (XGetWindowAttributes( default_display
, root
, &win_attr
))
1024 rootVisual
= win_attr
.visual
;
1028 /* Get the default visual, since we can't seem to get the attributes from the
1029 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
1030 rootVisual
= DefaultVisual( default_display
, DefaultScreen(default_display
) );
1033 template.visualid
= XVisualIDFromVisual(rootVisual
);
1034 vis
= XGetVisualInfo(default_display
, VisualIDMask
, &template, &num
);
1035 if (vis
!= NULL
) default_cx
= glXCreateContext(default_display
, vis
, 0, GL_TRUE
);
1036 if (default_cx
!= NULL
) glXMakeCurrent(default_display
, root
, default_cx
);
1040 opengl_handle
= wine_dlopen(SONAME_LIBGL
, RTLD_NOW
|RTLD_GLOBAL
, NULL
, 0);
1041 if (opengl_handle
!= NULL
) {
1042 p_glXGetProcAddressARB
= wine_dlsym(opengl_handle
, "glXGetProcAddressARB", NULL
, 0);
1043 wine_dlclose(opengl_handle
, NULL
, 0);
1044 if (p_glXGetProcAddressARB
== NULL
)
1045 TRACE("could not find glXGetProcAddressARB in libGL.\n");
1048 internal_gl_disabled_extensions
[0] = 0;
1049 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\OpenGL", &hkey
)) {
1050 if (!RegQueryValueExA( hkey
, "DisabledExtensions", 0, NULL
, (LPBYTE
)internal_gl_disabled_extensions
, &size
)) {
1051 TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions
);
1056 if (default_cx
== NULL
) {
1057 ERR("Could not create default context.\n");
1061 /* After context initialize also the list of supported WGL extensions. */
1062 wgl_initialize_glx(default_display
, DefaultScreen(default_display
), p_glXGetProcAddressARB
);
1063 wgl_ext_initialize_extensions(default_display
, DefaultScreen(default_display
), p_glXGetProcAddressARB
, internal_gl_disabled_extensions
);
1069 /**********************************************************************/
1071 static void process_detach(void)
1073 glXDestroyContext(default_display
, default_cx
);
1075 /* Do not leak memory... */
1076 wgl_ext_finalize_extensions();
1077 if (NULL
!= internal_gl_extensions
) {
1078 HeapFree(GetProcessHeap(), 0, internal_gl_extensions
);
1082 /***********************************************************************
1083 * OpenGL initialisation routine
1085 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
1089 case DLL_PROCESS_ATTACH
:
1090 opengl32_handle
= hinst
;
1091 DisableThreadLibraryCalls(hinst
);
1092 return process_attach();
1093 case DLL_PROCESS_DETACH
: