1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
9 #include "wine/exception.h"
12 #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)
83 TRACE("(%08x)\n", hdc);
85 /* First, get the visual in use by the X11DRV */
86 template.visualid = XVisualIDFromVisual(X11DRV_GetVisual());
87 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
90 ERR("NULL visual !!!\n");
91 /* Need to set errors here */
95 /* The context will be allocated in the wglMakeCurrent call */
97 ret = alloc_context();
102 TRACE(" creating context %p (GL context creation delayed)\n", ret);
106 /***********************************************************************
107 * wglCreateLayerContext
109 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
111 FIXME("(%08x,%d): stub !\n", hdc, iLayerPlane);
116 /***********************************************************************
119 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
122 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
127 /***********************************************************************
130 BOOL WINAPI wglDeleteContext(HGLRC hglrc) {
131 int (*WineXHandler)(Display *, XErrorEvent *);
132 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
135 TRACE("(%p)\n", hglrc);
138 /* A game (Half Life not to name it) deletes twice the same context. To prevent
139 crashes, run with our own error function enabled */
140 XSync(gdi_display, False);
142 WineXHandler = XSetErrorHandler(XGLErrorHandler);
144 glXDestroyContext(gdi_display, ctx->ctx);
145 XSync(gdi_display, False);
148 if (XGLErrorHandler == 0) free_context(ctx);
150 __EXCEPT(page_fault) {
156 XSetErrorHandler(WineXHandler);
158 WARN("Error deleting context !\n");
159 SetLastError(ERROR_INVALID_HANDLE);
167 /***********************************************************************
168 * wglDescribeLayerPlane
170 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
174 LPLAYERPLANEDESCRIPTOR plpd) {
175 FIXME("(%08x,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
180 /***********************************************************************
181 * wglGetCurrentContext
183 HGLRC WINAPI wglGetCurrentContext(void) {
190 gl_ctx = glXGetCurrentContext();
191 ret = get_context_from_GLXContext(gl_ctx);
194 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
199 /***********************************************************************
202 HDC WINAPI wglGetCurrentDC(void) {
209 gl_ctx = glXGetCurrentContext();
210 ret = get_context_from_GLXContext(gl_ctx);
214 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
217 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
222 /***********************************************************************
223 * wglGetLayerPaletteEntries
225 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
229 const COLORREF *pcr) {
230 FIXME("(): stub !\n");
235 static int compar(const void *elt_a, const void *elt_b) {
236 return strcmp(((OpenGL_extension *) elt_a)->name,
237 ((OpenGL_extension *) elt_b)->name);
240 /***********************************************************************
243 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
245 static HMODULE hm = 0;
247 TRACE("(%s)\n", lpszProc);
250 hm = GetModuleHandleA("opengl32");
252 /* First, look if it's not already defined in the 'standard' OpenGL functions */
253 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
254 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
258 /* After that, look at the extensions defined in the Linux OpenGL library */
259 if ((local_func = glXGetProcAddressARB(lpszProc)) == NULL) {
263 /* Remove the 3 last letters (EXT, ARB, ...).
265 I know that some extensions have more than 3 letters (MESA, NV,
266 INTEL, ...), but this is only a stop-gap measure to fix buggy
267 OpenGL drivers (moreover, it is only useful for old 1.0 apps
268 that query the glBindTextureEXT extension).
270 strncpy(buf, lpszProc, strlen(lpszProc) - 3);
271 buf[strlen(lpszProc) - 3] = '\0';
272 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
274 ret = GetProcAddress(hm, buf);
276 TRACE(" found function in main OpenGL library (%p) !\n", ret);
281 OpenGL_extension ext;
282 OpenGL_extension *ret;
284 ext.name = (char *) lpszProc;
285 ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
286 extension_registry_size, sizeof(OpenGL_extension), compar);
289 TRACE(" returning function (%p)\n", ret->func);
290 *(ret->func_ptr) = local_func;
294 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
300 /***********************************************************************
303 BOOL WINAPI wglMakeCurrent(HDC hdc,
307 TRACE("(%08x,%p)\n", hdc, hglrc);
311 ret = glXMakeCurrent(gdi_display,
316 DC * dc = DC_GetDCPtr( hdc );
319 ERR("Null DC !!!\n");
322 X11DRV_PDEVICE *physDev;
323 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
325 physDev =(X11DRV_PDEVICE *)dc->physDev;
327 if (ctx->ctx == NULL) {
329 ctx->ctx = glXCreateContext(gdi_display, ctx->vis, NULL, True);
331 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
335 ret = glXMakeCurrent(gdi_display,
339 GDI_ReleaseObj( hdc );
342 TRACE(" returning %s\n", (ret ? "True" : "False"));
346 /***********************************************************************
347 * wglRealizeLayerPalette
349 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
357 /***********************************************************************
358 * wglSetLayerPaletteEntries
360 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
364 const COLORREF *pcr) {
365 FIXME("(): stub !\n");
370 /***********************************************************************
373 BOOL WINAPI wglShareLists(HGLRC hglrc1,
375 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
376 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
378 TRACE("(%p, %p)\n", org, dest);
380 if (dest->ctx != NULL) {
381 ERR("Could not share display lists, context already created !\n");
384 if (org->ctx == NULL) {
386 org->ctx = glXCreateContext(gdi_display, org->vis, NULL, True);
388 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
392 /* Create the destination context with display lists shared */
393 dest->ctx = glXCreateContext(gdi_display, dest->vis, org->ctx, True);
395 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
401 /***********************************************************************
402 * wglSwapLayerBuffers
404 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
406 FIXME("(): stub !\n");
411 /***********************************************************************
414 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
418 DC * dc = DC_GetDCPtr( hdc );
419 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
420 fontObject* pfo = XFONT_GetFontObject( physDev->font );
421 Font fid = pfo->fs->fid;
423 TRACE("(%08x, %ld, %ld, %ld)\n", hdc, first, count, listBase);
426 /* I assume that the glyphs are at the same position for X and for Windows */
427 glXUseXFont(fid, first, count, listBase);
429 GDI_ReleaseObj( hdc );
433 /***********************************************************************
434 * wglUseFontOutlinesA
436 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
443 LPGLYPHMETRICSFLOAT lpgmf) {
444 FIXME("(): stub !\n");
450 /* This is for brain-dead applications that use OpenGL functions before even
451 creating a rendering context.... */
452 static void process_attach(void) {
453 XWindowAttributes win_attr;
456 XVisualInfo template;
457 XVisualInfo *vis = NULL;
460 ERR("X11DRV not loaded yet. Cannot create default context.\n");
466 /* Try to get the visual from the Root Window. We can't use the standard (presumably
467 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
468 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
469 with mismatched visuals. Note that the Root Window visual may not be double
470 buffered, so apps actually attempting to render this way may flicker */
471 if (TSXGetWindowAttributes( gdi_display, X11DRV_GetXRootWindow(), &win_attr ))
473 rootVisual = win_attr.visual;
477 /* Get the default visual, since we can't seem to get the attributes from the
478 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
479 rootVisual = DefaultVisual( gdi_display, DefaultScreen(gdi_display) );
482 template.visualid = XVisualIDFromVisual(rootVisual);
483 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
484 if (vis != NULL) default_cx = glXCreateContext(gdi_display, vis, 0, GL_TRUE);
485 if (default_cx != NULL) glXMakeCurrent(gdi_display, X11DRV_GetXRootWindow(), default_cx);
489 if (default_cx == NULL) {
490 ERR("Could not create default context.\n");
493 context_array = NULL;
496 static void process_detach(void) {
497 glXDestroyContext(gdi_display, default_cx);
500 /***********************************************************************
501 * OpenGL initialisation routine
503 BOOL WINAPI OpenGL32_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
506 case DLL_PROCESS_ATTACH:
509 case DLL_PROCESS_DETACH: