Cleaned up dll startup routines now that we have separate address
[wine/testsucceed.git] / dlls / opengl32 / wgl.c
blobfbc9cc99272b296d7cb93047a513417387d10635
1 /* Window-specific OpenGL functions implementation.
3 Copyright (c) 1999 Lionel Ulmer
4 */
6 #include <stdlib.h>
8 #include "wine/exception.h"
10 #include "config.h"
11 #include "debugtools.h"
12 #include "gdi.h"
13 #include "windef.h"
14 #include "winerror.h"
15 #include "wine_gl.h"
16 #include "x11drv.h"
17 #include "x11font.h"
19 #include "wgl.h"
20 #include "opengl_ext.h"
22 DEFAULT_DEBUG_CHANNEL(opengl);
24 static GLXContext default_cx = NULL;
26 typedef struct wine_glcontext {
27 HDC hdc;
28 GLXContext ctx;
29 XVisualInfo *vis;
30 struct wine_glcontext *next;
31 struct wine_glcontext *prev;
32 } Wine_GLContext;
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;
38 return ret;
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) {
50 Wine_GLContext *ret;
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;
57 return ret;
61 static int XGLErrorFlag = 0;
62 static int XGLErrorHandler(Display *dpy, XErrorEvent *event) {
63 XGLErrorFlag = 1;
64 return 0;
66 /* filter for page-fault exceptions */
67 static WINE_EXCEPTION_FILTER(page_fault)
69 return EXCEPTION_EXECUTE_HANDLER;
72 /***********************************************************************
73 * wglCreateContext
75 HGLRC WINAPI wglCreateContext(HDC hdc) {
76 DC * dc = DC_GetDCPtr( hdc );
77 X11DRV_PDEVICE *physDev;
78 XVisualInfo *vis;
79 Wine_GLContext *ret;
81 TRACE("(%08x)\n", hdc);
83 if (dc == NULL) {
84 ERR("Null DC !!!\n");
85 return NULL;
88 physDev = (X11DRV_PDEVICE *)dc->physDev;
90 /* First, get the visual for the choosen pixel format */
91 vis = physDev->visuals[physDev->current_pf - 1];
93 if (vis == NULL) {
94 ERR("NULL visual !!!\n");
95 /* Need to set errors here */
96 GDI_ReleaseObj( hdc );
97 return NULL;
100 /* The context will be allocated in the wglMakeCurrent call */
101 ENTER_GL();
102 ret = alloc_context();
103 LEAVE_GL();
104 ret->hdc = hdc;
105 ret->vis = vis;
107 TRACE(" creating context %p (GL context creation delayed)\n", ret);
109 GDI_ReleaseObj( hdc );
110 return (HGLRC) ret;
113 /***********************************************************************
114 * wglCreateLayerContext
116 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
117 int iLayerPlane) {
118 FIXME("(%08x,%d): stub !\n", hdc, iLayerPlane);
120 return NULL;
123 /***********************************************************************
124 * wglCopyContext
126 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
127 HGLRC hglrcDst,
128 UINT mask) {
129 FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
131 return FALSE;
134 /***********************************************************************
135 * wglDeleteContext
137 BOOL WINAPI wglDeleteContext(HGLRC hglrc) {
138 int (*WineXHandler)(Display *, XErrorEvent *);
139 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
140 BOOL ret;
142 TRACE("(%p)\n", hglrc);
144 ENTER_GL();
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);
148 XGLErrorFlag = 0;
149 WineXHandler = XSetErrorHandler(XGLErrorHandler);
150 __TRY {
151 glXDestroyContext(display, ctx->ctx);
152 XSync(display, False);
153 XFlush(display);
155 if (XGLErrorHandler == 0) free_context(ctx);
157 __EXCEPT(page_fault) {
158 XGLErrorFlag = 1;
160 __ENDTRY
162 ret = TRUE;
163 XSetErrorHandler(WineXHandler);
164 if (XGLErrorFlag) {
165 WARN("Error deleting context !\n");
166 SetLastError(ERROR_INVALID_HANDLE);
167 ret = FALSE;
169 LEAVE_GL();
171 return ret;
174 /***********************************************************************
175 * wglDescribeLayerPlane
177 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
178 int iPixelFormat,
179 int iLayerPlane,
180 UINT nBytes,
181 LPLAYERPLANEDESCRIPTOR plpd) {
182 FIXME("(%08x,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
184 return FALSE;
187 /***********************************************************************
188 * wglGetCurrentContext
190 HGLRC WINAPI wglGetCurrentContext(void) {
191 GLXContext gl_ctx;
192 Wine_GLContext *ret;
194 TRACE("()\n");
196 ENTER_GL();
197 gl_ctx = glXGetCurrentContext();
198 ret = get_context_from_GLXContext(gl_ctx);
199 LEAVE_GL();
201 TRACE(" returning %p (GL context %p)\n", ret, gl_ctx);
203 return ret;
206 /***********************************************************************
207 * wglGetCurrentDC
209 HDC WINAPI wglGetCurrentDC(void) {
210 GLXContext gl_ctx;
211 Wine_GLContext *ret;
213 TRACE("()\n");
215 ENTER_GL();
216 gl_ctx = glXGetCurrentContext();
217 ret = get_context_from_GLXContext(gl_ctx);
218 LEAVE_GL();
220 if (ret) {
221 TRACE(" returning %08x (GL context %p - Wine context %p)\n", ret->hdc, gl_ctx, ret);
222 return ret->hdc;
223 } else {
224 TRACE(" no Wine context found for GLX context %p\n", gl_ctx);
225 return 0;
229 /***********************************************************************
230 * wglGetLayerPaletteEntries
232 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
233 int iLayerPlane,
234 int iStart,
235 int cEntries,
236 const COLORREF *pcr) {
237 FIXME("(): stub !\n");
239 return 0;
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 /***********************************************************************
248 * wglGetProcAddress
250 void* WINAPI wglGetProcAddress(LPCSTR lpszProc) {
251 void *local_func;
252 static HMODULE hm = 0;
254 TRACE("(%s)\n", lpszProc);
256 if (hm == 0)
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);
262 return local_func;
265 /* After that, look at the extensions defined in the Linux OpenGL library */
266 if ((local_func = glXGetProcAddressARB(lpszProc)) == NULL) {
267 char buf[256];
268 void *ret = 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);
282 if (ret != NULL) {
283 TRACE(" found function in main OpenGL library (%p) !\n", ret);
286 return ret;
287 } else {
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);
295 if (ret != NULL) {
296 TRACE(" returning function (%p)\n", ret->func);
297 *(ret->func_ptr) = local_func;
299 return ret->func;
300 } else {
301 ERR("Extension defined in the OpenGL library but NOT in opengl_ext.c... Please report (lionel.ulmer@free.fr) !\n");
302 return NULL;
307 /***********************************************************************
308 * wglMakeCurrent
310 BOOL WINAPI wglMakeCurrent(HDC hdc,
311 HGLRC hglrc) {
312 BOOL ret;
314 TRACE("(%08x,%p)\n", hdc, hglrc);
316 if (hglrc == NULL) {
317 ENTER_GL();
318 ret = glXMakeCurrent(display,
319 None,
320 NULL);
321 LEAVE_GL();
322 } else {
323 DC * dc = DC_GetDCPtr( hdc );
325 if (dc == NULL) {
326 ERR("Null DC !!!\n");
327 ret = FALSE;
328 } else {
329 X11DRV_PDEVICE *physDev;
330 Wine_GLContext *ctx = (Wine_GLContext *) hglrc;
332 physDev =(X11DRV_PDEVICE *)dc->physDev;
334 if (ctx->ctx == NULL) {
335 ENTER_GL();
336 ctx->ctx = glXCreateContext(display, ctx->vis, NULL, True);
337 LEAVE_GL();
338 TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx);
341 ENTER_GL();
342 ret = glXMakeCurrent(display,
343 physDev->drawable,
344 ctx->ctx);
345 LEAVE_GL();
346 GDI_ReleaseObj( hdc );
349 TRACE(" returning %s\n", (ret ? "True" : "False"));
350 return ret;
353 /***********************************************************************
354 * wglRealizeLayerPalette
356 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
357 int iLayerPlane,
358 BOOL bRealize) {
359 FIXME("()\n");
361 return FALSE;
364 /***********************************************************************
365 * wglSetLayerPaletteEntries
367 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
368 int iLayerPlane,
369 int iStart,
370 int cEntries,
371 const COLORREF *pcr) {
372 FIXME("(): stub !\n");
374 return 0;
377 /***********************************************************************
378 * wglShareLists
380 BOOL WINAPI wglShareLists(HGLRC hglrc1,
381 HGLRC hglrc2) {
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");
389 return FALSE;
390 } else {
391 if (org->ctx == NULL) {
392 ENTER_GL();
393 org->ctx = glXCreateContext(display, org->vis, NULL, True);
394 LEAVE_GL();
395 TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org);
398 ENTER_GL();
399 /* Create the destination context with display lists shared */
400 dest->ctx = glXCreateContext(display, dest->vis, org->ctx, True);
401 LEAVE_GL();
402 TRACE(" created a delayed OpenGL context (%p) for Wine context %p sharing lists with OpenGL ctx %p\n", dest->ctx, dest, org->ctx);
405 return TRUE;
408 /***********************************************************************
409 * wglSwapLayerBuffers
411 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
412 UINT fuPlanes) {
413 FIXME("(): stub !\n");
415 return FALSE;
418 /***********************************************************************
419 * wglUseFontBitmapsA
421 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
422 DWORD first,
423 DWORD count,
424 DWORD listBase) {
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);
432 ENTER_GL();
433 /* I assume that the glyphs are at the same position for X and for Windows */
434 glXUseXFont(fid, first, count, listBase);
435 LEAVE_GL();
436 GDI_ReleaseObj( hdc );
437 return TRUE;
440 /***********************************************************************
441 * wglUseFontOutlinesA
443 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
444 DWORD first,
445 DWORD count,
446 DWORD listBase,
447 FLOAT deviation,
448 FLOAT extrusion,
449 int format,
450 LPGLYPHMETRICSFLOAT lpgmf) {
451 FIXME("(): stub !\n");
453 return FALSE;
457 /* This is for brain-dead applications that use OpenGL functions before even
458 creating a rendering context.... */
459 static void process_attach(void) {
460 int num;
461 XVisualInfo template;
462 XVisualInfo *vis = NULL;
464 if (!visual) {
465 ERR("X11DRV not loaded yet. Cannot create default context.\n");
466 return;
469 ENTER_GL();
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);
474 XFree(vis);
475 LEAVE_GL();
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 switch(reason) {
494 case DLL_PROCESS_ATTACH:
495 process_attach();
496 break;
497 case DLL_PROCESS_DETACH:
498 process_detach();
499 break;
501 return TRUE;