Add missing wReserved1 member to DCB structure definition.
[wine] / graphics / x11drv / opengl.c
1 /*
2  * X11DRV OpenGL functions
3  *
4  * Copyright 2000 Lionel Ulmer
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include "ts_xlib.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "gdi.h"
30 #include "x11drv.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(opengl);
34
35 #if defined(HAVE_GL_GL_H) && defined(HAVE_GL_GLX_H)
36
37 #undef APIENTRY
38 #undef CALLBACK
39 #undef WINAPI
40
41 #define XMD_H /* This is to prevent the Xmd.h inclusion bug :-/ */
42 #ifdef HAVE_GL_GL_H
43 # include <GL/gl.h>
44 #endif
45 #ifdef HAVE_GL_GLX_H
46 # include <GL/glx.h>
47 #endif
48 #ifdef HAVE_GL_GLEXT_H
49 # include <GL/glext.h>
50 #endif
51 #undef  XMD_H
52
53 #undef APIENTRY
54 #undef CALLBACK
55 #undef WINAPI
56
57 /* Redefines the constants */
58 #define CALLBACK    __stdcall
59 #define WINAPI      __stdcall
60 #define APIENTRY    WINAPI
61
62
63 static void dump_PIXELFORMATDESCRIPTOR(PIXELFORMATDESCRIPTOR *ppfd) {
64   DPRINTF("  - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
65   DPRINTF("  - dwFlags : ");
66 #define TEST_AND_DUMP(t,tv) if ((t) & (tv)) DPRINTF(#tv " ")
67   TEST_AND_DUMP(ppfd->dwFlags, PFD_DEPTH_DONTCARE);
68   TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER);
69   TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER_DONTCARE);
70   TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_WINDOW);
71   TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_BITMAP);
72   TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_ACCELERATED);
73   TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_FORMAT);
74   TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_PALETTE);
75   TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_SYSTEM_PALETTE);
76   TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO);
77   TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO_DONTCARE);
78   TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_GDI);
79   TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_OPENGL);
80   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_COPY);
81   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_EXCHANGE);
82   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_LAYER_BUFFERS);
83 #undef TEST_AND_DUMP
84   DPRINTF("\n");
85
86   DPRINTF("  - iPixelType : ");
87   switch (ppfd->iPixelType) {
88   case PFD_TYPE_RGBA: DPRINTF("PFD_TYPE_RGBA"); break;
89   case PFD_TYPE_COLORINDEX: DPRINTF("PFD_TYPE_COLORINDEX"); break;
90   }
91   DPRINTF("\n");
92
93   DPRINTF("  - Color   : %d\n", ppfd->cColorBits);
94   DPRINTF("  - Alpha   : %d\n", ppfd->cAlphaBits);
95   DPRINTF("  - Accum   : %d\n", ppfd->cAccumBits);
96   DPRINTF("  - Depth   : %d\n", ppfd->cDepthBits);
97   DPRINTF("  - Stencil : %d\n", ppfd->cStencilBits);
98   DPRINTF("  - Aux     : %d\n", ppfd->cAuxBuffers);
99
100   DPRINTF("  - iLayerType : ");
101   switch (ppfd->iLayerType) {
102   case PFD_MAIN_PLANE: DPRINTF("PFD_MAIN_PLANE"); break;
103   case PFD_OVERLAY_PLANE: DPRINTF("PFD_OVERLAY_PLANE"); break;
104   case PFD_UNDERLAY_PLANE: DPRINTF("PFD_UNDERLAY_PLANE"); break;
105   }
106   DPRINTF("\n");
107 }
108
109 /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and
110    include all dependencies
111 */
112 #ifndef SONAME_LIBGL
113 #define SONAME_LIBGL "libGL.so"
114 #endif
115
116 static void *opengl_handle;
117
118 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
119 MAKE_FUNCPTR(glXChooseVisual)
120 MAKE_FUNCPTR(glXGetConfig)
121 MAKE_FUNCPTR(glXSwapBuffers)
122 MAKE_FUNCPTR(glXQueryExtension)
123 #undef MAKE_FUNCPTR
124
125 void X11DRV_OpenGL_Init(Display *display) {
126     int error_base, event_base;
127
128     opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0);
129     if (opengl_handle == NULL) return;
130
131 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(opengl_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
132 LOAD_FUNCPTR(glXChooseVisual)
133 LOAD_FUNCPTR(glXGetConfig)
134 LOAD_FUNCPTR(glXSwapBuffers)
135 LOAD_FUNCPTR(glXQueryExtension)
136 #undef LOAD_FUNCPTR
137
138     wine_tsx11_lock();
139     if (pglXQueryExtension(display, &event_base, &error_base) == True) {
140         TRACE("GLX is up and running error_base = %d\n", error_base);
141     } else {
142         wine_dlclose(opengl_handle, NULL, 0);
143         opengl_handle = NULL;
144     }
145     wine_tsx11_unlock();
146     return;
147
148 sym_not_found:
149     wine_dlclose(opengl_handle, NULL, 0);
150     opengl_handle = NULL;
151 }
152
153 /* X11DRV_ChoosePixelFormat
154
155      Equivalent of glXChooseVisual
156 */
157 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
158                              const PIXELFORMATDESCRIPTOR *ppfd) {
159 #define TEST_AND_ADD1(t,a) if (t) att_list[att_pos++] = a
160 #define TEST_AND_ADD2(t,a,b) if (t) { att_list[att_pos++] = a; att_list[att_pos++] = b; }
161 #define NULL_TEST_AND_ADD2(tv,a,b) att_list[att_pos++] = a; att_list[att_pos++] = ((tv) == 0 ? 0 : b)
162 #define ADD2(a,b) att_list[att_pos++] = a; att_list[att_pos++] = b
163
164   int att_list[64];
165   int att_pos = 0;
166   XVisualInfo *vis;
167   int i;
168
169   if (opengl_handle == NULL) {
170     ERR("No libGL on this box - disabling OpenGL support !\n");
171     return 0;
172   }
173   
174   if (TRACE_ON(opengl)) {
175     TRACE("(%p,%p)\n", physDev, ppfd);
176
177     dump_PIXELFORMATDESCRIPTOR((PIXELFORMATDESCRIPTOR *) ppfd);
178   }
179
180   if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) {
181     ERR("Flag not supported !\n");
182     /* Should SetError here... */
183     return 0;
184   }
185
186   /* Now, build the request to GLX */
187   TEST_AND_ADD1(ppfd->dwFlags & PFD_DOUBLEBUFFER, GLX_DOUBLEBUFFER);
188   TEST_AND_ADD1(ppfd->dwFlags & PFD_STEREO, GLX_STEREO);
189   TEST_AND_ADD1(ppfd->iPixelType == PFD_TYPE_RGBA, GLX_RGBA);
190   TEST_AND_ADD2(ppfd->iPixelType == PFD_TYPE_COLORINDEX, GLX_BUFFER_SIZE, ppfd->cColorBits);
191
192   NULL_TEST_AND_ADD2(ppfd->cDepthBits, GLX_DEPTH_SIZE, 8);
193   /* These flags are not supported yet...
194
195      NULL_TEST_AND_ADD2(ppfd->cAlphaBits, GLX_ALPHA_SIZE, 8);
196      ADD2(GLX_ACCUM_SIZE, ppfd->cAccumBits); */
197   ADD2(GLX_STENCIL_SIZE, ppfd->cStencilBits); /* now supported */
198   /*   ADD2(GLX_AUX_BUFFERS, ppfd->cAuxBuffers); */
199   att_list[att_pos] = None;
200
201   wine_tsx11_lock(); {
202     /*
203        This command cannot be used as we need to use the default visual...
204        Let's hope it at least contains some OpenGL functionnalities
205
206        vis = glXChooseVisual(gdi_display, DefaultScreen(gdi_display), att_list);
207     */
208     int num;
209     XVisualInfo template;
210
211     template.visualid = XVisualIDFromVisual(visual);
212     vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num);
213
214     TRACE("Found visual : %p - returns %d\n", vis, physDev->used_visuals + 1);
215   }
216   wine_tsx11_unlock();
217
218   if (vis == NULL) {
219     ERR("No visual found !\n");
220     /* Should SetError here... */
221     return 0;
222   }
223   /* try to find the visualid in the already created visuals */
224   for( i=0; i<physDev->used_visuals; i++ ) {
225     if ( vis->visualid == physDev->visuals[i]->visualid ) {
226       XFree(vis);
227       return i+1;
228     }
229   }
230   /* now give up, if the maximum is reached */
231   if (physDev->used_visuals == MAX_PIXELFORMATS) {
232     ERR("Maximum number of visuals reached !\n");
233     /* Should SetError here... */
234     return 0;
235   }
236   physDev->visuals[physDev->used_visuals++] = vis;
237
238   return physDev->used_visuals;
239 }
240
241 /* X11DRV_DescribePixelFormat
242
243      Get the pixel-format descriptor associated to the given id
244 */
245 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
246                                int iPixelFormat,
247                                UINT nBytes,
248                                PIXELFORMATDESCRIPTOR *ppfd) {
249   XVisualInfo *vis;
250   int value;
251   int rb,gb,bb,ab;
252
253   if (opengl_handle == NULL) {
254     ERR("No libGL on this box - disabling OpenGL support !\n");
255     return 0;
256   }
257   
258   TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd);
259
260   if (ppfd == NULL) {
261     /* The application is only querying the number of visuals */
262     return MAX_PIXELFORMATS;
263   }
264
265   if (nBytes < sizeof(PIXELFORMATDESCRIPTOR)) {
266     ERR("Wrong structure size !\n");
267     /* Should set error */
268     return 0;
269   }
270   if ((iPixelFormat > MAX_PIXELFORMATS) ||
271       (iPixelFormat > physDev->used_visuals + 1) ||
272       (iPixelFormat <= 0)) {
273     ERR("Wrong pixel format !\n");
274     /* Should set error */
275     return 0;
276   }
277
278   if (iPixelFormat == physDev->used_visuals + 1) {
279     int dblBuf[]={GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
280
281     /* Create a 'standard' X Visual */
282     wine_tsx11_lock();
283     vis = pglXChooseVisual(gdi_display, DefaultScreen(gdi_display), dblBuf);
284     wine_tsx11_unlock();
285
286     WARN("Uninitialized Visual. Creating standard (%p) !\n", vis);
287
288     if (vis == NULL) {
289       ERR("Could not create standard visual !\n");
290       /* Should set error */
291       return 0;
292     }
293
294     physDev->visuals[physDev->used_visuals++] = vis;
295   }
296   vis = physDev->visuals[iPixelFormat - 1];
297
298   memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
299   ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
300   ppfd->nVersion = 1;
301
302   /* These flags are always the same... */
303   ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED;
304   /* Now the flags extraced from the Visual */
305   wine_tsx11_lock();
306   pglXGetConfig(gdi_display, vis, GLX_DOUBLEBUFFER, &value); if (value) ppfd->dwFlags |= PFD_DOUBLEBUFFER;
307   pglXGetConfig(gdi_display, vis, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
308
309   /* Pixel type */
310   pglXGetConfig(gdi_display, vis, GLX_RGBA, &value);
311   if (value)
312     ppfd->iPixelType = PFD_TYPE_RGBA;
313   else
314     ppfd->iPixelType = PFD_TYPE_COLORINDEX;
315
316   /* Color bits */
317   pglXGetConfig(gdi_display, vis, GLX_BUFFER_SIZE, &value);
318   ppfd->cColorBits = value;
319
320   /* Red, green, blue and alpha bits / shifts */
321   if (ppfd->iPixelType == PFD_TYPE_RGBA) {
322     pglXGetConfig(gdi_display, vis, GLX_RED_SIZE, &rb);
323     pglXGetConfig(gdi_display, vis, GLX_GREEN_SIZE, &gb);
324     pglXGetConfig(gdi_display, vis, GLX_BLUE_SIZE, &bb);
325     pglXGetConfig(gdi_display, vis, GLX_ALPHA_SIZE, &ab);
326
327     ppfd->cRedBits = rb;
328     ppfd->cRedShift = gb + bb + ab;
329     ppfd->cBlueBits = bb;
330     ppfd->cBlueShift = ab;
331     ppfd->cGreenBits = gb;
332     ppfd->cGreenShift = bb + ab;
333     ppfd->cAlphaBits = ab;
334     ppfd->cAlphaShift = 0;
335   } else {
336     ppfd->cRedBits = 0;
337     ppfd->cRedShift = 0;
338     ppfd->cBlueBits = 0;
339     ppfd->cBlueShift = 0;
340     ppfd->cGreenBits = 0;
341     ppfd->cGreenShift = 0;
342     ppfd->cAlphaBits = 0;
343     ppfd->cAlphaShift = 0;
344   }
345   /* Accums : to do ... */
346
347   /* Depth bits */
348   pglXGetConfig(gdi_display, vis, GLX_DEPTH_SIZE, &value);
349   ppfd->cDepthBits = value;
350
351   /* stencil bits */
352   pglXGetConfig( gdi_display, vis, GLX_STENCIL_SIZE, &value );
353   ppfd->cStencilBits = value;
354
355   wine_tsx11_unlock();
356
357   /* Aux : to do ... */
358
359   ppfd->iLayerType = PFD_MAIN_PLANE;
360
361   if (TRACE_ON(opengl)) {
362     dump_PIXELFORMATDESCRIPTOR(ppfd);
363   }
364
365   return MAX_PIXELFORMATS;
366 }
367
368 /* X11DRV_GetPixelFormat
369
370      Get the pixel-format id used by this DC
371 */
372 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
373   TRACE("(%p): returns %d\n", physDev, physDev->current_pf);
374
375   return physDev->current_pf;
376 }
377
378 /* X11DRV_SetPixelFormat
379
380      Set the pixel-format id used by this DC
381 */
382 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
383                            int iPixelFormat,
384                            const PIXELFORMATDESCRIPTOR *ppfd) {
385   TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd);
386
387   physDev->current_pf = iPixelFormat;
388
389   return TRUE;
390 }
391
392 /* X11DRV_SwapBuffers
393
394      Swap the buffers of this DC
395 */
396 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) {
397   if (opengl_handle == NULL) {
398     ERR("No libGL on this box - disabling OpenGL support !\n");
399     return 0;
400   }
401   
402   TRACE("(%p)\n", physDev);
403
404   wine_tsx11_lock();
405   pglXSwapBuffers(gdi_display, physDev->drawable);
406   wine_tsx11_unlock();
407
408   return TRUE;
409 }
410
411 /***********************************************************************
412  *              X11DRV_setup_opengl_visual
413  *
414  * Setup the default visual used for OpenGL and Direct3D, and the desktop
415  * window (if it exists).  If OpenGL isn't available, the visual is simply
416  * set to the default visual for the display
417  */
418 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
419 {
420     XVisualInfo *visual = NULL;
421     int dblBuf[]={GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
422
423     if (opengl_handle == NULL) return NULL;
424     
425     /* In order to support OpenGL or D3D, we require a double-buffered visual */
426     wine_tsx11_lock();
427     visual = pglXChooseVisual(display, DefaultScreen(display), dblBuf);
428     wine_tsx11_unlock();
429     return visual;
430 }
431
432 #else  /* no OpenGL includes */
433
434 void X11DRV_OpenGL_Init(Display *display)
435 {
436 }
437
438 /***********************************************************************
439  *              ChoosePixelFormat (X11DRV.@)
440  */
441 int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
442                              const PIXELFORMATDESCRIPTOR *ppfd) {
443   ERR("No OpenGL support compiled in.\n");
444
445   return 0;
446 }
447
448 /***********************************************************************
449  *              DescribePixelFormat (X11DRV.@)
450  */
451 int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev,
452                                int iPixelFormat,
453                                UINT nBytes,
454                                PIXELFORMATDESCRIPTOR *ppfd) {
455   ERR("No OpenGL support compiled in.\n");
456
457   return 0;
458 }
459
460 /***********************************************************************
461  *              GetPixelFormat (X11DRV.@)
462  */
463 int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) {
464   ERR("No OpenGL support compiled in.\n");
465
466   return 0;
467 }
468
469 /***********************************************************************
470  *              SetPixelFormat (X11DRV.@)
471  */
472 BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev,
473                            int iPixelFormat,
474                            const PIXELFORMATDESCRIPTOR *ppfd) {
475   ERR("No OpenGL support compiled in.\n");
476
477   return FALSE;
478 }
479
480 /***********************************************************************
481  *              SwapBuffers (X11DRV.@)
482  */
483 BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) {
484   ERR("No OpenGL support compiled in.\n");
485
486   return FALSE;
487 }
488
489 XVisualInfo *X11DRV_setup_opengl_visual( Display *display )
490 {
491   return NULL;
492 }
493
494 #endif /* defined(HAVE_OPENGL) */