1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
8 #include "wine/exception.h"
11 #include "debugtools.h"
20 #include "opengl_ext.h"
22 DEFAULT_DEBUG_CHANNEL(opengl
);
24 static GLXContext default_cx
= NULL
;
26 typedef struct wine_glcontext
{
30 struct wine_glcontext
*next
;
31 struct wine_glcontext
*prev
;
33 static Wine_GLContext
*context_array
;
35 static inline Wine_GLContext
*get_context_from_GLXContext(GLXContext ctx
) {
36 Wine_GLContext
*ret
= context_array
;
37 while (ret
!= NULL
) if (ctx
== ret
->ctx
) break; else ret
= ret
->next
;
41 static inline void free_context(Wine_GLContext
*context
) {
42 if (context
->next
!= NULL
) context
->next
->prev
= context
->prev
;
43 if (context
->prev
!= NULL
) context
->prev
->next
= context
->next
;
44 else context_array
= context
->next
;
46 HeapFree(GetProcessHeap(), 0, context
);
49 static inline Wine_GLContext
*alloc_context(void) {
52 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(Wine_GLContext
));
53 ret
->next
= context_array
;
54 if (context_array
!= NULL
) context_array
->prev
= ret
;
55 else context_array
= ret
;
61 static int XGLErrorFlag
= 0;
62 static int XGLErrorHandler(Display
*dpy
, XErrorEvent
*event
) {
66 /* filter for page-fault exceptions */
67 static WINE_EXCEPTION_FILTER(page_fault
)
69 return EXCEPTION_EXECUTE_HANDLER
;
72 /***********************************************************************
75 HGLRC WINAPI
wglCreateContext(HDC hdc
) {
76 DC
* dc
= DC_GetDCPtr( hdc
);
77 X11DRV_PDEVICE
*physDev
;
81 TRACE("(%08x)\n", hdc
);
88 physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
90 /* First, get the visual for the choosen pixel format */
91 vis
= physDev
->visuals
[physDev
->current_pf
- 1];
94 ERR("NULL visual !!!\n");
95 /* Need to set errors here */
96 GDI_ReleaseObj( hdc
);
100 /* The context will be allocated in the wglMakeCurrent call */
102 ret
= alloc_context();
107 TRACE(" creating context %p (GL context creation delayed)\n", ret
);
109 GDI_ReleaseObj( hdc
);
113 /***********************************************************************
114 * wglCreateLayerContext
116 HGLRC WINAPI
wglCreateLayerContext(HDC hdc
,
118 FIXME("(%08x,%d): stub !\n", hdc
, iLayerPlane
);
123 /***********************************************************************
126 BOOL WINAPI
wglCopyContext(HGLRC hglrcSrc
,
129 FIXME("(%p,%p,%d)\n", hglrcSrc
, hglrcDst
, mask
);
134 /***********************************************************************
137 BOOL WINAPI
wglDeleteContext(HGLRC hglrc
) {
138 int (*WineXHandler
)(Display
*, XErrorEvent
*);
139 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
142 TRACE("(%p)\n", hglrc
);
145 /* A game (Half Life not to name it) deletes twice the same context. To prevent
146 crashes, run with our own error function enabled */
147 XSync(display
, False
);
149 WineXHandler
= XSetErrorHandler(XGLErrorHandler
);
151 glXDestroyContext(display
, ctx
->ctx
);
152 XSync(display
, False
);
155 if (XGLErrorHandler
== 0) free_context(ctx
);
157 __EXCEPT(page_fault
) {
163 XSetErrorHandler(WineXHandler
);
165 WARN("Error deleting context !\n");
166 SetLastError(ERROR_INVALID_HANDLE
);
174 /***********************************************************************
175 * wglDescribeLayerPlane
177 BOOL WINAPI
wglDescribeLayerPlane(HDC hdc
,
181 LPLAYERPLANEDESCRIPTOR plpd
) {
182 FIXME("(%08x,%d,%d,%d,%p)\n", hdc
, iPixelFormat
, iLayerPlane
, nBytes
, plpd
);
187 /***********************************************************************
188 * wglGetCurrentContext
190 HGLRC WINAPI
wglGetCurrentContext(void) {
197 gl_ctx
= glXGetCurrentContext();
198 ret
= get_context_from_GLXContext(gl_ctx
);
201 TRACE(" returning %p (GL context %p)\n", ret
, gl_ctx
);
206 /***********************************************************************
209 HDC WINAPI
wglGetCurrentDC(void) {
216 gl_ctx
= glXGetCurrentContext();
217 ret
= get_context_from_GLXContext(gl_ctx
);
221 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret
->hdc
, gl_ctx
, ret
);
224 TRACE(" no Wine context found for GLX context %p\n", gl_ctx
);
229 /***********************************************************************
230 * wglGetLayerPaletteEntries
232 int WINAPI
wglGetLayerPaletteEntries(HDC hdc
,
236 const COLORREF
*pcr
) {
237 FIXME("(): stub !\n");
242 static int compar(const void *elt_a
, const void *elt_b
) {
243 return strcmp(((OpenGL_extension
*) elt_a
)->name
,
244 ((OpenGL_extension
*) elt_b
)->name
);
247 /***********************************************************************
250 void* WINAPI
wglGetProcAddress(LPCSTR lpszProc
) {
252 static HMODULE hm
= 0;
254 TRACE("(%s)\n", lpszProc
);
257 hm
= GetModuleHandleA("opengl32");
259 /* First, look if it's not already defined in the 'standard' OpenGL functions */
260 if ((local_func
= GetProcAddress(hm
, lpszProc
)) != NULL
) {
261 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func
);
265 /* After that, look at the extensions defined in the Linux OpenGL library */
266 if ((local_func
= glXGetProcAddressARB(lpszProc
)) == NULL
) {
270 /* Remove the 3 last letters (EXT, ARB, ...).
272 I know that some extensions have more than 3 letters (MESA, NV,
273 INTEL, ...), but this is only a stop-gap measure to fix buggy
274 OpenGL drivers (moreover, it is only useful for old 1.0 apps
275 that query the glBindTextureEXT extension).
277 strncpy(buf
, lpszProc
, strlen(lpszProc
) - 3);
278 buf
[strlen(lpszProc
) - 3] = '\0';
279 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf
);
281 ret
= GetProcAddress(hm
, buf
);
283 TRACE(" found function in main OpenGL library (%p) !\n", ret
);
288 OpenGL_extension ext
;
289 OpenGL_extension
*ret
;
291 ext
.name
= (char *) lpszProc
;
292 ret
= (OpenGL_extension
*) bsearch(&ext
, extension_registry
,
293 extension_registry_size
, sizeof(OpenGL_extension
), compar
);
296 TRACE(" returning function (%p)\n", ret
->func
);
297 *(ret
->func_ptr
) = local_func
;
301 ERR("Extension defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n");
307 /***********************************************************************
310 BOOL WINAPI
wglMakeCurrent(HDC hdc
,
314 TRACE("(%08x,%p)\n", hdc
, hglrc
);
318 ret
= glXMakeCurrent(display
,
323 DC
* dc
= DC_GetDCPtr( hdc
);
326 ERR("Null DC !!!\n");
329 X11DRV_PDEVICE
*physDev
;
330 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
332 physDev
=(X11DRV_PDEVICE
*)dc
->physDev
;
334 if (ctx
->ctx
== NULL
) {
336 ctx
->ctx
= glXCreateContext(display
, ctx
->vis
, NULL
, True
);
338 TRACE(" created a delayed OpenGL context (%p)\n", ctx
->ctx
);
342 ret
= glXMakeCurrent(display
,
346 GDI_ReleaseObj( hdc
);
349 TRACE(" returning %s\n", (ret
? "True" : "False"));
353 /***********************************************************************
354 * wglRealizeLayerPalette
356 BOOL WINAPI
wglRealizeLayerPalette(HDC hdc
,
364 /***********************************************************************
365 * wglSetLayerPaletteEntries
367 int WINAPI
wglSetLayerPaletteEntries(HDC hdc
,
371 const COLORREF
*pcr
) {
372 FIXME("(): stub !\n");
377 /***********************************************************************
380 BOOL WINAPI
wglShareLists(HGLRC hglrc1
,
382 Wine_GLContext
*org
= (Wine_GLContext
*) hglrc1
;
383 Wine_GLContext
*dest
= (Wine_GLContext
*) hglrc2
;
385 TRACE("(%p, %p)\n", org
, dest
);
387 if (dest
->ctx
!= NULL
) {
388 ERR("Could not share display lists, context already created !\n");
391 if (org
->ctx
== NULL
) {
393 org
->ctx
= glXCreateContext(display
, org
->vis
, NULL
, True
);
395 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org
->ctx
, org
);
399 /* Create the destination context with display lists shared */
400 dest
->ctx
= glXCreateContext(display
, dest
->vis
, org
->ctx
, True
);
402 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest
->ctx
, dest
, org
->ctx
);
408 /***********************************************************************
409 * wglSwapLayerBuffers
411 BOOL WINAPI
wglSwapLayerBuffers(HDC hdc
,
413 FIXME("(): stub !\n");
418 /***********************************************************************
421 BOOL WINAPI
wglUseFontBitmapsA(HDC hdc
,
425 DC
* dc
= DC_GetDCPtr( hdc
);
426 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
427 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
428 Font fid
= pfo
->fs
->fid
;
430 TRACE("(%08x, %ld, %ld, %ld)\n", hdc
, first
, count
, listBase
);
433 /* I assume that the glyphs are at the same position for X and for Windows */
434 glXUseXFont(fid
, first
, count
, listBase
);
436 GDI_ReleaseObj( hdc
);
440 /***********************************************************************
441 * wglUseFontOutlinesA
443 BOOL WINAPI
wglUseFontOutlinesA(HDC hdc
,
450 LPGLYPHMETRICSFLOAT lpgmf
) {
451 FIXME("(): stub !\n");
457 /* This is for brain-dead applications that use OpenGL functions before even
458 creating a rendering context.... */
459 static void process_attach(void) {
461 XVisualInfo
template;
462 XVisualInfo
*vis
= NULL
;
465 ERR("X11DRV not loaded yet. Cannot create default context.\n");
470 template.visualid
= XVisualIDFromVisual(visual
);
471 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
472 if (vis
!= NULL
) default_cx
= glXCreateContext(display
, vis
, 0, GL_TRUE
);
473 if (default_cx
!= NULL
) glXMakeCurrent(display
, X11DRV_GetXRootWindow(), default_cx
);
477 if (default_cx
== NULL
) {
478 ERR("Could not create default context.\n");
481 context_array
= NULL
;
484 static void process_detach(void) {
485 glXDestroyContext(display
, default_cx
);
488 /***********************************************************************
489 * OpenGL initialisation routine
491 BOOL WINAPI
OpenGL32_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
494 case DLL_PROCESS_ATTACH
:
497 case DLL_PROCESS_DETACH
: