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 )
493 static int process_count;
496 case DLL_PROCESS_ATTACH:
497 if (!process_count++) process_attach();
499 case DLL_PROCESS_DETACH:
500 if (!--process_count) process_detach();