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