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 */
97 GDI_ReleaseObj( hdc );
101 /* The context will be allocated in the wglMakeCurrent call */
103 ret = alloc_context();
108 TRACE(" creating context %p (GL context creation delayed)\n", ret);
110 GDI_ReleaseObj( hdc );
114 /***********************************************************************
115 * wglCreateLayerContext
117 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
119 FIXME("(%08x,%d): stub !\n", hdc, iLayerPlane);
124 /***********************************************************************
127 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
130 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
135 /***********************************************************************
138 BOOL WINAPI wglDeleteContext(HGLRC hglrc) {
139 int (*WineXHandler)(Display *, XErrorEvent *);
140 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
143 TRACE("(%p)\n", hglrc);
146 /* A game (Half Life not to name it) deletes twice the same context. To prevent
147 crashes, run with our own error function enabled */
148 XSync(display, False);
150 WineXHandler = XSetErrorHandler(XGLErrorHandler);
152 glXDestroyContext(display, ctx->ctx);
153 XSync(display, False);
156 if (XGLErrorHandler == 0) free_context(ctx);
158 __EXCEPT(page_fault) {
164 XSetErrorHandler(WineXHandler);
166 WARN("Error deleting context !\n");
167 SetLastError(ERROR_INVALID_HANDLE);
175 /***********************************************************************
176 * wglDescribeLayerPlane
178 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
182 LPLAYERPLANEDESCRIPTOR plpd) {
183 FIXME("(%08x,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
188 /***********************************************************************
189 * wglGetCurrentContext
191 HGLRC WINAPI wglGetCurrentContext(void) {
198 gl_ctx = glXGetCurrentContext();
199 ret = get_context_from_GLXContext(gl_ctx);
202 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
207 /***********************************************************************
210 HDC WINAPI wglGetCurrentDC(void) {
217 gl_ctx = glXGetCurrentContext();
218 ret = get_context_from_GLXContext(gl_ctx);
222 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
225 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
230 /***********************************************************************
231 * wglGetLayerPaletteEntries
233 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
237 const COLORREF *pcr) {
238 FIXME("(): stub !\n");
243 static int compar(const void *elt_a, const void *elt_b) {
244 return strcmp(((OpenGL_extension *) elt_a)->name,
245 ((OpenGL_extension *) elt_b)->name);
248 /***********************************************************************
251 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
253 static HMODULE hm = 0;
255 TRACE("(%s)\n", lpszProc);
258 hm = GetModuleHandleA("opengl32");
260 /* First, look if it's not already defined in the 'standard' OpenGL functions */
261 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
262 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
266 /* After that, look at the extensions defined in the Linux OpenGL library */
267 if ((local_func = glXGetProcAddressARB(lpszProc)) == NULL) {
271 /* Remove the 3 last letters (EXT, ARB, ...).
273 I know that some extensions have more than 3 letters (MESA, NV,
274 INTEL, ...), but this is only a stop-gap measure to fix buggy
275 OpenGL drivers (moreover, it is only useful for old 1.0 apps
276 that query the glBindTextureEXT extension).
278 strncpy(buf, lpszProc, strlen(lpszProc) - 3);
279 buf[strlen(lpszProc) - 3] = '\0';
280 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
282 ret = GetProcAddress(hm, buf);
284 TRACE(" found function in main OpenGL library (%p) !\n", ret);
289 OpenGL_extension ext;
290 OpenGL_extension *ret;
292 ext.name = (char *) lpszProc;
293 ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
294 extension_registry_size, sizeof(OpenGL_extension), compar);
297 TRACE(" returning function (%p)\n", ret->func);
298 *(ret->func_ptr) = local_func;
302 ERR("Extension defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n");
308 /***********************************************************************
311 BOOL WINAPI wglMakeCurrent(HDC hdc,
315 TRACE("(%08x,%p)\n", hdc, hglrc);
319 ret = glXMakeCurrent(display,
324 DC * dc = DC_GetDCPtr( hdc );
327 ERR("Null DC !!!\n");
330 X11DRV_PDEVICE *physDev;
331 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
333 physDev =(X11DRV_PDEVICE *)dc->physDev;
335 if (ctx->ctx == NULL) {
337 ctx->ctx = glXCreateContext(display, ctx->vis, NULL, True);
339 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
343 ret = glXMakeCurrent(display,
347 GDI_ReleaseObj( hdc );
350 TRACE(" returning %s\n", (ret ? "True" : "False"));
354 /***********************************************************************
355 * wglRealizeLayerPalette
357 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
365 /***********************************************************************
366 * wglSetLayerPaletteEntries
368 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
372 const COLORREF *pcr) {
373 FIXME("(): stub !\n");
378 /***********************************************************************
381 BOOL WINAPI wglShareLists(HGLRC hglrc1,
383 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
384 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
386 TRACE("(%p, %p)\n", org, dest);
388 if (dest->ctx != NULL) {
389 ERR("Could not share display lists, context already created !\n");
392 if (org->ctx == NULL) {
394 org->ctx = glXCreateContext(display, org->vis, NULL, True);
396 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
400 /* Create the destination context with display lists shared */
401 dest->ctx = glXCreateContext(display, dest->vis, org->ctx, True);
403 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
409 /***********************************************************************
410 * wglSwapLayerBuffers
412 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
414 FIXME("(): stub !\n");
419 /***********************************************************************
422 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
426 DC * dc = DC_GetDCPtr( hdc );
427 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
428 fontObject* pfo = XFONT_GetFontObject( physDev->font );
429 Font fid = pfo->fs->fid;
431 TRACE("(%08x, %ld, %ld, %ld)\n", hdc, first, count, listBase);
434 /* I assume that the glyphs are at the same position for X and for Windows */
435 glXUseXFont(fid, first, count, listBase);
437 GDI_ReleaseObj( hdc );
441 /***********************************************************************
442 * wglUseFontOutlinesA
444 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
451 LPGLYPHMETRICSFLOAT lpgmf) {
452 FIXME("(): stub !\n");
458 /* This is for brain-dead applications that use OpenGL functions before even
459 creating a rendering context.... */
460 static void process_attach(void) {
462 XVisualInfo template;
463 XVisualInfo *vis = NULL;
466 ERR("X11DRV not loaded yet. Cannot create default context.\n");
471 template.visualid = XVisualIDFromVisual(visual);
472 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
473 if (vis != NULL) default_cx = glXCreateContext(display, vis, 0, GL_TRUE);
474 if (default_cx != NULL) glXMakeCurrent(display, X11DRV_GetXRootWindow(), default_cx);
478 if (default_cx == NULL) {
479 ERR("Could not create default context.\n");
482 context_array = NULL;
485 static void process_detach(void) {
486 glXDestroyContext(display, default_cx);
489 /***********************************************************************
490 * OpenGL initialisation routine
492 BOOL WINAPI OpenGL32_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
494 static int process_count;
497 case DLL_PROCESS_ATTACH:
498 if (!process_count++) process_attach();
500 case DLL_PROCESS_DETACH:
501 if (!--process_count) process_detach();