Setting the line endings and keywords on a bunch of new text files
[freeglut] / src / x11 / freeglut_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 "../Common/freeglut_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 int fgPlatformGlutLayerGet( GLenum eWhat )
259 {
260     /*
261      * This is easy as layers are not implemented ;-)
262      *
263      * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or
264      * XXX is overlay support planned?
265      */
266     switch( eWhat )
267     {
268     case GLUT_OVERLAY_POSSIBLE:
269         return 0;
270
271     case GLUT_LAYER_IN_USE:
272         return GLUT_NORMAL;
273
274     case GLUT_HAS_OVERLAY:
275         return 0;
276
277     case GLUT_TRANSPARENT_INDEX:
278         /*
279          * Return just anything, which is always defined as zero
280          *
281          * XXX HUH?
282          */
283         return 0;
284
285     case GLUT_NORMAL_DAMAGED:
286         /* XXX Actually I do not know. Maybe. */
287         return 0;
288
289     case GLUT_OVERLAY_DAMAGED:
290         return -1;
291
292     default:
293         fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
294         break;
295     }
296
297     /* And fail. That's good. Programs do love failing. */
298     return -1;
299 }
300
301
302 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
303 {
304   int *array;
305
306   int attributes[9];
307   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
308   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
309   int attribute_name = 0;
310
311   array = NULL;
312   *size = 0;
313
314   switch (eWhat)
315     {
316     case GLUT_AUX:
317     case GLUT_MULTISAMPLE:
318
319       attributes[0] = GLX_BUFFER_SIZE;
320       attributes[1] = GLX_DONT_CARE;
321
322       switch (eWhat)
323         {
324         case GLUT_AUX:
325           /*
326             FBConfigs are now sorted by increasing number of auxiliary
327             buffers.  We want at least one buffer.
328           */
329           attributes[2] = GLX_AUX_BUFFERS;
330           attributes[3] = 1;
331           attributes[4] = None;
332
333           attribute_name = GLX_AUX_BUFFERS;
334
335           break;
336
337
338         case GLUT_MULTISAMPLE:
339           attributes[2] = GLX_AUX_BUFFERS;
340           attributes[3] = GLX_DONT_CARE;
341           attributes[4] = GLX_SAMPLE_BUFFERS;
342           attributes[5] = 1;
343           /*
344             FBConfigs are now sorted by increasing number of samples per
345             pixel.  We want at least one sample.
346           */
347           attributes[6] = GLX_SAMPLES;
348           attributes[7] = 1;
349           attributes[8] = None;
350
351           attribute_name = GLX_SAMPLES;
352
353           break;
354         }
355
356       fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
357                                         fgDisplay.pDisplay.Screen,
358                                         attributes,
359                                         &fbconfigArraySize);
360
361       if (fbconfigArray != NULL)
362         {
363           int * temp_array;
364           int result;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
365           int previous_value;
366           int i;
367
368           temp_array = malloc(sizeof(int) * fbconfigArraySize);
369           previous_value = 0;
370
371           for (i = 0; i < fbconfigArraySize; i++)
372             {
373               int value;
374
375               result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
376                                             fbconfigArray[i],
377                                             attribute_name,
378                                             &value);
379               if (value > previous_value)
380                 {
381                   temp_array[*size] = value;
382                   previous_value = value;
383                   (*size)++;
384                 }
385             }
386
387           array = malloc(sizeof(int) * (*size));
388           for (i = 0; i < *size; i++)
389             {
390               array[i] = temp_array[i];
391             }
392
393           free(temp_array);
394           XFree(fbconfigArray);
395         }
396
397       break;
398
399     default:
400       break;
401     }
402
403   return array;
404 }
405
406