1 /* Window-specific OpenGL functions implementation.
3 * Copyright (c) 1999 Lionel Ulmer
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/exception.h"
27 #include "wine/debug.h"
34 #include "msvcrt/excpt.h"
37 #include "opengl_ext.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(opengl
);
41 static GLXContext default_cx
= NULL
;
43 typedef struct wine_glcontext
{
47 struct wine_glcontext
*next
;
48 struct wine_glcontext
*prev
;
50 static Wine_GLContext
*context_array
;
52 static inline Wine_GLContext
*get_context_from_GLXContext(GLXContext ctx
) {
53 Wine_GLContext
*ret
= context_array
;
54 while (ret
!= NULL
) if (ctx
== ret
->ctx
) break; else ret
= ret
->next
;
58 static inline void free_context(Wine_GLContext
*context
) {
59 if (context
->next
!= NULL
) context
->next
->prev
= context
->prev
;
60 if (context
->prev
!= NULL
) context
->prev
->next
= context
->next
;
61 else context_array
= context
->next
;
63 HeapFree(GetProcessHeap(), 0, context
);
66 static inline Wine_GLContext
*alloc_context(void) {
69 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(Wine_GLContext
));
70 ret
->next
= context_array
;
71 if (context_array
!= NULL
) context_array
->prev
= ret
;
72 else context_array
= ret
;
78 static int XGLErrorFlag
= 0;
79 static int XGLErrorHandler(Display
*dpy
, XErrorEvent
*event
) {
83 /* filter for page-fault exceptions */
84 static WINE_EXCEPTION_FILTER(page_fault
)
86 return EXCEPTION_EXECUTE_HANDLER
;
89 /***********************************************************************
90 * wglCreateContext (OPENGL32.@)
92 HGLRC WINAPI
wglCreateContext(HDC hdc
)
99 TRACE("(%08x)\n", hdc
);
101 /* First, get the visual in use by the X11DRV */
102 template.visualid
= GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
103 vis
= XGetVisualInfo(gdi_display
, VisualIDMask
, &template, &num
);
106 ERR("NULL visual !!!\n");
107 /* Need to set errors here */
111 /* The context will be allocated in the wglMakeCurrent call */
113 ret
= alloc_context();
118 TRACE(" creating context %p (GL context creation delayed)\n", ret
);
122 /***********************************************************************
123 * wglCreateLayerContext (OPENGL32.@)
125 HGLRC WINAPI
wglCreateLayerContext(HDC hdc
,
127 FIXME("(%08x,%d): stub !\n", hdc
, iLayerPlane
);
132 /***********************************************************************
133 * wglCopyContext (OPENGL32.@)
135 BOOL WINAPI
wglCopyContext(HGLRC hglrcSrc
,
138 FIXME("(%p,%p,%d)\n", hglrcSrc
, hglrcDst
, mask
);
143 /***********************************************************************
144 * wglDeleteContext (OPENGL32.@)
146 BOOL WINAPI
wglDeleteContext(HGLRC hglrc
) {
147 int (*WineXHandler
)(Display
*, XErrorEvent
*);
148 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
151 TRACE("(%p)\n", hglrc
);
154 /* A game (Half Life not to name it) deletes twice the same context. To prevent
155 crashes, run with our own error function enabled */
156 XSync(gdi_display
, False
);
158 WineXHandler
= XSetErrorHandler(XGLErrorHandler
);
160 glXDestroyContext(gdi_display
, ctx
->ctx
);
161 XSync(gdi_display
, False
);
164 if (XGLErrorHandler
== 0) free_context(ctx
);
166 __EXCEPT(page_fault
) {
172 XSetErrorHandler(WineXHandler
);
174 WARN("Error deleting context !\n");
175 SetLastError(ERROR_INVALID_HANDLE
);
183 /***********************************************************************
184 * wglDescribeLayerPlane (OPENGL32.@)
186 BOOL WINAPI
wglDescribeLayerPlane(HDC hdc
,
190 LPLAYERPLANEDESCRIPTOR plpd
) {
191 FIXME("(%08x,%d,%d,%d,%p)\n", hdc
, iPixelFormat
, iLayerPlane
, nBytes
, plpd
);
196 /***********************************************************************
197 * wglGetCurrentContext (OPENGL32.@)
199 HGLRC WINAPI
wglGetCurrentContext(void) {
206 gl_ctx
= glXGetCurrentContext();
207 ret
= get_context_from_GLXContext(gl_ctx
);
210 TRACE(" returning %p (GL context %p)\n", ret
, gl_ctx
);
215 /***********************************************************************
216 * wglGetCurrentDC (OPENGL32.@)
218 HDC WINAPI
wglGetCurrentDC(void) {
225 gl_ctx
= glXGetCurrentContext();
226 ret
= get_context_from_GLXContext(gl_ctx
);
230 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret
->hdc
, gl_ctx
, ret
);
233 TRACE(" no Wine context found for GLX context %p\n", gl_ctx
);
238 /***********************************************************************
239 * wglGetLayerPaletteEntries (OPENGL32.@)
241 int WINAPI
wglGetLayerPaletteEntries(HDC hdc
,
245 const COLORREF
*pcr
) {
246 FIXME("(): stub !\n");
251 /***********************************************************************
252 * wglGetProcAddress (OPENGL32.@)
254 static int compar(const void *elt_a
, const void *elt_b
) {
255 return strcmp(((OpenGL_extension
*) elt_a
)->name
,
256 ((OpenGL_extension
*) elt_b
)->name
);
259 void* WINAPI
wglGetProcAddress(LPCSTR lpszProc
) {
261 static HMODULE hm
= 0;
262 OpenGL_extension ext
;
263 OpenGL_extension
*ext_ret
;
266 TRACE("(%s)\n", lpszProc
);
269 hm
= GetModuleHandleA("opengl32");
271 /* First, look if it's not already defined in the 'standard' OpenGL functions */
272 if ((local_func
= GetProcAddress(hm
, lpszProc
)) != NULL
) {
273 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func
);
277 /* After that, search in the thunks to find the real name of the extension */
278 ext
.name
= (char *) lpszProc
;
279 ext_ret
= (OpenGL_extension
*) bsearch(&ext
, extension_registry
,
280 extension_registry_size
, sizeof(OpenGL_extension
), compar
);
282 if (ext_ret
== NULL
) {
283 /* Some sanity checks :-) */
284 if (glXGetProcAddressARB(lpszProc
) != NULL
) {
285 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc
);
289 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc
);
292 /* After that, look at the extensions defined in the Linux OpenGL library */
293 if ((local_func
= glXGetProcAddressARB(ext_ret
->glx_name
)) == NULL
) {
297 /* Remove the 3 last letters (EXT, ARB, ...).
299 I know that some extensions have more than 3 letters (MESA, NV,
300 INTEL, ...), but this is only a stop-gap measure to fix buggy
301 OpenGL drivers (moreover, it is only useful for old 1.0 apps
302 that query the glBindTextureEXT extension).
304 strncpy(buf
, ext_ret
->glx_name
, strlen(ext_ret
->glx_name
) - 3);
305 buf
[strlen(ext_ret
->glx_name
) - 3] = '\0';
306 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf
);
308 ret
= GetProcAddress(hm
, buf
);
310 TRACE(" found function in main OpenGL library (%p) !\n", ret
);
312 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc
, ext_ret
->glx_name
);
317 TRACE(" returning function (%p)\n", ext_ret
->func
);
318 *(ext_ret
->func_ptr
) = local_func
;
320 return ext_ret
->func
;
325 /***********************************************************************
326 * wglMakeCurrent (OPENGL32.@)
328 BOOL WINAPI
wglMakeCurrent(HDC hdc
,
332 TRACE("(%08x,%p)\n", hdc
, hglrc
);
336 ret
= glXMakeCurrent(gdi_display
,
341 DC
* dc
= DC_GetDCPtr( hdc
);
344 ERR("Null DC !!!\n");
347 X11DRV_PDEVICE
*physDev
;
348 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
350 physDev
=(X11DRV_PDEVICE
*)dc
->physDev
;
352 if (ctx
->ctx
== NULL
) {
354 ctx
->ctx
= glXCreateContext(gdi_display
, ctx
->vis
, NULL
, True
);
356 TRACE(" created a delayed OpenGL context (%p)\n", ctx
->ctx
);
360 ret
= glXMakeCurrent(gdi_display
,
364 GDI_ReleaseObj( hdc
);
367 TRACE(" returning %s\n", (ret
? "True" : "False"));
371 /***********************************************************************
372 * wglRealizeLayerPalette (OPENGL32.@)
374 BOOL WINAPI
wglRealizeLayerPalette(HDC hdc
,
382 /***********************************************************************
383 * wglSetLayerPaletteEntries (OPENGL32.@)
385 int WINAPI
wglSetLayerPaletteEntries(HDC hdc
,
389 const COLORREF
*pcr
) {
390 FIXME("(): stub !\n");
395 /***********************************************************************
396 * wglShareLists (OPENGL32.@)
398 BOOL WINAPI
wglShareLists(HGLRC hglrc1
,
400 Wine_GLContext
*org
= (Wine_GLContext
*) hglrc1
;
401 Wine_GLContext
*dest
= (Wine_GLContext
*) hglrc2
;
403 TRACE("(%p, %p)\n", org
, dest
);
405 if (dest
->ctx
!= NULL
) {
406 ERR("Could not share display lists, context already created !\n");
409 if (org
->ctx
== NULL
) {
411 org
->ctx
= glXCreateContext(gdi_display
, org
->vis
, NULL
, True
);
413 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org
->ctx
, org
);
417 /* Create the destination context with display lists shared */
418 dest
->ctx
= glXCreateContext(gdi_display
, dest
->vis
, org
->ctx
, True
);
420 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest
->ctx
, dest
, org
->ctx
);
426 /***********************************************************************
427 * wglSwapLayerBuffers (OPENGL32.@)
429 BOOL WINAPI
wglSwapLayerBuffers(HDC hdc
,
431 FIXME("(): stub !\n");
436 /***********************************************************************
437 * wglUseFontBitmapsA (OPENGL32.@)
439 BOOL WINAPI
wglUseFontBitmapsA(HDC hdc
,
443 DC
* dc
= DC_GetDCPtr( hdc
);
444 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
445 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
446 Font fid
= pfo
->fs
->fid
;
448 TRACE("(%08x, %ld, %ld, %ld)\n", hdc
, first
, count
, listBase
);
451 /* I assume that the glyphs are at the same position for X and for Windows */
452 glXUseXFont(fid
, first
, count
, listBase
);
454 GDI_ReleaseObj( hdc
);
458 /***********************************************************************
459 * wglUseFontOutlinesA (OPENGL32.@)
461 BOOL WINAPI
wglUseFontOutlinesA(HDC hdc
,
468 LPGLYPHMETRICSFLOAT lpgmf
) {
469 FIXME("(): stub !\n");
475 /* This is for brain-dead applications that use OpenGL functions before even
476 creating a rendering context.... */
477 static void process_attach(void) {
478 XWindowAttributes win_attr
;
481 XVisualInfo
template;
482 XVisualInfo
*vis
= NULL
;
483 Window root
= (Window
)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
487 ERR("X11DRV not loaded. Cannot create default context.\n");
493 /* Try to get the visual from the Root Window. We can't use the standard (presumably
494 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
495 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
496 with mismatched visuals. Note that the Root Window visual may not be double
497 buffered, so apps actually attempting to render this way may flicker */
498 if (XGetWindowAttributes( gdi_display
, root
, &win_attr
))
500 rootVisual
= win_attr
.visual
;
504 /* Get the default visual, since we can't seem to get the attributes from the
505 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
506 rootVisual
= DefaultVisual( gdi_display
, DefaultScreen(gdi_display
) );
509 template.visualid
= XVisualIDFromVisual(rootVisual
);
510 vis
= XGetVisualInfo(gdi_display
, VisualIDMask
, &template, &num
);
511 if (vis
!= NULL
) default_cx
= glXCreateContext(gdi_display
, vis
, 0, GL_TRUE
);
512 if (default_cx
!= NULL
) glXMakeCurrent(gdi_display
, root
, default_cx
);
516 if (default_cx
== NULL
) {
517 ERR("Could not create default context.\n");
520 context_array
= NULL
;
523 static void process_detach(void) {
524 glXDestroyContext(gdi_display
, default_cx
);
527 /***********************************************************************
528 * OpenGL initialisation routine
530 BOOL WINAPI
OpenGL32_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
533 case DLL_PROCESS_ATTACH
:
536 case DLL_PROCESS_DETACH
: