and some more renames
[freeglut] / src / x11 / fg_state_x11.c
1 /*
2  * freeglut_state_x11.c
3  *
4  * X11-specific freeglut state query methods.
5  *
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
7  * Written by John F. Fay, <fayjf@sourceforge.net>
8  * Creation date: Sat Feb 4 2012
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #include <GL/freeglut.h>
29 #include "../fg_internal.h"
30
31 /*
32  * TODO BEFORE THE STABLE RELEASE:
33  *
34  *  fgPlatformChooseFBConfig()      -- OK, but what about glutInitDisplayString()?
35  */
36
37 /* A helper function to check if a display mode is possible to use */
38 GLXFBConfig* fgPlatformChooseFBConfig( int* numcfgs );
39
40 /*
41  * Queries the GL context about some attributes
42  */
43 int fgPlatformGetConfig( int attribute )
44 {
45   int returnValue = 0;
46   int result;  /*  Not checked  */
47
48   if( fgStructure.CurrentWindow )
49       result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
50                                      *(fgStructure.CurrentWindow->Window.pContext.FBConfig),
51                                      attribute,
52                                      &returnValue );
53
54   return returnValue;
55 }
56
57 int fgPlatformGlutGet ( GLenum eWhat )
58 {
59     int nsamples = 0;
60
61     switch( eWhat )
62     {
63     /*
64      * The window/context specific queries are handled mostly by
65      * fgPlatformGetConfig().
66      */
67     case GLUT_WINDOW_NUM_SAMPLES:
68 #ifdef GLX_VERSION_1_3
69         glGetIntegerv(GL_SAMPLES, &nsamples);
70 #endif
71         return nsamples;
72
73     /*
74      * The rest of GLX queries under X are general enough to use a macro to
75      * check them
76      */
77 #   define GLX_QUERY(a,b) case a: return fgPlatformGetConfig( b );
78
79     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );
80     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );
81     GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE,         GLX_BUFFER_SIZE         );
82     GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE,        GLX_STENCIL_SIZE        );
83     GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE,          GLX_DEPTH_SIZE          );
84     GLX_QUERY( GLUT_WINDOW_RED_SIZE,            GLX_RED_SIZE            );
85     GLX_QUERY( GLUT_WINDOW_GREEN_SIZE,          GLX_GREEN_SIZE          );
86     GLX_QUERY( GLUT_WINDOW_BLUE_SIZE,           GLX_BLUE_SIZE           );
87     GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE,          GLX_ALPHA_SIZE          );
88     GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE,      GLX_ACCUM_RED_SIZE      );
89     GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE,    GLX_ACCUM_GREEN_SIZE    );
90     GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE,     GLX_ACCUM_BLUE_SIZE     );
91     GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE,    GLX_ACCUM_ALPHA_SIZE    );
92     GLX_QUERY( GLUT_WINDOW_STEREO,              GLX_STEREO              );
93
94 #   undef GLX_QUERY
95
96     /* Colormap size is handled in a bit different way than all the rest */
97     case GLUT_WINDOW_COLORMAP_SIZE:
98         if( (fgPlatformGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
99         {
100             /*
101              * We've got a RGBA visual, so there is no colormap at all.
102              * The other possibility is that we have no current window set.
103              */
104             return 0;
105         }
106         else
107         {
108           const GLXFBConfig * fbconfig =
109                 fgStructure.CurrentWindow->Window.pContext.FBConfig;
110
111           XVisualInfo * visualInfo =
112                 glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, *fbconfig );
113
114           const int result = visualInfo->visual->map_entries;
115
116           XFree(visualInfo);
117
118           return result;
119         }
120
121     /*
122      * Those calls are somewhat similiar, as they use XGetWindowAttributes()
123      * function
124      */
125     case GLUT_WINDOW_X:
126     case GLUT_WINDOW_Y:
127     case GLUT_WINDOW_BORDER_WIDTH:
128     case GLUT_WINDOW_HEADER_HEIGHT:
129     {
130         int x, y;
131         Window w;
132
133         if( fgStructure.CurrentWindow == NULL )
134             return 0;
135
136         XTranslateCoordinates(
137             fgDisplay.pDisplay.Display,
138             fgStructure.CurrentWindow->Window.Handle,
139             fgDisplay.pDisplay.RootWindow,
140             0, 0, &x, &y, &w);
141
142         switch ( eWhat )
143         {
144         case GLUT_WINDOW_X: return x;
145         case GLUT_WINDOW_Y: return y;
146         }
147
148         if ( w == 0 )
149             return 0;
150         XTranslateCoordinates(
151             fgDisplay.pDisplay.Display,
152             fgStructure.CurrentWindow->Window.Handle,
153             w, 0, 0, &x, &y, &w);
154
155         switch ( eWhat )
156         {
157         case GLUT_WINDOW_BORDER_WIDTH:  return x;
158         case GLUT_WINDOW_HEADER_HEIGHT: return y;
159         }
160     }
161
162     case GLUT_WINDOW_WIDTH:
163     case GLUT_WINDOW_HEIGHT:
164     {
165         XWindowAttributes winAttributes;
166
167         if( fgStructure.CurrentWindow == NULL )
168             return 0;
169         XGetWindowAttributes(
170             fgDisplay.pDisplay.Display,
171             fgStructure.CurrentWindow->Window.Handle,
172             &winAttributes
173         );
174         switch ( eWhat )
175         {
176         case GLUT_WINDOW_WIDTH:            return winAttributes.width ;
177         case GLUT_WINDOW_HEIGHT:           return winAttributes.height ;
178         }
179     }
180
181     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
182     case GLUT_DISPLAY_MODE_POSSIBLE:
183     {
184         /*  We should not have to call fgPlatformChooseFBConfig again here.  */
185         GLXFBConfig * fbconfig;
186         int isPossible;
187
188         fbconfig = fgPlatformChooseFBConfig(NULL);
189
190         if (fbconfig == NULL)
191         {
192             isPossible = 0;
193         }
194         else
195         {
196             isPossible = 1;
197             XFree(fbconfig);
198         }
199
200         return isPossible;
201     }
202
203     /* This is system-dependant */
204     case GLUT_WINDOW_FORMAT_ID:
205         if( fgStructure.CurrentWindow == NULL )
206             return 0;
207
208         return fgPlatformGetConfig( GLX_VISUAL_ID );
209
210     default:
211         fgWarning( "glutGet(): missing enum handle %d", eWhat );
212         break;
213     }
214
215         return -1;
216 }
217
218
219 int fgPlatformGlutDeviceGet ( GLenum eWhat )
220 {
221     switch( eWhat )
222     {
223     case GLUT_HAS_KEYBOARD:
224         /*
225          * X11 has a core keyboard by definition, although it can
226          * be present as a virtual/dummy keyboard. For now, there
227          * is no reliable way to tell if a real keyboard is present.
228          */
229         return 1;
230
231     /* X11 has a mouse by definition */
232     case GLUT_HAS_MOUSE:
233         return 1 ;
234
235     case GLUT_NUM_MOUSE_BUTTONS:
236         /* We should be able to pass NULL when the last argument is zero,
237          * but at least one X server has a bug where this causes a segfault.
238          *
239          * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
240          * rather than an Axis; "freeglut_main.c" expects this when
241          * checking for a wheel event.
242          */
243         {
244             unsigned char map;
245             int nbuttons = XGetPointerMapping(fgDisplay.pDisplay.Display, &map,0);
246             return nbuttons;
247         }
248
249     default:
250         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
251         break;
252     }
253
254     /* And now -- the failure. */
255     return -1;
256 }
257
258
259 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
260 {
261   int *array;
262
263   int attributes[9];
264   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
265   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
266   int attribute_name = 0;
267
268   array = NULL;
269   *size = 0;
270
271   switch (eWhat)
272     {
273     case GLUT_AUX:
274     case GLUT_MULTISAMPLE:
275
276       attributes[0] = GLX_BUFFER_SIZE;
277       attributes[1] = GLX_DONT_CARE;
278
279       switch (eWhat)
280         {
281         case GLUT_AUX:
282           /*
283             FBConfigs are now sorted by increasing number of auxiliary
284             buffers.  We want at least one buffer.
285           */
286           attributes[2] = GLX_AUX_BUFFERS;
287           attributes[3] = 1;
288           attributes[4] = None;
289
290           attribute_name = GLX_AUX_BUFFERS;
291
292           break;
293
294
295         case GLUT_MULTISAMPLE:
296           attributes[2] = GLX_AUX_BUFFERS;
297           attributes[3] = GLX_DONT_CARE;
298           attributes[4] = GLX_SAMPLE_BUFFERS;
299           attributes[5] = 1;
300           /*
301             FBConfigs are now sorted by increasing number of samples per
302             pixel.  We want at least one sample.
303           */
304           attributes[6] = GLX_SAMPLES;
305           attributes[7] = 1;
306           attributes[8] = None;
307
308           attribute_name = GLX_SAMPLES;
309
310           break;
311         }
312
313       fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
314                                         fgDisplay.pDisplay.Screen,
315                                         attributes,
316                                         &fbconfigArraySize);
317
318       if (fbconfigArray != NULL)
319         {
320           int * temp_array;
321           int result;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
322           int previous_value;
323           int i;
324
325           temp_array = malloc(sizeof(int) * fbconfigArraySize);
326           previous_value = 0;
327
328           for (i = 0; i < fbconfigArraySize; i++)
329             {
330               int value;
331
332               result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
333                                             fbconfigArray[i],
334                                             attribute_name,
335                                             &value);
336               if (value > previous_value)
337                 {
338                   temp_array[*size] = value;
339                   previous_value = value;
340                   (*size)++;
341                 }
342             }
343
344           array = malloc(sizeof(int) * (*size));
345           for (i = 0; i < *size; i++)
346             {
347               array[i] = temp_array[i];
348             }
349
350           free(temp_array);
351           XFree(fbconfigArray);
352         }
353
354       break;
355
356     default:
357       break;
358     }
359
360   return array;
361 }
362
363