1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
11 #include "wine/exception.h"
13 #include "debugtools.h"
20 #include "msvcrt/excpt.h"
23 #include "opengl_ext.h"
25 DEFAULT_DEBUG_CHANNEL(opengl);
27 static GLXContext default_cx = NULL;
29 typedef struct wine_glcontext {
33 struct wine_glcontext *next;
34 struct wine_glcontext *prev;
36 static Wine_GLContext *context_array;
38 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx) {
39 Wine_GLContext *ret = context_array;
40 while (ret != NULL) if (ctx == ret->ctx) break; else ret = ret->next;
44 static inline void free_context(Wine_GLContext *context) {
45 if (context->next != NULL) context->next->prev = context->prev;
46 if (context->prev != NULL) context->prev->next = context->next;
47 else context_array = context->next;
49 HeapFree(GetProcessHeap(), 0, context);
52 static inline Wine_GLContext *alloc_context(void) {
55 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext));
56 ret->next = context_array;
57 if (context_array != NULL) context_array->prev = ret;
58 else context_array = ret;
64 static int XGLErrorFlag = 0;
65 static int XGLErrorHandler(Display *dpy, XErrorEvent *event) {
69 /* filter for page-fault exceptions */
70 static WINE_EXCEPTION_FILTER(page_fault)
72 return EXCEPTION_EXECUTE_HANDLER;
75 /***********************************************************************
76 * wglCreateContext (OPENGL32.@)
78 HGLRC WINAPI wglCreateContext(HDC hdc)
85 TRACE("(%08x)\n", hdc);
87 /* First, get the visual in use by the X11DRV */
88 template.visualid = GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
89 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
92 ERR("NULL visual !!!\n");
93 /* Need to set errors here */
97 /* The context will be allocated in the wglMakeCurrent call */
99 ret = alloc_context();
104 TRACE(" creating context %p (GL context creation delayed)\n", ret);
108 /***********************************************************************
109 * wglCreateLayerContext (OPENGL32.@)
111 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
113 FIXME("(%08x,%d): stub !\n", hdc, iLayerPlane);
118 /***********************************************************************
119 * wglCopyContext (OPENGL32.@)
121 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
124 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
129 /***********************************************************************
130 * wglDeleteContext (OPENGL32.@)
132 BOOL WINAPI wglDeleteContext(HGLRC hglrc) {
133 int (*WineXHandler)(Display *, XErrorEvent *);
134 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
137 TRACE("(%p)\n", hglrc);
140 /* A game (Half Life not to name it) deletes twice the same context. To prevent
141 crashes, run with our own error function enabled */
142 XSync(gdi_display, False);
144 WineXHandler = XSetErrorHandler(XGLErrorHandler);
146 glXDestroyContext(gdi_display, ctx->ctx);
147 XSync(gdi_display, False);
150 if (XGLErrorHandler == 0) free_context(ctx);
152 __EXCEPT(page_fault) {
158 XSetErrorHandler(WineXHandler);
160 WARN("Error deleting context !\n");
161 SetLastError(ERROR_INVALID_HANDLE);
169 /***********************************************************************
170 * wglDescribeLayerPlane (OPENGL32.@)
172 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
176 LPLAYERPLANEDESCRIPTOR plpd) {
177 FIXME("(%08x,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
182 /***********************************************************************
183 * wglGetCurrentContext (OPENGL32.@)
185 HGLRC WINAPI wglGetCurrentContext(void) {
192 gl_ctx = glXGetCurrentContext();
193 ret = get_context_from_GLXContext(gl_ctx);
196 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
201 /***********************************************************************
202 * wglGetCurrentDC (OPENGL32.@)
204 HDC WINAPI wglGetCurrentDC(void) {
211 gl_ctx = glXGetCurrentContext();
212 ret = get_context_from_GLXContext(gl_ctx);
216 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
219 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
224 /***********************************************************************
225 * wglGetLayerPaletteEntries (OPENGL32.@)
227 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
231 const COLORREF *pcr) {
232 FIXME("(): stub !\n");
237 /***********************************************************************
238 * wglGetProcAddress (OPENGL32.@)
240 static int compar(const void *elt_a, const void *elt_b) {
241 return strcmp(((OpenGL_extension *) elt_a)->name,
242 ((OpenGL_extension *) elt_b)->name);
245 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
247 static HMODULE hm = 0;
248 OpenGL_extension ext;
249 OpenGL_extension *ext_ret;
252 TRACE("(%s)\n", lpszProc);
255 hm = GetModuleHandleA("opengl32");
257 /* First, look if it's not already defined in the 'standard' OpenGL functions */
258 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
259 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
263 /* After that, search in the thunks to find the real name of the extension */
264 ext.name = (char *) lpszProc;
265 ext_ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
266 extension_registry_size, sizeof(OpenGL_extension), compar);
268 if (ext_ret == NULL) {
269 /* Some sanity checks :-) */
270 if (glXGetProcAddressARB(lpszProc) != NULL) {
271 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
275 WARN("Did not find extension %s in either Wine or your OpenGL library.\n", lpszProc);
278 /* After that, look at the extensions defined in the Linux OpenGL library */
279 if ((local_func = glXGetProcAddressARB(ext_ret->glx_name)) == NULL) {
283 /* Remove the 3 last letters (EXT, ARB, ...).
285 I know that some extensions have more than 3 letters (MESA, NV,
286 INTEL, ...), but this is only a stop-gap measure to fix buggy
287 OpenGL drivers (moreover, it is only useful for old 1.0 apps
288 that query the glBindTextureEXT extension).
290 strncpy(buf, ext_ret->glx_name, strlen(ext_ret->glx_name) - 3);
291 buf[strlen(ext_ret->glx_name) - 3] = '\0';
292 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
294 ret = GetProcAddress(hm, buf);
296 TRACE(" found function in main OpenGL library (%p) !\n", ret);
298 WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, ext_ret->glx_name);
303 TRACE(" returning function (%p)\n", ext_ret->func);
304 *(ext_ret->func_ptr) = local_func;
306 return ext_ret->func;
311 /***********************************************************************
312 * wglMakeCurrent (OPENGL32.@)
314 BOOL WINAPI wglMakeCurrent(HDC hdc,
318 TRACE("(%08x,%p)\n", hdc, hglrc);
322 ret = glXMakeCurrent(gdi_display,
327 DC * dc = DC_GetDCPtr( hdc );
330 ERR("Null DC !!!\n");
333 X11DRV_PDEVICE *physDev;
334 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
336 physDev =(X11DRV_PDEVICE *)dc->physDev;
338 if (ctx->ctx == NULL) {
340 ctx->ctx = glXCreateContext(gdi_display, ctx->vis, NULL, True);
342 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
346 ret = glXMakeCurrent(gdi_display,
350 GDI_ReleaseObj( hdc );
353 TRACE(" returning %s\n", (ret ? "True" : "False"));
357 /***********************************************************************
358 * wglRealizeLayerPalette (OPENGL32.@)
360 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
368 /***********************************************************************
369 * wglSetLayerPaletteEntries (OPENGL32.@)
371 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
375 const COLORREF *pcr) {
376 FIXME("(): stub !\n");
381 /***********************************************************************
382 * wglShareLists (OPENGL32.@)
384 BOOL WINAPI wglShareLists(HGLRC hglrc1,
386 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
387 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
389 TRACE("(%p, %p)\n", org, dest);
391 if (dest->ctx != NULL) {
392 ERR("Could not share display lists, context already created !\n");
395 if (org->ctx == NULL) {
397 org->ctx = glXCreateContext(gdi_display, org->vis, NULL, True);
399 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
403 /* Create the destination context with display lists shared */
404 dest->ctx = glXCreateContext(gdi_display, dest->vis, org->ctx, True);
406 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
412 /***********************************************************************
413 * wglSwapLayerBuffers (OPENGL32.@)
415 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
417 FIXME("(): stub !\n");
422 /***********************************************************************
423 * wglUseFontBitmapsA (OPENGL32.@)
425 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
429 DC * dc = DC_GetDCPtr( hdc );
430 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
431 fontObject* pfo = XFONT_GetFontObject( physDev->font );
432 Font fid = pfo->fs->fid;
434 TRACE("(%08x, %ld, %ld, %ld)\n", hdc, first, count, listBase);
437 /* I assume that the glyphs are at the same position for X and for Windows */
438 glXUseXFont(fid, first, count, listBase);
440 GDI_ReleaseObj( hdc );
444 /***********************************************************************
445 * wglUseFontOutlinesA (OPENGL32.@)
447 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
454 LPGLYPHMETRICSFLOAT lpgmf) {
455 FIXME("(): stub !\n");
461 /* This is for brain-dead applications that use OpenGL functions before even
462 creating a rendering context.... */
463 static void process_attach(void) {
464 XWindowAttributes win_attr;
467 XVisualInfo template;
468 XVisualInfo *vis = NULL;
469 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
473 ERR("X11DRV not loaded. Cannot create default context.\n");
479 /* Try to get the visual from the Root Window. We can't use the standard (presumably
480 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
481 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
482 with mismatched visuals. Note that the Root Window visual may not be double
483 buffered, so apps actually attempting to render this way may flicker */
484 if (XGetWindowAttributes( gdi_display, root, &win_attr ))
486 rootVisual = win_attr.visual;
490 /* Get the default visual, since we can't seem to get the attributes from the
491 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
492 rootVisual = DefaultVisual( gdi_display, DefaultScreen(gdi_display) );
495 template.visualid = XVisualIDFromVisual(rootVisual);
496 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
497 if (vis != NULL) default_cx = glXCreateContext(gdi_display, vis, 0, GL_TRUE);
498 if (default_cx != NULL) glXMakeCurrent(gdi_display, root, default_cx);
502 if (default_cx == NULL) {
503 ERR("Could not create default context.\n");
506 context_array = NULL;
509 static void process_detach(void) {
510 glXDestroyContext(gdi_display, default_cx);
513 /***********************************************************************
514 * OpenGL initialisation routine
516 BOOL WINAPI OpenGL32_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
519 case DLL_PROCESS_ATTACH:
522 case DLL_PROCESS_DETACH: