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