Partial implementation of world transform support.
[wine] / graphics / x11drv / opengl.c
1 /* 
2  * X11DRV OpenGL functions
3  *
4  * Copyright 2000 Lionel Ulmer
5  *
6  */
7
8 #include "config.h"
9
10 #include "ts_xlib.h"
11
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "debugtools.h"
16 #include "gdi.h"
17 #include "x11drv.h"
18 #include "wine_gl.h"
19
20 DEFAULT_DEBUG_CHANNEL(opengl);
21
22 #ifdef HAVE_OPENGL
23
24 static void dump_PIXELFORMATDESCRIPTOR(PIXELFORMATDESCRIPTOR *ppfd) {
25   DPRINTF("  - size / version : %d / %d\n", ppfd->nSize, ppfd->nVersion);
26   DPRINTF("  - dwFlags : ");
27 #define TEST_AND_DUMP(t,tv) if ((t) & (tv)) DPRINTF(#tv " ")
28   TEST_AND_DUMP(ppfd->dwFlags, PFD_DEPTH_DONTCARE);
29   TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER);
30   TEST_AND_DUMP(ppfd->dwFlags, PFD_DOUBLEBUFFER_DONTCARE);
31   TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_WINDOW);
32   TEST_AND_DUMP(ppfd->dwFlags, PFD_DRAW_TO_BITMAP);
33   TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_ACCELERATED);
34   TEST_AND_DUMP(ppfd->dwFlags, PFD_GENERIC_FORMAT);
35   TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_PALETTE);
36   TEST_AND_DUMP(ppfd->dwFlags, PFD_NEED_SYSTEM_PALETTE);
37   TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO);
38   TEST_AND_DUMP(ppfd->dwFlags, PFD_STEREO_DONTCARE);
39   TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_GDI);
40   TEST_AND_DUMP(ppfd->dwFlags, PFD_SUPPORT_OPENGL);
41   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_COPY);
42   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_EXCHANGE);
43   TEST_AND_DUMP(ppfd->dwFlags, PFD_SWAP_LAYER_BUFFERS);
44 #undef TEST_AND_DUMP
45   DPRINTF("\n");
46   
47   DPRINTF("  - iPixelType : ");
48   switch (ppfd->iPixelType) {
49   case PFD_TYPE_RGBA: DPRINTF("PFD_TYPE_RGBA"); break;
50   case PFD_TYPE_COLORINDEX: DPRINTF("PFD_TYPE_COLORINDEX"); break;
51   }
52   DPRINTF("\n");
53   
54   DPRINTF("  - Color   : %d\n", ppfd->cColorBits);
55   DPRINTF("  - Alpha   : %d\n", ppfd->cAlphaBits);
56   DPRINTF("  - Accum   : %d\n", ppfd->cAccumBits);
57   DPRINTF("  - Depth   : %d\n", ppfd->cDepthBits);
58   DPRINTF("  - Stencil : %d\n", ppfd->cStencilBits);
59   DPRINTF("  - Aux     : %d\n", ppfd->cAuxBuffers);
60   
61   DPRINTF("  - iLayerType : ");
62   switch (ppfd->iLayerType) {
63   case PFD_MAIN_PLANE: DPRINTF("PFD_MAIN_PLANE"); break;
64   case PFD_OVERLAY_PLANE: DPRINTF("PFD_OVERLAY_PLANE"); break;
65   case PFD_UNDERLAY_PLANE: DPRINTF("PFD_UNDERLAY_PLANE"); break;
66   }
67   DPRINTF("\n");
68 }
69      
70 /* X11DRV_ChoosePixelFormat
71
72      Equivalent of glXChooseVisual
73 */
74 int X11DRV_ChoosePixelFormat(DC *dc,
75                              const PIXELFORMATDESCRIPTOR *ppfd) {
76 #define TEST_AND_ADD1(t,a) if (t) att_list[att_pos++] = a
77 #define TEST_AND_ADD2(t,a,b) if (t) { att_list[att_pos++] = a; att_list[att_pos++] = b; }
78 #define NULL_TEST_AND_ADD2(tv,a,b) att_list[att_pos++] = a; att_list[att_pos++] = ((tv) == 0 ? 0 : b)
79 #define ADD2(a,b) att_list[att_pos++] = a; att_list[att_pos++] = b
80   
81   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
82   int att_list[64];
83   int att_pos = 0;
84   XVisualInfo *vis;
85   
86   if (TRACE_ON(opengl)) {
87     TRACE("(%p,%p)\n", dc, ppfd);
88     
89     dump_PIXELFORMATDESCRIPTOR((PIXELFORMATDESCRIPTOR *) ppfd);
90   }
91
92   /* For the moment, we are dumb : we always allocate a new XVisualInfo structure,
93      we do not try to find an already found that could match */
94   if (physDev->used_visuals == MAX_PIXELFORMATS) {
95     ERR("Maximum number of visuals reached !\n");
96     /* Should SetError here... */
97     return 0;
98   }
99
100   if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) {
101     ERR("Flag not supported !\n");
102     /* Should SetError here... */
103     return 0;
104   }
105
106   /* Now, build the request to GLX */
107   TEST_AND_ADD1(ppfd->dwFlags & PFD_DOUBLEBUFFER, GLX_DOUBLEBUFFER);
108   TEST_AND_ADD1(ppfd->dwFlags & PFD_STEREO, GLX_STEREO);
109   TEST_AND_ADD1(ppfd->iPixelType == PFD_TYPE_RGBA, GLX_RGBA);
110   TEST_AND_ADD2(ppfd->iPixelType == PFD_TYPE_COLORINDEX, GLX_BUFFER_SIZE, ppfd->cColorBits);
111
112   NULL_TEST_AND_ADD2(ppfd->cDepthBits, GLX_DEPTH_SIZE, 8);
113   /* These flags are not supported yet...
114      
115      NULL_TEST_AND_ADD2(ppfd->cAlphaBits, GLX_ALPHA_SIZE, 8);
116      ADD2(GLX_ACCUM_SIZE, ppfd->cAccumBits); 
117      ADD2(GLX_STENCIL_SIZE, ppfd->cStencilBits);
118      ADD2(GLX_AUX_BUFFERS, ppfd->cAuxBuffers); */
119   att_list[att_pos] = None;
120   
121   ENTER_GL(); {
122     /*
123        This command cannot be used as we need to use the default visual...
124        Let's hope it at least contains some OpenGL functionnalities
125        
126        vis = glXChooseVisual(display, DefaultScreen(display), att_list);
127     */
128     int num;
129     XVisualInfo template;
130
131     template.visualid = XVisualIDFromVisual(visual);
132     vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
133
134     TRACE("Found visual : %p - returns %d\n", vis, physDev->used_visuals + 1);
135   }
136   LEAVE_GL();
137   
138   if (vis == NULL) {
139     ERR("No visual found !\n");
140     /* Should SetError here... */
141     return 0;
142   }
143   physDev->visuals[physDev->used_visuals++] = vis;
144   
145   return physDev->used_visuals;
146 }
147
148 /* X11DRV_DescribePixelFormat
149
150      Get the pixel-format descriptor associated to the given id
151 */
152 int X11DRV_DescribePixelFormat(DC *dc,
153                                int iPixelFormat,
154                                UINT nBytes,
155                                PIXELFORMATDESCRIPTOR *ppfd) {
156   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
157   XVisualInfo *vis;
158   int value;
159   int rb,gb,bb,ab;
160   
161   TRACE("(%p,%d,%d,%p)\n", dc, iPixelFormat, nBytes, ppfd);
162   
163   if (nBytes < sizeof(PIXELFORMATDESCRIPTOR)) {
164     ERR("Wrong structure size !\n");
165     /* Should set error */
166     return 0;
167   }
168   if ((iPixelFormat > MAX_PIXELFORMATS) ||
169       (iPixelFormat > physDev->used_visuals + 1) ||
170       (iPixelFormat <= 0)) {
171     ERR("Wrong pixel format !\n");
172     /* Should set error */
173     return 0;
174   }
175       
176   if (iPixelFormat == physDev->used_visuals + 1) {
177     int dblBuf[]={GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};
178
179     /* Create a 'standard' X Visual */
180     ENTER_GL();
181     vis = glXChooseVisual(display,
182                           DefaultScreen(display),
183                           dblBuf);
184     LEAVE_GL();
185     
186     WARN("Uninitialized Visual. Creating standard (%p) !\n", vis);
187
188     if (vis == NULL) {
189       ERR("Could not create standard visual !\n");
190       /* Should set error */
191       return 0;
192     }
193     
194     physDev->visuals[physDev->used_visuals++] = vis;
195   }
196   vis = physDev->visuals[iPixelFormat - 1];
197
198   memset(ppfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
199   ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
200   ppfd->nVersion = 1;
201   
202   /* These flags are always the same... */
203   ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED;
204   /* Now the flags extraced from the Visual */
205   ENTER_GL();
206   glXGetConfig(display, vis, GLX_DOUBLEBUFFER, &value); if (value) ppfd->dwFlags |= PFD_DOUBLEBUFFER;
207   glXGetConfig(display, vis, GLX_STEREO, &value); if (value) ppfd->dwFlags |= PFD_STEREO;
208
209   /* Pixel type */
210   glXGetConfig(display, vis, GLX_RGBA, &value);
211   if (value)
212     ppfd->iPixelType = PFD_TYPE_RGBA;
213   else
214     ppfd->iPixelType = PFD_TYPE_COLORINDEX;
215
216   /* Color bits */
217   glXGetConfig(display, vis, GLX_BUFFER_SIZE, &value);
218   ppfd->cColorBits = value;
219
220   /* Red, green, blue and alpha bits / shifts */
221   if (ppfd->iPixelType == PFD_TYPE_RGBA) {
222     glXGetConfig(display, vis, GLX_RED_SIZE, &rb);
223     glXGetConfig(display, vis, GLX_GREEN_SIZE, &gb);
224     glXGetConfig(display, vis, GLX_BLUE_SIZE, &bb);
225     glXGetConfig(display, vis, GLX_ALPHA_SIZE, &ab);
226     
227     ppfd->cRedBits = rb;
228     ppfd->cRedShift = gb + bb + ab;
229     ppfd->cBlueBits = bb;
230     ppfd->cBlueShift = ab;
231     ppfd->cGreenBits = gb;
232     ppfd->cGreenShift = bb + ab;
233     ppfd->cAlphaBits = ab;
234     ppfd->cAlphaShift = 0;
235   } else {
236     ppfd->cRedBits = 0;
237     ppfd->cRedShift = 0;
238     ppfd->cBlueBits = 0;
239     ppfd->cBlueShift = 0;
240     ppfd->cGreenBits = 0;
241     ppfd->cGreenShift = 0;
242     ppfd->cAlphaBits = 0;
243     ppfd->cAlphaShift = 0;
244   }
245   /* Accums : to do ... */
246   
247   /* Depth bits */
248   glXGetConfig(display, vis, GLX_DEPTH_SIZE, &value);
249   ppfd->cDepthBits = value;
250   LEAVE_GL();
251
252   /* Aux, stencil : to do ... */
253
254   ppfd->iLayerType = PFD_MAIN_PLANE;
255   
256   if (TRACE_ON(opengl)) {
257     dump_PIXELFORMATDESCRIPTOR(ppfd);
258   }
259   
260   return MAX_PIXELFORMATS;
261 }
262
263 /* X11DRV_GetPixelFormat
264
265      Get the pixel-format id used by this DC
266 */
267 int X11DRV_GetPixelFormat(DC *dc) {
268   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
269   
270   TRACE("(%p): returns %d\n", dc, physDev->current_pf);
271
272   return physDev->current_pf;
273 }
274
275 /* X11DRV_SetPixelFormat
276
277      Set the pixel-format id used by this DC
278 */
279 BOOL X11DRV_SetPixelFormat(DC *dc,
280                            int iPixelFormat,
281                            const PIXELFORMATDESCRIPTOR *ppfd) {
282   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
283   
284   TRACE("(%p,%d,%p)\n", dc, iPixelFormat, ppfd);
285
286   physDev->current_pf = iPixelFormat;
287   
288   return TRUE;
289 }
290
291 /* X11DRV_SwapBuffers
292
293      Swap the buffers of this DC
294 */
295 BOOL X11DRV_SwapBuffers(DC *dc) {
296   X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
297   
298   TRACE("(%p)\n", dc);
299
300   ENTER_GL();
301   glXSwapBuffers(display, physDev->drawable);
302   LEAVE_GL();
303   
304   return TRUE;
305 }
306
307 #else  /* defined(HAVE_OPENGL) */
308
309 int X11DRV_ChoosePixelFormat(DC *dc,
310                              const PIXELFORMATDESCRIPTOR *ppfd) {
311   ERR("No OpenGL support compiled in.\n");
312
313   return 0;
314 }
315
316 int X11DRV_DescribePixelFormat(DC *dc,
317                                int iPixelFormat,
318                                UINT nBytes,
319                                PIXELFORMATDESCRIPTOR *ppfd) {
320   ERR("No OpenGL support compiled in.\n");
321   
322   return 0;
323 }
324
325 int X11DRV_GetPixelFormat(DC *dc) {
326   ERR("No OpenGL support compiled in.\n");
327   
328   return 0;
329 }
330
331 BOOL X11DRV_SetPixelFormat(DC *dc,
332                            int iPixelFormat,
333                            const PIXELFORMATDESCRIPTOR *ppfd) {
334   ERR("No OpenGL support compiled in.\n");
335   
336   return FALSE;
337 }
338
339 BOOL X11DRV_SwapBuffers(DC *dc) {
340   ERR("No OpenGL support compiled in.\n");
341   
342   return FALSE;
343 }
344
345 #endif /* defined(HAVE_OPENGL) */