winex11.drv: Move WGL extension code to winex11.drv.
[wine] / dlls / opengl32 / wgl.c
1 /* Window-specific OpenGL functions implementation.
2  *
3  * Copyright (c) 1999 Lionel Ulmer
4  * Copyright (c) 2005 Raphael Junqueira
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winternl.h"
35 #include "winnt.h"
36
37 #include "wgl_ext.h"
38 #include "opengl_ext.h"
39 #ifdef HAVE_GL_GLU_H
40 #undef far
41 #undef near
42 #include <GL/glu.h>
43 #endif
44 #include "wine/library.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
48 WINE_DECLARE_DEBUG_CHANNEL(opengl);
49
50 typedef struct wine_glx_s {
51   unsigned     version;
52   /** SGIX / 1.3 */
53   GLXFBConfig* (*p_glXChooseFBConfig) (Display *dpy, int screen, const int *attrib_list, int *nelements);
54   int          (*p_glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, int attribute, int *value);
55   XVisualInfo* (*p_glXGetVisualFromFBConfig) (Display *dpy, GLXFBConfig config); 
56   /** 1.3 */
57   GLXFBConfig* (*p_glXGetFBConfigs) (Display *dpy, int screen, int *nelements);
58   void         (*p_glXQueryDrawable) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
59   Bool         (*p_glXMakeContextCurrent) (Display *, GLXDrawable, GLXDrawable, GLXContext);
60 } wine_glx_t;
61
62 typedef struct wine_wgl_s {
63     HGLRC WINAPI (*p_wglCreateContext)(HDC hdc);
64     BOOL WINAPI  (*p_wglDeleteContext)(HGLRC hglrc);
65     HGLRC WINAPI (*p_wglGetCurrentContext)(void);
66     HDC WINAPI   (*p_wglGetCurrentDC)(void);
67     HDC WINAPI   (*p_wglGetCurrentReadDCARB)(void);
68     PROC WINAPI  (*p_wglGetProcAddress)(LPCSTR  lpszProc);
69     BOOL WINAPI  (*p_wglMakeCurrent)(HDC hdc, HGLRC hglrc);
70     BOOL WINAPI  (*p_wglMakeContextCurrentARB)(HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 
71     BOOL WINAPI  (*p_wglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
72
73     void WINAPI  (*p_wglGetIntegerv)(GLenum pname, GLint* params);
74 } wine_wgl_t;
75
76 /** global glx object */
77 static wine_glx_t wine_glx;
78 /** global wgl object */
79 static wine_wgl_t wine_wgl;
80
81 /* x11drv GDI escapes */
82 #define X11DRV_ESCAPE 6789
83 enum x11drv_escape_codes
84 {
85     X11DRV_GET_DISPLAY,         /* get X11 display for a DC */
86     X11DRV_GET_DRAWABLE,        /* get current drawable for a DC */
87     X11DRV_GET_FONT,            /* get current X font for a DC */
88     X11DRV_SET_DRAWABLE,        /* set current drawable for a DC */
89     X11DRV_START_EXPOSURES,     /* start graphics exposures */
90     X11DRV_END_EXPOSURES,       /* end graphics exposures */
91     X11DRV_GET_DCE,             /* get the DCE pointer */
92     X11DRV_SET_DCE,             /* set the DCE pointer */
93     X11DRV_GET_GLX_DRAWABLE,    /* get current glx drawable for a DC */
94     X11DRV_SYNC_PIXMAP          /* sync the dibsection to its pixmap */
95 };
96
97 void (*wine_tsx11_lock_ptr)(void) = NULL;
98 void (*wine_tsx11_unlock_ptr)(void) = NULL;
99
100 static GLXContext default_cx = NULL;
101 static Display *default_display;  /* display to use for default context */
102
103 static HMODULE opengl32_handle;
104
105 static glXGetProcAddressARB_t p_glXGetProcAddressARB = NULL;
106
107 static char  internal_gl_disabled_extensions[512];
108 static char* internal_gl_extensions = NULL;
109
110 typedef struct wine_glcontext {
111   HDC hdc;
112   Display *display;
113   XVisualInfo *vis;
114   GLXFBConfig fb_conf;
115   GLXContext ctx;
116   BOOL do_escape;
117   struct wine_glcontext *next;
118   struct wine_glcontext *prev;
119 } Wine_GLContext;
120
121 void enter_gl(void)
122 {
123     Wine_GLContext *curctx = (Wine_GLContext *) NtCurrentTeb()->glContext;
124     
125     if (curctx && curctx->do_escape)
126     {
127         enum x11drv_escape_codes escape = X11DRV_SYNC_PIXMAP;
128         ExtEscape(curctx->hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape, 0, NULL);
129     }
130
131     wine_tsx11_lock_ptr();
132     return;
133 }
134
135 /* retrieve the X display to use on a given DC */
136 inline static Display *get_display( HDC hdc )
137 {
138     Display *display;
139     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
140
141     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
142                     sizeof(display), (LPSTR)&display )) display = NULL;
143     return display;
144 }
145
146 /* retrieve the X font to use on a given DC */
147 inline static Font get_font( HDC hdc )
148 {
149     Font font;
150     enum x11drv_escape_codes escape = X11DRV_GET_FONT;
151
152     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
153                     sizeof(font), (LPSTR)&font )) font = 0;
154     return font;
155 }
156
157 /* GLX can advertise dozens of different pixelformats including offscreen and onscreen ones.
158  * In our WGL implementation we only support a subset of these formats namely the format of
159  * Wine's main visual and offscreen formats (if they are available).
160  * This function converts a WGL format to its corresponding GLX one. It returns the index (zero-based)
161  * into the GLX FB config table and it returns the number of supported WGL formats in fmt_count.
162  */
163 BOOL ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, int *fmt_index, int *fmt_count)
164 {
165   int res = FALSE;
166   int i = 0;
167   GLXFBConfig* cfgs = NULL;
168   int nCfgs = 0;
169   int tmp_fmt_id = 0;
170   int tmp_vis_id = 0;
171   int nFormats = 1; /* Start at 1 as we always have a main visual */
172   VisualID visualid = 0;
173
174   /* Request to look up the format of the main visual when iPixelFormat = 1 */
175   if(iPixelFormat == 1) visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
176
177   /* As mentioned in various parts of the code only the format of the main visual can be used for onscreen rendering.
178    * Next to this format there are also so called offscreen rendering formats (used for pbuffers) which can be supported
179    * because they don't need a visual. Below we use glXGetFBConfigs instead of glXChooseFBConfig to enumerate the fb configurations
180    * bas this call lists both types of formats instead of only onscreen ones. */
181   cfgs = wine_glx.p_glXGetFBConfigs(display, DefaultScreen(display), &nCfgs);
182   if (NULL == cfgs || 0 == nCfgs) {
183     ERR("glXChooseFBConfig returns NULL\n");
184     if(cfgs != NULL) XFree(cfgs);
185     return FALSE;
186   }
187
188   /* Find the requested offscreen format and count the number of offscreen formats */
189   for(i=0; i<nCfgs; i++) {
190     wine_glx.p_glXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
191     wine_glx.p_glXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
192
193     /* We are looking up the GLX index of our main visual and have found it :) */
194     if(iPixelFormat == 1 && visualid == tmp_vis_id) {
195       *fmt_index = i;
196       TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", tmp_fmt_id, *fmt_index, tmp_vis_id);
197       res = TRUE;
198     }
199     /* We found an offscreen rendering format :) */
200     else if(tmp_vis_id == 0) {
201       nFormats++;
202       TRACE("Checking offscreen format FBCONFIG_ID 0x%x at index %d\n", tmp_fmt_id, i);
203
204       if(iPixelFormat == nFormats) {
205         *fmt_index = i;
206         TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", tmp_fmt_id, iPixelFormat, i);
207         res = TRUE;
208       }
209     }
210   }
211   *fmt_count = nFormats;
212   TRACE("Number of offscreen formats: %d; returning index: %d\n", *fmt_count, *fmt_index);
213
214   if(cfgs != NULL) XFree(cfgs);
215
216   return res;
217 }
218
219 /***********************************************************************
220  *              wglCreateContext (OPENGL32.@)
221  */
222 HGLRC WINAPI wglCreateContext(HDC hdc)
223 {
224     TRACE("(%p)\n", hdc);
225     return wine_wgl.p_wglCreateContext(hdc);
226 }
227
228 /***********************************************************************
229  *              wglCreateLayerContext (OPENGL32.@)
230  */
231 HGLRC WINAPI wglCreateLayerContext(HDC hdc,
232                                    int iLayerPlane) {
233   TRACE("(%p,%d)\n", hdc, iLayerPlane);
234
235   if (iLayerPlane == 0) {
236       return wglCreateContext(hdc);
237   }
238   FIXME(" no handler for layer %d\n", iLayerPlane);
239
240   return NULL;
241 }
242
243 /***********************************************************************
244  *              wglCopyContext (OPENGL32.@)
245  */
246 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc,
247                            HGLRC hglrcDst,
248                            UINT mask) {
249   FIXME("(%p,%p,%d)\n", hglrcSrc, hglrcDst, mask);
250
251   return FALSE;
252 }
253
254 /***********************************************************************
255  *              wglDeleteContext (OPENGL32.@)
256  */
257 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
258 {
259     TRACE("(%p)\n", hglrc);
260     return wine_wgl.p_wglDeleteContext(hglrc);
261 }
262
263 /***********************************************************************
264  *              wglDescribeLayerPlane (OPENGL32.@)
265  */
266 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
267                                   int iPixelFormat,
268                                   int iLayerPlane,
269                                   UINT nBytes,
270                                   LPLAYERPLANEDESCRIPTOR plpd) {
271   FIXME("(%p,%d,%d,%d,%p)\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
272
273   return FALSE;
274 }
275
276 /***********************************************************************
277  *              wglGetCurrentContext (OPENGL32.@)
278  */
279 HGLRC WINAPI wglGetCurrentContext(void) {
280     TRACE("\n");
281     return wine_wgl.p_wglGetCurrentContext();
282 }
283
284 /***********************************************************************
285  *              wglGetCurrentDC (OPENGL32.@)
286  */
287 HDC WINAPI wglGetCurrentDC(void) {
288     TRACE("\n");
289     return wine_wgl.p_wglGetCurrentDC();
290 }
291
292 /***********************************************************************
293  *              wglGetLayerPaletteEntries (OPENGL32.@)
294  */
295 int WINAPI wglGetLayerPaletteEntries(HDC hdc,
296                                      int iLayerPlane,
297                                      int iStart,
298                                      int cEntries,
299                                      const COLORREF *pcr) {
300   FIXME("(): stub !\n");
301
302   return 0;
303 }
304
305 /***********************************************************************
306  *              wglGetProcAddress (OPENGL32.@)
307  */
308 static int compar(const void *elt_a, const void *elt_b) {
309   return strcmp(((const OpenGL_extension *) elt_a)->name,
310                 ((const OpenGL_extension *) elt_b)->name);
311 }
312
313 PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc) {
314   void *local_func;
315   OpenGL_extension  ext;
316   const OpenGL_extension *ext_ret;
317
318   TRACE("(%s)\n", lpszProc);
319
320   /* First, look if it's not already defined in the 'standard' OpenGL functions */
321   if ((local_func = GetProcAddress(opengl32_handle, lpszProc)) != NULL) {
322     TRACE(" found function in 'standard' OpenGL functions (%p)\n", local_func);
323     return local_func;
324   }
325
326   if (p_glXGetProcAddressARB == NULL) {
327     ERR("Warning : dynamic GL extension loading not supported by native GL library.\n");
328     return NULL;
329   }
330   
331   /* After that, search in the thunks to find the real name of the extension */
332   ext.name = lpszProc;
333   ext_ret = (const OpenGL_extension *) bsearch(&ext, extension_registry,
334                                          extension_registry_size, sizeof(OpenGL_extension), compar);
335
336   /* If nothing was found, we are looking for a WGL extension */
337   if (ext_ret == NULL) {
338     return wine_wgl.p_wglGetProcAddress(lpszProc);
339   } else { /* We are looking for an OpenGL extension */
340     const char *glx_name = ext_ret->glx_name ? ext_ret->glx_name : ext_ret->name;
341     ENTER_GL();
342     local_func = p_glXGetProcAddressARB( (const GLubyte*)glx_name);
343     LEAVE_GL();
344     
345     /* After that, look at the extensions defined in the Linux OpenGL library */
346     if (local_func == NULL) {
347       char buf[256];
348       void *ret = NULL;
349
350       /* Remove the 3 last letters (EXT, ARB, ...).
351
352          I know that some extensions have more than 3 letters (MESA, NV,
353          INTEL, ...), but this is only a stop-gap measure to fix buggy
354          OpenGL drivers (moreover, it is only useful for old 1.0 apps
355          that query the glBindTextureEXT extension).
356       */
357       memcpy(buf, glx_name, strlen(glx_name) - 3);
358       buf[strlen(glx_name) - 3] = '\0';
359       TRACE(" extension not found in the Linux OpenGL library, checking against libGL bug with %s..\n", buf);
360
361       ret = GetProcAddress(opengl32_handle, buf);
362       if (ret != NULL) {
363         TRACE(" found function in main OpenGL library (%p) !\n", ret);
364       } else {
365         WARN("Did not find function %s (%s) in your OpenGL library !\n", lpszProc, glx_name);
366       }
367
368       return ret;
369     } else {
370       TRACE(" returning function  (%p)\n", ext_ret->func);
371       extension_funcs[ext_ret - extension_registry] = local_func;
372
373       return ext_ret->func;
374     }
375   }
376 }
377
378 /***********************************************************************
379  *              wglMakeCurrent (OPENGL32.@)
380  */
381 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc) {
382     TRACE("hdc: (%p), hglrc: (%p)\n", hdc, hglrc);
383     return wine_wgl.p_wglMakeCurrent(hdc, hglrc);
384 }
385
386 /***********************************************************************
387  *              wglMakeContextCurrentARB (OPENGL32.@)
388  */
389 BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc) 
390 {
391     TRACE("hDrawDC: (%p), hReadDC: (%p), hglrc: (%p)\n", hDrawDC, hReadDC, hglrc);
392     return wine_wgl.p_wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc);
393 }
394
395 /***********************************************************************
396  *              wglGetCurrentReadDCARB (OPENGL32.@)
397  */
398 HDC WINAPI wglGetCurrentReadDCARB(void) 
399 {
400     TRACE("\n");
401     return wine_wgl.p_wglGetCurrentReadDCARB();
402 }
403
404 /***********************************************************************
405  *              wglRealizeLayerPalette (OPENGL32.@)
406  */
407 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
408                                    int iLayerPlane,
409                                    BOOL bRealize) {
410   FIXME("()\n");
411
412   return FALSE;
413 }
414
415 /***********************************************************************
416  *              wglSetLayerPaletteEntries (OPENGL32.@)
417  */
418 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
419                                      int iLayerPlane,
420                                      int iStart,
421                                      int cEntries,
422                                      const COLORREF *pcr) {
423   FIXME("(): stub !\n");
424
425   return 0;
426 }
427
428 /***********************************************************************
429  *              wglShareLists (OPENGL32.@)
430  */
431 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
432     TRACE("(%p, %p)\n", hglrc1, hglrc2);
433     return wine_wgl.p_wglShareLists(hglrc1, hglrc2);
434 }
435
436 /***********************************************************************
437  *              wglSwapLayerBuffers (OPENGL32.@)
438  */
439 BOOL WINAPI wglSwapLayerBuffers(HDC hdc,
440                                 UINT fuPlanes) {
441   TRACE_(opengl)("(%p, %08x)\n", hdc, fuPlanes);
442
443   if (fuPlanes & WGL_SWAP_MAIN_PLANE) {
444     if (!SwapBuffers(hdc)) return FALSE;
445     fuPlanes &= ~WGL_SWAP_MAIN_PLANE;
446   }
447
448   if (fuPlanes) {
449     WARN("Following layers unhandled : %08x\n", fuPlanes);
450   }
451
452   return TRUE;
453 }
454
455 static BOOL internal_wglUseFontBitmaps(HDC hdc,
456                                        DWORD first,
457                                        DWORD count,
458                                        DWORD listBase,
459                                        DWORD (WINAPI *GetGlyphOutline_ptr)(HDC,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*))
460 {
461     /* We are running using client-side rendering fonts... */
462     GLYPHMETRICS gm;
463     unsigned int glyph;
464     int size = 0;
465     void *bitmap = NULL, *gl_bitmap = NULL;
466     int org_alignment;
467
468     ENTER_GL();
469     glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
470     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
471     LEAVE_GL();
472
473     for (glyph = first; glyph < first + count; glyph++) {
474         unsigned int needed_size = GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, 0, NULL, NULL);
475         int height, width_int;
476
477         TRACE("Glyph : %3d / List : %ld\n", glyph, listBase);
478         if (needed_size == GDI_ERROR) {
479             TRACE("  - needed size : %d (GDI_ERROR)\n", needed_size);
480             goto error;
481         } else {
482             TRACE("  - needed size : %d\n", needed_size);
483         }
484
485         if (needed_size > size) {
486             size = needed_size;
487             HeapFree(GetProcessHeap(), 0, bitmap);
488             HeapFree(GetProcessHeap(), 0, gl_bitmap);
489             bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
490             gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
491         }
492         if (GetGlyphOutline_ptr(hdc, glyph, GGO_BITMAP, &gm, size, bitmap, NULL) == GDI_ERROR) goto error;
493         if (TRACE_ON(opengl)) {
494             unsigned int height, width, bitmask;
495             unsigned char *bitmap_ = (unsigned char *) bitmap;
496             
497             TRACE("  - bbox : %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
498             TRACE("  - origin : (%ld , %ld)\n", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
499             TRACE("  - increment : %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
500             if (needed_size != 0) {
501                 TRACE("  - bitmap :\n");
502                 for (height = 0; height < gm.gmBlackBoxY; height++) {
503                     TRACE("      ");
504                     for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++, bitmask >>= 1) {
505                         if (bitmask == 0) {
506                             bitmap_ += 1;
507                             bitmask = 0x80;
508                         }
509                         if (*bitmap_ & bitmask)
510                             TRACE("*");
511                         else
512                             TRACE(" ");
513                     }
514                     bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
515                     TRACE("\n");
516                 }
517             }
518         }
519         
520         /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to invert the
521          * glyph for it to be drawn properly.
522          */
523         if (needed_size != 0) {
524             width_int = (gm.gmBlackBoxX + 31) / 32;
525             for (height = 0; height < gm.gmBlackBoxY; height++) {
526                 int width;
527                 for (width = 0; width < width_int; width++) {
528                     ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int + width] =
529                         ((int *) bitmap)[height * width_int + width];
530                 }
531             }
532         }
533         
534         ENTER_GL();
535         glNewList(listBase++, GL_COMPILE);
536         if (needed_size != 0) {
537             glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
538                      0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y,
539                      gm.gmCellIncX, gm.gmCellIncY,
540                      gl_bitmap);
541         } else {
542             /* This is the case of 'empty' glyphs like the space character */
543             glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
544         }
545         glEndList();
546         LEAVE_GL();
547     }
548     
549     ENTER_GL();
550     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
551     LEAVE_GL();
552     
553     HeapFree(GetProcessHeap(), 0, bitmap);
554     HeapFree(GetProcessHeap(), 0, gl_bitmap);
555     return TRUE;
556
557   error:
558     ENTER_GL();
559     glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
560     LEAVE_GL();
561
562     HeapFree(GetProcessHeap(), 0, bitmap);
563     HeapFree(GetProcessHeap(), 0, gl_bitmap);
564     return FALSE;    
565 }
566
567 /***********************************************************************
568  *              wglUseFontBitmapsA (OPENGL32.@)
569  */
570 BOOL WINAPI wglUseFontBitmapsA(HDC hdc,
571                                DWORD first,
572                                DWORD count,
573                                DWORD listBase)
574 {
575   Font fid = get_font( hdc );
576
577   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
578
579   if (fid == 0) {
580       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineA);
581   }
582
583   ENTER_GL();
584   /* I assume that the glyphs are at the same position for X and for Windows */
585   glXUseXFont(fid, first, count, listBase);
586   LEAVE_GL();
587   return TRUE;
588 }
589
590 /***********************************************************************
591  *              wglUseFontBitmapsW (OPENGL32.@)
592  */
593 BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
594                                DWORD first,
595                                DWORD count,
596                                DWORD listBase)
597 {
598   Font fid = get_font( hdc );
599
600   TRACE("(%p, %ld, %ld, %ld) using font %ld\n", hdc, first, count, listBase, fid);
601
602   if (fid == 0) {
603       return internal_wglUseFontBitmaps(hdc, first, count, listBase, GetGlyphOutlineW);
604   }
605
606   WARN("Using the glX API for the WCHAR variant - some characters may come out incorrectly !\n");
607   
608   ENTER_GL();
609   /* I assume that the glyphs are at the same position for X and for Windows */
610   glXUseXFont(fid, first, count, listBase);
611   LEAVE_GL();
612   return TRUE;
613 }
614
615 #ifdef HAVE_GL_GLU_H
616
617 static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
618 {
619     vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;  
620     vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;  
621     vertex[2] = 0.0;
622 }
623
624 static void tess_callback_vertex(GLvoid *vertex)
625 {
626     GLdouble *dbl = vertex;
627     TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
628     glVertex3dv(vertex);
629 }
630
631 static void tess_callback_begin(GLenum which)
632 {
633     TRACE("%d\n", which);
634     glBegin(which);
635 }
636
637 static void tess_callback_end(void)
638 {
639     TRACE("\n");
640     glEnd();
641 }
642
643 /***********************************************************************
644  *              wglUseFontOutlines_common
645  */
646 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
647                                       DWORD first,
648                                       DWORD count,
649                                       DWORD listBase,
650                                       FLOAT deviation,
651                                       FLOAT extrusion,
652                                       int format,
653                                       LPGLYPHMETRICSFLOAT lpgmf,
654                                       BOOL unicode)
655 {
656     UINT glyph;
657     const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
658     GLUtesselator *tess;
659     LOGFONTW lf;
660     HFONT old_font, unscaled_font;
661     UINT em_size = 1024;
662     RECT rc;
663
664     TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
665           listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
666
667
668     ENTER_GL();
669     tess = gluNewTess();
670     if(tess)
671     {
672         gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
673         gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
674         gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
675     }
676     LEAVE_GL();
677
678     if(!tess) return FALSE;
679
680     GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
681     rc.left = rc.right = rc.bottom = 0;
682     rc.top = em_size;
683     DPtoLP(hdc, (POINT*)&rc, 2);
684     lf.lfHeight = -abs(rc.top - rc.bottom);
685     lf.lfOrientation = lf.lfEscapement = 0;
686     unscaled_font = CreateFontIndirectW(&lf);
687     old_font = SelectObject(hdc, unscaled_font);
688
689     for (glyph = first; glyph < first + count; glyph++)
690     {
691         DWORD needed;
692         GLYPHMETRICS gm;
693         BYTE *buf;
694         TTPOLYGONHEADER *pph;
695         TTPOLYCURVE *ppc;
696         GLdouble *vertices;
697
698         if(unicode)
699             needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
700         else
701             needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
702
703         if(needed == GDI_ERROR)
704             goto error;
705
706         buf = HeapAlloc(GetProcessHeap(), 0, needed);
707         vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
708
709         if(unicode)
710             GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
711         else
712             GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
713
714         TRACE("glyph %d\n", glyph);
715
716         if(lpgmf)
717         {
718             lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
719             lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
720             lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
721             lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
722             lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
723             lpgmf->gmfCellIncY = (float)gm.gmCellIncY / em_size;
724
725             TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
726                   lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY); 
727             lpgmf++;
728         }
729
730         ENTER_GL();
731         glNewList(listBase++, GL_COMPILE);
732         gluTessBeginPolygon(tess, NULL);
733
734         pph = (TTPOLYGONHEADER*)buf;
735         while((BYTE*)pph < buf + needed)
736         {
737             TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
738
739             gluTessBeginContour(tess);
740
741             fixed_to_double(pph->pfxStart, em_size, vertices);
742             gluTessVertex(tess, vertices, vertices);
743             vertices += 3;
744
745             ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
746             while((char*)ppc < (char*)pph + pph->cb)
747             {
748                 int i;
749
750                 switch(ppc->wType) {
751                 case TT_PRIM_LINE:
752                     for(i = 0; i < ppc->cpfx; i++)
753                     {
754                         TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
755                         fixed_to_double(ppc->apfx[i], em_size, vertices); 
756                         gluTessVertex(tess, vertices, vertices);
757                         vertices += 3;
758                     }
759                     break;
760
761                 case TT_PRIM_QSPLINE:
762                     for(i = 0; i < ppc->cpfx/2; i++)
763                     {
764                         /* FIXME just connecting the control points for now */
765                         TRACE("\t\tcurve  %d,%d %d,%d\n",
766                               ppc->apfx[i * 2].x.value,     ppc->apfx[i * 3].y.value,
767                               ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
768                         fixed_to_double(ppc->apfx[i * 2], em_size, vertices); 
769                         gluTessVertex(tess, vertices, vertices);
770                         vertices += 3;
771                         fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices); 
772                         gluTessVertex(tess, vertices, vertices);
773                         vertices += 3;
774                     }
775                     break;
776                 default:
777                     ERR("\t\tcurve type = %d\n", ppc->wType);
778                     gluTessEndContour(tess);
779                     goto error_in_list;
780                 }
781
782                 ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
783                                      (ppc->cpfx - 1) * sizeof(POINTFX));
784             }
785             gluTessEndContour(tess);
786             pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
787         }
788
789 error_in_list:
790         gluTessEndPolygon(tess);
791         glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0);
792         glEndList();
793         LEAVE_GL();
794         HeapFree(GetProcessHeap(), 0, buf);
795         HeapFree(GetProcessHeap(), 0, vertices);
796     }
797
798  error:
799     DeleteObject(SelectObject(hdc, old_font));
800     gluDeleteTess(tess);
801     return TRUE;
802
803 }
804
805 #else /* HAVE_GL_GLU_H */
806
807 BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
808                                       DWORD first,
809                                       DWORD count,
810                                       DWORD listBase,
811                                       FLOAT deviation,
812                                       FLOAT extrusion,
813                                       int format,
814                                       LPGLYPHMETRICSFLOAT lpgmf,
815                                       BOOL unicode)
816 {
817     FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
818     return FALSE;
819 }
820
821 #endif /* HAVE_GL_GLU_H */
822
823 /***********************************************************************
824  *              wglUseFontOutlinesA (OPENGL32.@)
825  */
826 BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
827                                 DWORD first,
828                                 DWORD count,
829                                 DWORD listBase,
830                                 FLOAT deviation,
831                                 FLOAT extrusion,
832                                 int format,
833                                 LPGLYPHMETRICSFLOAT lpgmf)
834 {
835     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
836 }
837
838 /***********************************************************************
839  *              wglUseFontOutlinesW (OPENGL32.@)
840  */
841 BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
842                                 DWORD first,
843                                 DWORD count,
844                                 DWORD listBase,
845                                 FLOAT deviation,
846                                 FLOAT extrusion,
847                                 int format,
848                                 LPGLYPHMETRICSFLOAT lpgmf)
849 {
850     return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
851 }
852
853 const GLubyte * internal_glGetString(GLenum name) {
854   const char* GL_Extensions = NULL;
855   
856   if (GL_EXTENSIONS != name) {
857     return glGetString(name);
858   }
859
860   if (NULL == internal_gl_extensions) {
861     GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
862
863     TRACE("GL_EXTENSIONS reported:\n");  
864     if (NULL == GL_Extensions) {
865       ERR("GL_EXTENSIONS returns NULL\n");      
866       return NULL;
867     } else {
868       size_t len = strlen(GL_Extensions);
869       internal_gl_extensions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 2);
870
871       while (*GL_Extensions != 0x00) {
872         const char* Start = GL_Extensions;
873         char        ThisExtn[256];
874          
875         memset(ThisExtn, 0x00, sizeof(ThisExtn));
876         while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
877           GL_Extensions++;
878         }
879         memcpy(ThisExtn, Start, (GL_Extensions - Start));
880         TRACE("- %s:", ThisExtn);
881         
882         /* test if supported API is disabled by config */
883         if (NULL == strstr(internal_gl_disabled_extensions, ThisExtn)) {
884           strcat(internal_gl_extensions, " ");
885           strcat(internal_gl_extensions, ThisExtn);
886           TRACE(" active\n");
887         } else {
888           TRACE(" deactived (by config)\n");
889         }
890
891         if (*GL_Extensions == ' ') GL_Extensions++;
892       }
893     }
894   }
895   return (const GLubyte *) internal_gl_extensions;
896 }
897
898 void internal_glGetIntegerv(GLenum pname, GLint* params) {
899   TRACE("pname: 0x%x, params %p\n", pname, params);
900   glGetIntegerv(pname, params);
901   /* A few parameters like GL_DEPTH_BITS differ between WGL and GLX, the wglGetIntegerv helper function handles those */
902   wine_wgl.p_wglGetIntegerv(pname, params);
903 }
904
905
906 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
907    include all dependencies
908 */
909 #ifndef SONAME_LIBGL
910 #define SONAME_LIBGL "libGL.so"
911 #endif
912
913 static void wgl_initialize_glx(Display *display, int screen, glXGetProcAddressARB_t proc) 
914 {
915   const char *server_glx_version = glXQueryServerString(display, screen, GLX_VERSION);
916   const char *client_glx_version = glXGetClientString(display, GLX_VERSION);
917   const char *glx_extensions = NULL;
918   BOOL glx_direct = glXIsDirect(display, default_cx);
919
920   memset(&wine_glx, 0, sizeof(wine_glx));
921
922   /* In case of GLX you have direct and indirect rendering. Most of the time direct rendering is used
923    * as in general only that is hardware accelerated. In some cases like in case of remote X indirect
924    * rendering is used.
925    *
926    * The main problem for our OpenGL code is that we need certain GLX calls but their presence
927    * depends on the reported GLX client / server version and on the client / server extension list.
928    * Those don't have to be the same.
929    *
930    * In general the server GLX information should be used in case of indirect rendering. When direct
931    * rendering is used, the OpenGL client library is responsible for which GLX calls are available.
932    * Nvidia's OpenGL drivers are the best in terms of GLX features. At the moment of writing their
933    * 8762 drivers support 1.3 for the server and 1.4 for the client and they support lots of extensions.
934    * Unfortunately it is much more complicated for Mesa/DRI-based drivers and ATI's drivers.
935    * Both sets of drivers report a server version of 1.2 and the client version can be 1.3 or 1.4.
936    * Further in case of at least ATI's drivers one crucial extension needed for our pixel format code
937    * is only available in the list of server extensions and not in the client list.
938    *
939    * The version checks below try to take into account the comments from above.
940    */
941
942   TRACE("Server GLX version: %s\n", server_glx_version);
943   TRACE("Client GLX version: %s\n", client_glx_version);
944   TRACE("Direct rendering eanbled: %s\n", glx_direct ? "True" : "False");
945
946   /* Based on the default opengl context we decide whether direct or indirect rendering is used.
947    * In case of indirect rendering we check if the GLX version of the server is 1.2 and else
948    * the client version is checked.
949    */
950   if ( (!glx_direct && !strcmp("1.2", server_glx_version)) || (glx_direct && !strcmp("1.2", client_glx_version)) ) {
951     wine_glx.version = 2;
952   } else {
953     wine_glx.version = 3;
954   }
955
956   /* Depending on the use of direct or indirect rendering we need either the list of extensions
957    * exported by the client or by the server.
958    */
959   if(glx_direct)
960     glx_extensions = glXGetClientString(display, GLX_EXTENSIONS);
961   else
962     glx_extensions = glXQueryServerString(display, screen, GLX_EXTENSIONS);
963
964   if (2 < wine_glx.version) {
965     wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfig");
966     wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttrib");
967     wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfig");
968
969     /*wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");*/
970   } else {
971     if (NULL != strstr(glx_extensions, "GLX_SGIX_fbconfig")) {
972       wine_glx.p_glXChooseFBConfig = proc( (const GLubyte *) "glXChooseFBConfigSGIX");
973       wine_glx.p_glXGetFBConfigAttrib = proc( (const GLubyte *) "glXGetFBConfigAttribSGIX");
974       wine_glx.p_glXGetVisualFromFBConfig = proc( (const GLubyte *) "glXGetVisualFromFBConfigSGIX");
975     } else {
976       ERR(" glx_version as %s and GLX_SGIX_fbconfig extension is unsupported. Expect problems.\n", client_glx_version);
977     }
978   }
979
980   /* The mesa libGL client library seems to forward glXQueryDrawable to the Xserver, so only
981    * enable this function when the Xserver understand GLX 1.3 or newer
982    */  
983   if (!strcmp("1.2", server_glx_version))
984     wine_glx.p_glXQueryDrawable = NULL;
985   else
986     wine_glx.p_glXQueryDrawable = proc( (const GLubyte *) "glXQueryDrawable");
987   
988   /** try anyway to retrieve that calls, maybe they works using glx client tricks */
989   wine_glx.p_glXGetFBConfigs = proc( (const GLubyte *) "glXGetFBConfigs");
990   wine_glx.p_glXMakeContextCurrent = proc( (const GLubyte *) "glXMakeContextCurrent");
991 }
992
993 /* This is for brain-dead applications that use OpenGL functions before even
994    creating a rendering context.... */
995 static BOOL process_attach(void)
996 {
997   XWindowAttributes win_attr;
998   Visual *rootVisual;
999   int num;
1000   XVisualInfo template;
1001   HDC hdc;
1002   XVisualInfo *vis = NULL;
1003   Window root = (Window)GetPropA( GetDesktopWindow(), "__wine_x11_whole_window" );
1004   HMODULE mod = GetModuleHandleA( "winex11.drv" );
1005   void *opengl_handle;
1006   DWORD size = sizeof(internal_gl_disabled_extensions);
1007   HKEY hkey = 0;
1008
1009   if (!root || !mod)
1010   {
1011       ERR("X11DRV not loaded. Cannot create default context.\n");
1012       return FALSE;
1013   }
1014
1015   wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
1016   wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
1017
1018   /* Load WGL function pointers from winex11.drv */
1019   wine_wgl.p_wglCreateContext = (void *)GetProcAddress(mod, "wglCreateContext");
1020   wine_wgl.p_wglDeleteContext = (void *)GetProcAddress(mod, "wglDeleteContext");
1021   wine_wgl.p_wglGetCurrentContext = (void *)GetProcAddress(mod, "wglGetCurrentContext");
1022   wine_wgl.p_wglGetCurrentDC = (void *)GetProcAddress(mod, "wglGetCurrentDC");
1023   wine_wgl.p_wglGetCurrentReadDCARB = (void *)GetProcAddress(mod, "wglGetCurrentReadDCARB");
1024   wine_wgl.p_wglGetProcAddress = (void *)GetProcAddress(mod, "wglGetProcAddress");
1025   wine_wgl.p_wglMakeCurrent = (void *)GetProcAddress(mod, "wglMakeCurrent");
1026   wine_wgl.p_wglMakeContextCurrentARB = (void *)GetProcAddress(mod, "wglMakeContextCurrentARB");
1027   wine_wgl.p_wglShareLists = (void *)GetProcAddress(mod, "wglShareLists");
1028   /* Interal WGL function */
1029   wine_wgl.p_wglGetIntegerv = (void *)GetProcAddress(mod, "wglGetIntegerv");
1030
1031   hdc = GetDC(0);
1032   default_display = get_display( hdc );
1033   ReleaseDC( 0, hdc );
1034   if (!default_display)
1035   {
1036       ERR("X11DRV not loaded. Cannot get display for screen DC.\n");
1037       return FALSE;
1038   }
1039
1040   ENTER_GL();
1041
1042   /* Try to get the visual from the Root Window.  We can't use the standard (presumably
1043      double buffered) X11DRV visual with the Root Window, since we don't know if the Root
1044      Window was created using the standard X11DRV visual, and glXMakeCurrent can't deal
1045      with mismatched visuals.  Note that the Root Window visual may not be double
1046      buffered, so apps actually attempting to render this way may flicker */
1047   if (XGetWindowAttributes( default_display, root, &win_attr ))
1048   {
1049     rootVisual = win_attr.visual;
1050   }
1051   else
1052   {
1053     /* Get the default visual, since we can't seem to get the attributes from the
1054        Root Window.  Let's hope that the Root Window Visual matches the DefaultVisual */
1055     rootVisual = DefaultVisual( default_display, DefaultScreen(default_display) );
1056   }
1057
1058   template.visualid = XVisualIDFromVisual(rootVisual);
1059   vis = XGetVisualInfo(default_display, VisualIDMask, &template, &num);
1060   if (vis != NULL) default_cx = glXCreateContext(default_display, vis, 0, GL_TRUE);
1061   if (default_cx != NULL) glXMakeCurrent(default_display, root, default_cx);
1062   XFree(vis);
1063   LEAVE_GL();
1064
1065   opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
1066   if (opengl_handle != NULL) {
1067    p_glXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0);
1068    wine_dlclose(opengl_handle, NULL, 0);
1069    if (p_glXGetProcAddressARB == NULL)
1070            TRACE("could not find glXGetProcAddressARB in libGL.\n");
1071   }
1072
1073   internal_gl_disabled_extensions[0] = 0;
1074   if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\OpenGL", &hkey)) {
1075     if (!RegQueryValueExA( hkey, "DisabledExtensions", 0, NULL, (LPBYTE)internal_gl_disabled_extensions, &size)) {
1076       TRACE("found DisabledExtensions=\"%s\"\n", internal_gl_disabled_extensions);
1077     }
1078     RegCloseKey(hkey);
1079   }
1080
1081   if (default_cx == NULL) {
1082     ERR("Could not create default context.\n");
1083   }
1084   else
1085   {
1086     /* After context initialize also the list of supported WGL extensions. */
1087     wgl_initialize_glx(default_display, DefaultScreen(default_display), p_glXGetProcAddressARB);
1088   }
1089   return TRUE;
1090 }
1091
1092
1093 /**********************************************************************/
1094
1095 static void process_detach(void)
1096 {
1097   glXDestroyContext(default_display, default_cx);
1098
1099   HeapFree(GetProcessHeap(), 0, internal_gl_extensions);
1100 }
1101
1102 /***********************************************************************
1103  *           OpenGL initialisation routine
1104  */
1105 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
1106 {
1107     switch(reason)
1108     {
1109     case DLL_PROCESS_ATTACH:
1110         opengl32_handle = hinst;
1111         DisableThreadLibraryCalls(hinst);
1112         return process_attach();
1113     case DLL_PROCESS_DETACH:
1114         process_detach();
1115         break;
1116     }
1117     return TRUE;
1118 }