1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
8 #include "wine/exception.h"
11 #include "debugtools.h"
21 #include "opengl_ext.h"
23 DEFAULT_DEBUG_CHANNEL(opengl
);
25 static GLXContext default_cx
= NULL
;
27 typedef struct wine_glcontext
{
31 struct wine_glcontext
*next
;
32 struct wine_glcontext
*prev
;
34 static Wine_GLContext
*context_array
;
36 static inline Wine_GLContext
*get_context_from_GLXContext(GLXContext ctx
) {
37 Wine_GLContext
*ret
= context_array
;
38 while (ret
!= NULL
) if (ctx
== ret
->ctx
) break; else ret
= ret
->next
;
42 static inline void free_context(Wine_GLContext
*context
) {
43 if (context
->next
!= NULL
) context
->next
->prev
= context
->prev
;
44 if (context
->prev
!= NULL
) context
->prev
->next
= context
->next
;
45 else context_array
= context
->next
;
47 HeapFree(GetProcessHeap(), 0, context
);
50 static inline Wine_GLContext
*alloc_context(void) {
53 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(Wine_GLContext
));
54 ret
->next
= context_array
;
55 if (context_array
!= NULL
) context_array
->prev
= ret
;
56 else context_array
= ret
;
62 static int XGLErrorFlag
= 0;
63 static int XGLErrorHandler(Display
*dpy
, XErrorEvent
*event
) {
67 /* filter for page-fault exceptions */
68 static WINE_EXCEPTION_FILTER(page_fault
)
70 return EXCEPTION_EXECUTE_HANDLER
;
73 /***********************************************************************
76 HGLRC WINAPI
wglCreateContext(HDC hdc
) {
77 DC
* dc
= DC_GetDCPtr( hdc
);
78 X11DRV_PDEVICE
*physDev
;
82 TRACE("(%08x)\n", hdc
);
89 physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
91 /* First, get the visual for the choosen pixel format */
92 vis
= physDev
->visuals
[physDev
->current_pf
- 1];
95 ERR("NULL visual !!!\n");
96 /* Need to set errors here */
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
);
112 /***********************************************************************
113 * wglCreateLayerContext
115 HGLRC WINAPI
wglCreateLayerContext(HDC hdc
,
117 FIXME("(%08x,%d): stub !\n", hdc
, iLayerPlane
);
122 /***********************************************************************
125 BOOL WINAPI
wglCopyContext(HGLRC hglrcSrc
,
128 FIXME("(%p,%p,%d)\n", hglrcSrc
, hglrcDst
, mask
);
133 /***********************************************************************
136 BOOL WINAPI
wglDeleteContext(HGLRC hglrc
) {
137 int (*WineXHandler
)(Display
*, XErrorEvent
*);
138 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
141 TRACE("(%p)\n", hglrc
);
144 /* A game (Half Life not to name it) deletes twice the same context. To prevent
145 crashes, run with our own error function enabled */
146 XSync(display
, False
);
148 WineXHandler
= XSetErrorHandler(XGLErrorHandler
);
150 glXDestroyContext(display
, ctx
->ctx
);
151 XSync(display
, False
);
154 if (XGLErrorHandler
== 0) free_context(ctx
);
156 __EXCEPT(page_fault
) {
162 XSetErrorHandler(WineXHandler
);
164 WARN("Error deleting context !\n");
165 SetLastError(ERROR_INVALID_HANDLE
);
173 /***********************************************************************
174 * wglDescribeLayerPlane
176 BOOL WINAPI
wglDescribeLayerPlane(HDC hdc
,
180 LPLAYERPLANEDESCRIPTOR plpd
) {
181 FIXME("(%08x,%d,%d,%d,%p)\n", hdc
, iPixelFormat
, iLayerPlane
, nBytes
, plpd
);
186 /***********************************************************************
187 * wglGetCurrentContext
189 HGLRC WINAPI
wglGetCurrentContext(void) {
196 gl_ctx
= glXGetCurrentContext();
197 ret
= get_context_from_GLXContext(gl_ctx
);
200 TRACE(" returning %p (GL context %p)\n", ret
, gl_ctx
);
205 /***********************************************************************
208 HDC WINAPI
wglGetCurrentDC(void) {
215 gl_ctx
= glXGetCurrentContext();
216 ret
= get_context_from_GLXContext(gl_ctx
);
220 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret
->hdc
, gl_ctx
, ret
);
223 TRACE(" no Wine context found for GLX context %p\n", gl_ctx
);
228 /***********************************************************************
229 * wglGetLayerPaletteEntries
231 int WINAPI
wglGetLayerPaletteEntries(HDC hdc
,
235 const COLORREF
*pcr
) {
236 FIXME("(): stub !\n");
241 static int compar(const void *elt_a
, const void *elt_b
) {
242 return strcmp(((OpenGL_extension
*) elt_a
)->name
,
243 ((OpenGL_extension
*) elt_b
)->name
);
246 /***********************************************************************
249 void* WINAPI
wglGetProcAddress(LPCSTR lpszProc
) {
251 static HMODULE hm
= 0;
253 TRACE("(%s)\n", lpszProc
);
256 hm
= GetModuleHandleA("opengl32");
258 /* First, look if it's not already defined in the 'standard' OpenGL functions */
259 if ((local_func
= GetProcAddress(hm
, lpszProc
)) != NULL
) {
260 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func
);
264 /* After that, look at the extensions defined in the Linux OpenGL library */
265 if ((local_func
= glXGetProcAddressARB(lpszProc
)) == NULL
) {
269 /* Remove the 3 last letters (EXT, ARB, ...).
271 I know that some extensions have more than 3 letters (MESA, NV,
272 INTEL, ...), but this is only a stop-gap measure to fix buggy
273 OpenGL drivers (moreover, it is only useful for old 1.0 apps
274 that query the glBindTextureEXT extension).
276 strncpy(buf
, lpszProc
, strlen(lpszProc
) - 3);
277 buf
[strlen(lpszProc
) - 3] = '\0';
278 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf
);
280 ret
= GetProcAddress(hm
, buf
);
282 TRACE(" found function in main OpenGL library (%p) !\n", ret
);
287 OpenGL_extension ext
;
288 OpenGL_extension
*ret
;
290 ext
.name
= (char *) lpszProc
;
291 ret
= (OpenGL_extension
*) bsearch(&ext
, extension_registry
,
292 extension_registry_size
, sizeof(OpenGL_extension
), compar
);
295 TRACE(" returning function (%p)\n", ret
->func
);
296 *(ret
->func_ptr
) = local_func
;
300 ERR("Extension defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n");
306 /***********************************************************************
309 BOOL WINAPI
wglMakeCurrent(HDC hdc
,
313 TRACE("(%08x,%p)\n", hdc
, hglrc
);
317 ret
= glXMakeCurrent(display
,
322 DC
* dc
= DC_GetDCPtr( hdc
);
325 ERR("Null DC !!!\n");
328 X11DRV_PDEVICE
*physDev
;
329 Wine_GLContext
*ctx
= (Wine_GLContext
*) hglrc
;
331 physDev
=(X11DRV_PDEVICE
*)dc
->physDev
;
333 if (ctx
->ctx
== NULL
) {
335 ctx
->ctx
= glXCreateContext(display
, ctx
->vis
, NULL
, True
);
337 TRACE(" created a delayed OpenGL context (%p)\n", ctx
->ctx
);
341 ret
= glXMakeCurrent(display
,
347 TRACE(" returning %s\n", (ret
? "True" : "False"));
351 /***********************************************************************
352 * wglRealizeLayerPalette
354 BOOL WINAPI
wglRealizeLayerPalette(HDC hdc
,
362 /***********************************************************************
363 * wglSetLayerPaletteEntries
365 int WINAPI
wglSetLayerPaletteEntries(HDC hdc
,
369 const COLORREF
*pcr
) {
370 FIXME("(): stub !\n");
375 /***********************************************************************
378 BOOL WINAPI
wglShareLists(HGLRC hglrc1
,
380 Wine_GLContext
*org
= (Wine_GLContext
*) hglrc1
;
381 Wine_GLContext
*dest
= (Wine_GLContext
*) hglrc2
;
383 TRACE("(%p, %p)\n", org
, dest
);
385 if (dest
->ctx
!= NULL
) {
386 ERR("Could not share display lists, context already created !\n");
389 if (org
->ctx
== NULL
) {
391 org
->ctx
= glXCreateContext(display
, org
->vis
, NULL
, True
);
393 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org
->ctx
, org
);
397 /* Create the destination context with display lists shared */
398 dest
->ctx
= glXCreateContext(display
, dest
->vis
, org
->ctx
, True
);
400 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest
->ctx
, dest
, org
->ctx
);
406 /***********************************************************************
407 * wglSwapLayerBuffers
409 BOOL WINAPI
wglSwapLayerBuffers(HDC hdc
,
411 FIXME("(): stub !\n");
416 /***********************************************************************
419 BOOL WINAPI
wglUseFontBitmapsA(HDC hdc
,
423 DC
* dc
= DC_GetDCPtr( hdc
);
424 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
425 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
426 Font fid
= pfo
->fs
->fid
;
428 TRACE("(%08x, %ld, %ld, %ld)\n", hdc
, first
, count
, listBase
);
431 /* I assume that the glyphs are at the same position for X and for Windows */
432 glXUseXFont(fid
, first
, count
, listBase
);
438 /***********************************************************************
439 * wglUseFontOutlinesA
441 BOOL WINAPI
wglUseFontOutlinesA(HDC hdc
,
448 LPGLYPHMETRICSFLOAT lpgmf
) {
449 FIXME("(): stub !\n");
455 /* This is for brain-dead applications that use OpenGL functions before even
456 creating a rendering context.... */
457 static void process_attach(void) {
459 XVisualInfo
template;
460 XVisualInfo
*vis
= NULL
;
463 ERR("X11DRV not loaded yet. Cannot create default context.\n");
468 template.visualid
= XVisualIDFromVisual(visual
);
469 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
470 if (vis
!= NULL
) default_cx
= glXCreateContext(display
, vis
, 0, GL_TRUE
);
471 if (default_cx
!= NULL
) glXMakeCurrent(display
, X11DRV_GetXRootWindow(), default_cx
);
475 if (default_cx
== NULL
) {
476 ERR("Could not create default context.\n");
479 context_array
= NULL
;
482 static void process_detach(void) {
483 glXDestroyContext(display
, default_cx
);
486 /***********************************************************************
487 * OpenGL initialisation routine
489 BOOL WINAPI
OpenGL32_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
491 static int process_count
;
494 case DLL_PROCESS_ATTACH
:
495 if (!process_count
++) process_attach();
497 case DLL_PROCESS_DETACH
:
498 if (!--process_count
) process_detach();