1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
11 #include "wine/exception.h"
13 #include "debugtools.h"
22 #include "opengl_ext.h"
24 DEFAULT_DEBUG_CHANNEL(opengl);
26 static GLXContext default_cx = NULL;
28 typedef struct wine_glcontext {
32 struct wine_glcontext *next;
33 struct wine_glcontext *prev;
35 static Wine_GLContext *context_array;
37 static inline Wine_GLContext *get_context_from_GLXContext(GLXContext ctx) {
38 Wine_GLContext *ret = context_array;
39 while (ret != NULL) if (ctx == ret->ctx) break; else ret = ret->next;
43 static inline void free_context(Wine_GLContext *context) {
44 if (context->next != NULL) context->next->prev = context->prev;
45 if (context->prev != NULL) context->prev->next = context->next;
46 else context_array = context->next;
48 HeapFree(GetProcessHeap(), 0, context);
51 static inline Wine_GLContext *alloc_context(void) {
54 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLContext));
55 ret->next = context_array;
56 if (context_array != NULL) context_array->prev = ret;
57 else context_array = ret;
63 static int XGLErrorFlag = 0;
64 static int XGLErrorHandler(Display *dpy, XErrorEvent *event) {
68 /* filter for page-fault exceptions */
69 static WINE_EXCEPTION_FILTER(page_fault)
71 return EXCEPTION_EXECUTE_HANDLER;
74 /***********************************************************************
75 * wglCreateContext (OPENGL32.@)
77 HGLRC WINAPI wglCreateContext(HDC hdc)
84 TRACE("(%08x)\n", hdc);
86 /* First, get the visual in use by the X11DRV */
87 template.visualid = GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
88 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
91 ERR("NULL visual !!!\n");
92 /* Need to set errors here */
96 /* The context will be allocated in the wglMakeCurrent call */
98 ret = alloc_context();
103 TRACE(" creating context %p (GL context creation delayed)\n", ret);
107 /***********************************************************************
108 * wglCreateLayerContext (OPENGL32.@)
110 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
112 FIXME("(%08x,%d): stub !\n", hdc, iLayerPlane);
117 /***********************************************************************
118 * wglCopyContext (OPENGL32.@)
120 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
123 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
128 /***********************************************************************
129 * wglDeleteContext (OPENGL32.@)
131 BOOL WINAPI wglDeleteContext(HGLRC hglrc) {
132 int (*WineXHandler)(Display *, XErrorEvent *);
133 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
136 TRACE("(%p)\n", hglrc);
139 /* A game (Half Life not to name it) deletes twice the same context. To prevent
140 crashes, run with our own error function enabled */
141 XSync(gdi_display, False);
143 WineXHandler = XSetErrorHandler(XGLErrorHandler);
145 glXDestroyContext(gdi_display, ctx->ctx);
146 XSync(gdi_display, False);
149 if (XGLErrorHandler == 0) free_context(ctx);
151 __EXCEPT(page_fault) {
157 XSetErrorHandler(WineXHandler);
159 WARN("Error deleting context !\n");
160 SetLastError(ERROR_INVALID_HANDLE);
168 /***********************************************************************
169 * wglDescribeLayerPlane (OPENGL32.@)
171 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
175 LPLAYERPLANEDESCRIPTOR plpd) {
176 FIXME("(%08x,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
181 /***********************************************************************
182 * wglGetCurrentContext (OPENGL32.@)
184 HGLRC WINAPI wglGetCurrentContext(void) {
191 gl_ctx = glXGetCurrentContext();
192 ret = get_context_from_GLXContext(gl_ctx);
195 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
200 /***********************************************************************
201 * wglGetCurrentDC (OPENGL32.@)
203 HDC WINAPI wglGetCurrentDC(void) {
210 gl_ctx = glXGetCurrentContext();
211 ret = get_context_from_GLXContext(gl_ctx);
215 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
218 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
223 /***********************************************************************
224 * wglGetLayerPaletteEntries (OPENGL32.@)
226 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
230 const COLORREF *pcr) {
231 FIXME("(): stub !\n");
236 static int compar(const void *elt_a, const void *elt_b) {
237 return strcmp(((OpenGL_extension *) elt_a)->name,
238 ((OpenGL_extension *) elt_b)->name);
241 /***********************************************************************
242 * wglGetProcAddress (OPENGL32.@)
244 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
246 static HMODULE hm = 0;
248 TRACE("(%s)\n", lpszProc);
251 hm = GetModuleHandleA("opengl32");
253 /* First, look if it's not already defined in the 'standard' OpenGL functions */
254 if ((local_func = GetProcAddress(hm, lpszProc)) != NULL) {
255 TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
259 /* After that, look at the extensions defined in the Linux OpenGL library */
260 if ((local_func = glXGetProcAddressARB(lpszProc)) == NULL) {
264 /* Remove the 3 last letters (EXT, ARB, ...).
266 I know that some extensions have more than 3 letters (MESA, NV,
267 INTEL, ...), but this is only a stop-gap measure to fix buggy
268 OpenGL drivers (moreover, it is only useful for old 1.0 apps
269 that query the glBindTextureEXT extension).
271 strncpy(buf, lpszProc, strlen(lpszProc) - 3);
272 buf[strlen(lpszProc) - 3] = '\0';
273 TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
275 ret = GetProcAddress(hm, buf);
277 TRACE(" found function in main OpenGL library (%p) !\n", ret);
282 OpenGL_extension ext;
283 OpenGL_extension *ret;
285 ext.name = (char *) lpszProc;
286 ret = (OpenGL_extension *) bsearch(&ext, extension_registry,
287 extension_registry_size, sizeof(OpenGL_extension), compar);
290 TRACE(" returning function (%p)\n", ret->func);
291 *(ret->func_ptr) = local_func;
295 ERR("Extension %s defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n", lpszProc);
301 /***********************************************************************
302 * wglMakeCurrent (OPENGL32.@)
304 BOOL WINAPI wglMakeCurrent(HDC hdc,
308 TRACE("(%08x,%p)\n", hdc, hglrc);
312 ret = glXMakeCurrent(gdi_display,
317 DC * dc = DC_GetDCPtr( hdc );
320 ERR("Null DC !!!\n");
323 X11DRV_PDEVICE *physDev;
324 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
326 physDev =(X11DRV_PDEVICE *)dc->physDev;
328 if (ctx->ctx == NULL) {
330 ctx->ctx = glXCreateContext(gdi_display, ctx->vis, NULL, True);
332 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
336 ret = glXMakeCurrent(gdi_display,
340 GDI_ReleaseObj( hdc );
343 TRACE(" returning %s\n", (ret ? "True" : "False"));
347 /***********************************************************************
348 * wglRealizeLayerPalette (OPENGL32.@)
350 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
358 /***********************************************************************
359 * wglSetLayerPaletteEntries (OPENGL32.@)
361 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
365 const COLORREF *pcr) {
366 FIXME("(): stub !\n");
371 /***********************************************************************
372 * wglShareLists (OPENGL32.@)
374 BOOL WINAPI wglShareLists(HGLRC hglrc1,
376 Wine_GLContext *org = (Wine_GLContext *) hglrc1;
377 Wine_GLContext *dest = (Wine_GLContext *) hglrc2;
379 TRACE("(%p, %p)\n", org, dest);
381 if (dest->ctx != NULL) {
382 ERR("Could not share display lists, context already created !\n");
385 if (org->ctx == NULL) {
387 org->ctx = glXCreateContext(gdi_display, org->vis, NULL, True);
389 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
393 /* Create the destination context with display lists shared */
394 dest->ctx = glXCreateContext(gdi_display, dest->vis, org->ctx, True);
396 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
402 /***********************************************************************
403 * wglSwapLayerBuffers (OPENGL32.@)
405 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
407 FIXME("(): stub !\n");
412 /***********************************************************************
413 * wglUseFontBitmapsA (OPENGL32.@)
415 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
419 DC * dc = DC_GetDCPtr( hdc );
420 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
421 fontObject* pfo = XFONT_GetFontObject( physDev->font );
422 Font fid = pfo->fs->fid;
424 TRACE("(%08x, %ld, %ld, %ld)\n", hdc, first, count, listBase);
427 /* I assume that the glyphs are at the same position for X and for Windows */
428 glXUseXFont(fid, first, count, listBase);
430 GDI_ReleaseObj( hdc );
434 /***********************************************************************
435 * wglUseFontOutlinesA (OPENGL32.@)
437 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
444 LPGLYPHMETRICSFLOAT lpgmf) {
445 FIXME("(): stub !\n");
451 /* This is for brain-dead applications that use OpenGL functions before even
452 creating a rendering context.... */
453 static void process_attach(void) {
454 XWindowAttributes win_attr;
457 XVisualInfo template;
458 XVisualInfo *vis = NULL;
459 Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
463 ERR("X11DRV not loaded. Cannot create default context.\n");
469 /* Try to get the visual from the Root Window. We can't use the standard (presumably
470 double buffered) X11DRV visual with the Root Window, since we don't know if the Root
471 Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
472 with mismatched visuals. Note that the Root Window visual may not be double
473 buffered, so apps actually attempting to render this way may flicker */
474 if (XGetWindowAttributes( gdi_display, root, &win_attr ))
476 rootVisual = win_attr.visual;
480 /* Get the default visual, since we can't seem to get the attributes from the
481 Root Window. Let's hope that the Root Window Visual matches the DefaultVisual */
482 rootVisual = DefaultVisual( gdi_display, DefaultScreen(gdi_display) );
485 template.visualid = XVisualIDFromVisual(rootVisual);
486 vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
487 if (vis != NULL) default_cx = glXCreateContext(gdi_display, vis, 0, GL_TRUE);
488 if (default_cx != NULL) glXMakeCurrent(gdi_display, root, default_cx);
492 if (default_cx == NULL) {
493 ERR("Could not create default context.\n");
496 context_array = NULL;
499 static void process_detach(void) {
500 glXDestroyContext(gdi_display, default_cx);
503 /***********************************************************************
504 * OpenGL initialisation routine
506 BOOL WINAPI OpenGL32_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
509 case DLL_PROCESS_ATTACH:
512 case DLL_PROCESS_DETACH: