Moving Windows-specific "glutGet" code into its own file
[freeglut] / src / Common / freeglut_state.c
1 /*\r
2  * freeglut_state.c\r
3  *\r
4  * Freeglut state query methods.\r
5  *\r
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.\r
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>\r
8  * Creation date: Thu Dec 16 1999\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 "freeglut_internal.h"\r
30 \r
31 /*\r
32  * TODO BEFORE THE STABLE RELEASE:\r
33  *\r
34  *  glutGet()               -- X11 tests passed, but check if all enums\r
35  *                             handled (what about Win32?)\r
36  *  glutDeviceGet()         -- X11 tests passed, but check if all enums\r
37  *                             handled (what about Win32?)\r
38  *  glutGetModifiers()      -- OK, but could also remove the limitation\r
39  *  glutLayerGet()          -- what about GLUT_NORMAL_DAMAGED?\r
40  *\r
41  * The fail-on-call policy will help adding the most needed things imho.\r
42  */\r
43 \r
44 extern int fgPlatformGlutGet ( GLenum eWhat );\r
45 \r
46 /* -- LOCAL DEFINITIONS ---------------------------------------------------- */\r
47 \r
48 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */\r
49 \r
50 #if TARGET_HOST_POSIX_X11\r
51 /*\r
52  * Queries the GL context about some attributes\r
53  */\r
54 static int fghGetConfig( int attribute )\r
55 {\r
56   int returnValue = 0;\r
57   int result;  /*  Not checked  */\r
58 \r
59   if( fgStructure.CurrentWindow )\r
60       result = glXGetFBConfigAttrib( fgDisplay.Display,\r
61                                      *(fgStructure.CurrentWindow->Window.FBConfig),\r
62                                      attribute,\r
63                                      &returnValue );\r
64 \r
65   return returnValue;\r
66 }\r
67 \r
68 static int fgPlatformGlutGet ( GLenum eWhat )\r
69 {\r
70     int nsamples = 0;\r
71 \r
72     switch( eWhat )\r
73     {\r
74     /*\r
75      * The window/context specific queries are handled mostly by\r
76      * fghGetConfig().\r
77      */\r
78     case GLUT_WINDOW_NUM_SAMPLES:\r
79 #ifdef GLX_VERSION_1_3\r
80         glGetIntegerv(GL_SAMPLES, &nsamples);\r
81 #endif\r
82         return nsamples;\r
83 \r
84     /*\r
85      * The rest of GLX queries under X are general enough to use a macro to\r
86      * check them\r
87      */\r
88 #   define GLX_QUERY(a,b) case a: return fghGetConfig( b );\r
89 \r
90     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );\r
91     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );\r
92     GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE,         GLX_BUFFER_SIZE         );\r
93     GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE,        GLX_STENCIL_SIZE        );\r
94     GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE,          GLX_DEPTH_SIZE          );\r
95     GLX_QUERY( GLUT_WINDOW_RED_SIZE,            GLX_RED_SIZE            );\r
96     GLX_QUERY( GLUT_WINDOW_GREEN_SIZE,          GLX_GREEN_SIZE          );\r
97     GLX_QUERY( GLUT_WINDOW_BLUE_SIZE,           GLX_BLUE_SIZE           );\r
98     GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE,          GLX_ALPHA_SIZE          );\r
99     GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE,      GLX_ACCUM_RED_SIZE      );\r
100     GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE,    GLX_ACCUM_GREEN_SIZE    );\r
101     GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE,     GLX_ACCUM_BLUE_SIZE     );\r
102     GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE,    GLX_ACCUM_ALPHA_SIZE    );\r
103     GLX_QUERY( GLUT_WINDOW_STEREO,              GLX_STEREO              );\r
104 \r
105 #   undef GLX_QUERY\r
106 \r
107     /* Colormap size is handled in a bit different way than all the rest */\r
108     case GLUT_WINDOW_COLORMAP_SIZE:\r
109         if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )\r
110         {\r
111             /*\r
112              * We've got a RGBA visual, so there is no colormap at all.\r
113              * The other possibility is that we have no current window set.\r
114              */\r
115             return 0;\r
116         }\r
117         else\r
118         {\r
119           const GLXFBConfig * fbconfig =\r
120                 fgStructure.CurrentWindow->Window.FBConfig;\r
121 \r
122           XVisualInfo * visualInfo =\r
123                 glXGetVisualFromFBConfig( fgDisplay.Display, *fbconfig );\r
124 \r
125           const int result = visualInfo->visual->map_entries;\r
126 \r
127           XFree(visualInfo);\r
128 \r
129           return result;\r
130         }\r
131 \r
132     /*\r
133      * Those calls are somewhat similiar, as they use XGetWindowAttributes()\r
134      * function\r
135      */\r
136     case GLUT_WINDOW_X:\r
137     case GLUT_WINDOW_Y:\r
138     case GLUT_WINDOW_BORDER_WIDTH:\r
139     case GLUT_WINDOW_HEADER_HEIGHT:\r
140     {\r
141         int x, y;\r
142         Window w;\r
143 \r
144         if( fgStructure.CurrentWindow == NULL )\r
145             return 0;\r
146 \r
147         XTranslateCoordinates(\r
148             fgDisplay.Display,\r
149             fgStructure.CurrentWindow->Window.Handle,\r
150             fgDisplay.RootWindow,\r
151             0, 0, &x, &y, &w);\r
152 \r
153         switch ( eWhat )\r
154         {\r
155         case GLUT_WINDOW_X: return x;\r
156         case GLUT_WINDOW_Y: return y;\r
157         }\r
158 \r
159         if ( w == 0 )\r
160             return 0;\r
161         XTranslateCoordinates(\r
162             fgDisplay.Display,\r
163             fgStructure.CurrentWindow->Window.Handle,\r
164             w, 0, 0, &x, &y, &w);\r
165 \r
166         switch ( eWhat )\r
167         {\r
168         case GLUT_WINDOW_BORDER_WIDTH:  return x;\r
169         case GLUT_WINDOW_HEADER_HEIGHT: return y;\r
170         }\r
171     }\r
172 \r
173     case GLUT_WINDOW_WIDTH:\r
174     case GLUT_WINDOW_HEIGHT:\r
175     {\r
176         XWindowAttributes winAttributes;\r
177 \r
178         if( fgStructure.CurrentWindow == NULL )\r
179             return 0;\r
180         XGetWindowAttributes(\r
181             fgDisplay.Display,\r
182             fgStructure.CurrentWindow->Window.Handle,\r
183             &winAttributes\r
184         );\r
185         switch ( eWhat )\r
186         {\r
187         case GLUT_WINDOW_WIDTH:            return winAttributes.width ;\r
188         case GLUT_WINDOW_HEIGHT:           return winAttributes.height ;\r
189         }\r
190     }\r
191 \r
192     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */\r
193     case GLUT_DISPLAY_MODE_POSSIBLE:\r
194     {\r
195         /*  We should not have to call fgChooseFBConfig again here.  */\r
196         GLXFBConfig * fbconfig;\r
197         int isPossible;\r
198 \r
199         fbconfig = fgChooseFBConfig(NULL);\r
200 \r
201         if (fbconfig == NULL)\r
202         {\r
203             isPossible = 0;\r
204         }\r
205         else\r
206         {\r
207             isPossible = 1;\r
208             XFree(fbconfig);\r
209         }\r
210 \r
211         return isPossible;\r
212     }\r
213 \r
214     /* This is system-dependant */\r
215     case GLUT_WINDOW_FORMAT_ID:\r
216         if( fgStructure.CurrentWindow == NULL )\r
217             return 0;\r
218 \r
219         return fghGetConfig( GLX_VISUAL_ID );\r
220 \r
221     default:\r
222         fgWarning( "glutGet(): missing enum handle %d", eWhat );\r
223         break;\r
224     }\r
225 }\r
226 #endif\r
227 \r
228 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */\r
229 \r
230 /*\r
231  * General settings assignment method\r
232  */\r
233 void FGAPIENTRY glutSetOption( GLenum eWhat, int value )\r
234 {\r
235     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" );\r
236 \r
237     /*\r
238      * XXX In chronological code add order.  (WHY in that order?)\r
239      */\r
240     switch( eWhat )\r
241     {\r
242     case GLUT_INIT_WINDOW_X:\r
243         fgState.Position.X = (GLint)value;\r
244         break;\r
245 \r
246     case GLUT_INIT_WINDOW_Y:\r
247         fgState.Position.Y = (GLint)value;\r
248         break;\r
249 \r
250     case GLUT_INIT_WINDOW_WIDTH:\r
251         fgState.Size.X = (GLint)value;\r
252         break;\r
253 \r
254     case GLUT_INIT_WINDOW_HEIGHT:\r
255         fgState.Size.Y = (GLint)value;\r
256         break;\r
257 \r
258     case GLUT_INIT_DISPLAY_MODE:\r
259         fgState.DisplayMode = (unsigned int)value;\r
260         break;\r
261 \r
262     case GLUT_ACTION_ON_WINDOW_CLOSE:\r
263         fgState.ActionOnWindowClose = value;\r
264         break;\r
265 \r
266     case GLUT_RENDERING_CONTEXT:\r
267         fgState.UseCurrentContext =\r
268             ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;\r
269         break;\r
270 \r
271     case GLUT_DIRECT_RENDERING:\r
272         fgState.DirectContext = value;\r
273         break;\r
274 \r
275     case GLUT_WINDOW_CURSOR:\r
276         if( fgStructure.CurrentWindow != NULL )\r
277             fgStructure.CurrentWindow->State.Cursor = value;\r
278         break;\r
279 \r
280     case GLUT_AUX:\r
281       fgState.AuxiliaryBufferNumber = value;\r
282       break;\r
283 \r
284     case GLUT_MULTISAMPLE:\r
285       fgState.SampleNumber = value;\r
286       break;\r
287 \r
288     default:\r
289         fgWarning( "glutSetOption(): missing enum handle %d", eWhat );\r
290         break;\r
291     }\r
292 }\r
293 \r
294 /*\r
295  * General settings query method\r
296  */\r
297 int FGAPIENTRY glutGet( GLenum eWhat )\r
298 {\r
299     switch (eWhat)\r
300     {\r
301     case GLUT_INIT_STATE:\r
302         return fgState.Initialised;\r
303 \r
304     case GLUT_ELAPSED_TIME:\r
305         return fgElapsedTime();\r
306     }\r
307 \r
308     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );\r
309 \r
310     /* XXX In chronological code add order.  (WHY in that order?) */\r
311     switch( eWhat )\r
312     {\r
313     /* Following values are stored in fgState and fgDisplay global structures */\r
314     case GLUT_SCREEN_WIDTH:         return fgDisplay.ScreenWidth   ;\r
315     case GLUT_SCREEN_HEIGHT:        return fgDisplay.ScreenHeight  ;\r
316     case GLUT_SCREEN_WIDTH_MM:      return fgDisplay.ScreenWidthMM ;\r
317     case GLUT_SCREEN_HEIGHT_MM:     return fgDisplay.ScreenHeightMM;\r
318     case GLUT_INIT_WINDOW_X:        return fgState.Position.Use ?\r
319                                            fgState.Position.X : -1 ;\r
320     case GLUT_INIT_WINDOW_Y:        return fgState.Position.Use ?\r
321                                            fgState.Position.Y : -1 ;\r
322     case GLUT_INIT_WINDOW_WIDTH:    return fgState.Size.Use ?\r
323                                            fgState.Size.X : -1     ;\r
324     case GLUT_INIT_WINDOW_HEIGHT:   return fgState.Size.Use ?\r
325                                            fgState.Size.Y : -1     ;\r
326     case GLUT_INIT_DISPLAY_MODE:    return fgState.DisplayMode     ;\r
327     case GLUT_INIT_MAJOR_VERSION:   return fgState.MajorVersion    ;\r
328     case GLUT_INIT_MINOR_VERSION:   return fgState.MinorVersion    ;\r
329     case GLUT_INIT_FLAGS:           return fgState.ContextFlags    ;\r
330     case GLUT_INIT_PROFILE:         return fgState.ContextProfile  ;\r
331 \r
332     /* The window structure queries */\r
333     case GLUT_WINDOW_PARENT:\r
334         if( fgStructure.CurrentWindow         == NULL ) return 0;\r
335         if( fgStructure.CurrentWindow->Parent == NULL ) return 0;\r
336         return fgStructure.CurrentWindow->Parent->ID;\r
337 \r
338     case GLUT_WINDOW_NUM_CHILDREN:\r
339         if( fgStructure.CurrentWindow == NULL )\r
340             return 0;\r
341         return fgListLength( &fgStructure.CurrentWindow->Children );\r
342 \r
343     case GLUT_WINDOW_CURSOR:\r
344         if( fgStructure.CurrentWindow == NULL )\r
345             return 0;\r
346         return fgStructure.CurrentWindow->State.Cursor;\r
347 \r
348     case GLUT_MENU_NUM_ITEMS:\r
349         if( fgStructure.CurrentMenu == NULL )\r
350             return 0;\r
351         return fgListLength( &fgStructure.CurrentMenu->Entries );\r
352 \r
353     case GLUT_ACTION_ON_WINDOW_CLOSE:\r
354         return fgState.ActionOnWindowClose;\r
355 \r
356     case GLUT_VERSION :\r
357         return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;\r
358 \r
359     case GLUT_RENDERING_CONTEXT:\r
360         return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT\r
361                                          : GLUT_CREATE_NEW_CONTEXT;\r
362 \r
363     case GLUT_DIRECT_RENDERING:\r
364         return fgState.DirectContext;\r
365 \r
366     case GLUT_FULL_SCREEN:\r
367         return fgStructure.CurrentWindow->State.IsFullscreen;\r
368 \r
369     case GLUT_AUX:\r
370       return fgState.AuxiliaryBufferNumber;\r
371 \r
372     case GLUT_MULTISAMPLE:\r
373       return fgState.SampleNumber;\r
374 \r
375     default:\r
376         return fgPlatformGlutGet ( eWhat );\r
377         break;\r
378     }\r
379     return -1;\r
380 }\r
381 \r
382 /*\r
383  * Returns various device information.\r
384  */\r
385 int FGAPIENTRY glutDeviceGet( GLenum eWhat )\r
386 {\r
387     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" );\r
388 \r
389     /* XXX WARNING: we are mostly lying in this function. */\r
390     switch( eWhat )\r
391     {\r
392     case GLUT_HAS_KEYBOARD:\r
393         /*\r
394          * Win32 is assumed a keyboard, and this cannot be queried,\r
395          * except for WindowsCE.\r
396          *\r
397          * X11 has a core keyboard by definition, although it can\r
398          * be present as a virtual/dummy keyboard. For now, there\r
399          * is no reliable way to tell if a real keyboard is present.\r
400          */\r
401 #if defined(_WIN32_CE)\r
402         return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;\r
403 #   if FREEGLUT_LIB_PRAGMAS\r
404 #       pragma comment (lib,"Kbdui.lib")\r
405 #   endif\r
406 \r
407 #else\r
408         return 1;\r
409 #endif\r
410 \r
411 #if TARGET_HOST_POSIX_X11\r
412 \r
413     /* X11 has a mouse by definition */\r
414     case GLUT_HAS_MOUSE:\r
415         return 1 ;\r
416 \r
417     case GLUT_NUM_MOUSE_BUTTONS:\r
418         /* We should be able to pass NULL when the last argument is zero,\r
419          * but at least one X server has a bug where this causes a segfault.\r
420          *\r
421          * In XFree86/Xorg servers, a mouse wheel is seen as two buttons\r
422          * rather than an Axis; "freeglut_main.c" expects this when\r
423          * checking for a wheel event.\r
424          */\r
425         {\r
426             unsigned char map;\r
427             int nbuttons = XGetPointerMapping(fgDisplay.Display, &map,0);\r
428             return nbuttons;\r
429         }\r
430 \r
431 #elif TARGET_HOST_MS_WINDOWS\r
432 \r
433     case GLUT_HAS_MOUSE:\r
434         /*\r
435          * MS Windows can be booted without a mouse.\r
436          */\r
437         return GetSystemMetrics( SM_MOUSEPRESENT );\r
438 \r
439     case GLUT_NUM_MOUSE_BUTTONS:\r
440 #  if defined(_WIN32_WCE)\r
441         return 1;\r
442 #  else\r
443         return GetSystemMetrics( SM_CMOUSEBUTTONS );\r
444 #  endif\r
445 #endif\r
446 \r
447     case GLUT_HAS_JOYSTICK:\r
448         return fgJoystickDetect ();\r
449 \r
450     case GLUT_OWNS_JOYSTICK:\r
451         return fgState.JoysticksInitialised;\r
452 \r
453     case GLUT_JOYSTICK_POLL_RATE:\r
454         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0;\r
455 \r
456     /* XXX The following two are only for Joystick 0 but this is an improvement */\r
457     case GLUT_JOYSTICK_BUTTONS:\r
458         return glutJoystickGetNumButtons ( 0 );\r
459 \r
460     case GLUT_JOYSTICK_AXES:\r
461         return glutJoystickGetNumAxes ( 0 );\r
462 \r
463     case GLUT_HAS_DIAL_AND_BUTTON_BOX:\r
464         return fgInputDeviceDetect ();\r
465 \r
466     case GLUT_NUM_DIALS:\r
467         if ( fgState.InputDevsInitialised ) return 8;\r
468         return 0;\r
469  \r
470     case GLUT_NUM_BUTTON_BOX_BUTTONS:\r
471         return 0;\r
472 \r
473     case GLUT_HAS_SPACEBALL:\r
474         return fgHasSpaceball();\r
475 \r
476     case GLUT_HAS_TABLET:\r
477         return 0;\r
478 \r
479     case GLUT_NUM_SPACEBALL_BUTTONS:\r
480         return fgSpaceballNumButtons();\r
481 \r
482     case GLUT_NUM_TABLET_BUTTONS:\r
483         return 0;\r
484 \r
485     case GLUT_DEVICE_IGNORE_KEY_REPEAT:\r
486         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0;\r
487 \r
488     case GLUT_DEVICE_KEY_REPEAT:\r
489         return fgState.KeyRepeat;\r
490 \r
491     default:\r
492         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );\r
493         break;\r
494     }\r
495 \r
496     /* And now -- the failure. */\r
497     return -1;\r
498 }\r
499 \r
500 /*\r
501  * This should return the current state of ALT, SHIFT and CTRL keys.\r
502  */\r
503 int FGAPIENTRY glutGetModifiers( void )\r
504 {\r
505     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" );\r
506     if( fgState.Modifiers == INVALID_MODIFIERS )\r
507     {\r
508         fgWarning( "glutGetModifiers() called outside an input callback" );\r
509         return 0;\r
510     }\r
511 \r
512     return fgState.Modifiers;\r
513 }\r
514 \r
515 /*\r
516  * Return the state of the GLUT API overlay subsystem. A misery ;-)\r
517  */\r
518 int FGAPIENTRY glutLayerGet( GLenum eWhat )\r
519 {\r
520     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" );\r
521 \r
522     /*\r
523      * This is easy as layers are not implemented ;-)\r
524      *\r
525      * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or\r
526      * XXX is overlay support planned?\r
527      */\r
528     switch( eWhat )\r
529     {\r
530 \r
531 #if TARGET_HOST_POSIX_X11\r
532 \r
533     case GLUT_OVERLAY_POSSIBLE:\r
534         return 0;\r
535 \r
536     case GLUT_LAYER_IN_USE:\r
537         return GLUT_NORMAL;\r
538 \r
539     case GLUT_HAS_OVERLAY:\r
540         return 0;\r
541 \r
542     case GLUT_TRANSPARENT_INDEX:\r
543         /*\r
544          * Return just anything, which is always defined as zero\r
545          *\r
546          * XXX HUH?\r
547          */\r
548         return 0;\r
549 \r
550     case GLUT_NORMAL_DAMAGED:\r
551         /* XXX Actually I do not know. Maybe. */\r
552         return 0;\r
553 \r
554     case GLUT_OVERLAY_DAMAGED:\r
555         return -1;\r
556 \r
557 #elif TARGET_HOST_MS_WINDOWS\r
558 \r
559     case GLUT_OVERLAY_POSSIBLE:\r
560 /*      return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,\r
561                                    PFD_OVERLAY_PLANE ); */\r
562       return 0 ;\r
563 \r
564     case GLUT_LAYER_IN_USE:\r
565         return GLUT_NORMAL;\r
566 \r
567     case GLUT_HAS_OVERLAY:\r
568         return 0;\r
569 \r
570     case GLUT_TRANSPARENT_INDEX:\r
571         /*\r
572          * Return just anything, which is always defined as zero\r
573          *\r
574          * XXX HUH?\r
575          */\r
576         return 0;\r
577 \r
578     case GLUT_NORMAL_DAMAGED:\r
579         /* XXX Actually I do not know. Maybe. */\r
580         return 0;\r
581 \r
582     case GLUT_OVERLAY_DAMAGED:\r
583         return -1;\r
584 #endif\r
585 \r
586     default:\r
587         fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );\r
588         break;\r
589     }\r
590 \r
591     /* And fail. That's good. Programs do love failing. */\r
592     return -1;\r
593 }\r
594 \r
595 int * FGAPIENTRY glutGetModeValues(GLenum eWhat, int * size)\r
596 {\r
597   int * array;\r
598 \r
599 #if TARGET_HOST_POSIX_X11\r
600   int attributes[9];\r
601   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */\r
602   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */\r
603   int attribute_name = 0;\r
604 #endif\r
605 \r
606   FREEGLUT_EXIT_IF_NOT_INITIALISED("glutGetModeValues");\r
607 \r
608   array = NULL;\r
609   *size = 0;\r
610 \r
611   switch (eWhat)\r
612     {\r
613 #if TARGET_HOST_POSIX_X11\r
614     case GLUT_AUX:\r
615     case GLUT_MULTISAMPLE:\r
616 \r
617       attributes[0] = GLX_BUFFER_SIZE;\r
618       attributes[1] = GLX_DONT_CARE;\r
619 \r
620       switch (eWhat)\r
621         {\r
622         case GLUT_AUX:\r
623           /*\r
624             FBConfigs are now sorted by increasing number of auxiliary\r
625             buffers.  We want at least one buffer.\r
626           */\r
627           attributes[2] = GLX_AUX_BUFFERS;\r
628           attributes[3] = 1;\r
629           attributes[4] = None;\r
630 \r
631           attribute_name = GLX_AUX_BUFFERS;\r
632 \r
633           break;\r
634 \r
635 \r
636         case GLUT_MULTISAMPLE:\r
637           attributes[2] = GLX_AUX_BUFFERS;\r
638           attributes[3] = GLX_DONT_CARE;\r
639           attributes[4] = GLX_SAMPLE_BUFFERS;\r
640           attributes[5] = 1;\r
641           /*\r
642             FBConfigs are now sorted by increasing number of samples per\r
643             pixel.  We want at least one sample.\r
644           */\r
645           attributes[6] = GLX_SAMPLES;\r
646           attributes[7] = 1;\r
647           attributes[8] = None;\r
648 \r
649           attribute_name = GLX_SAMPLES;\r
650 \r
651           break;\r
652         }\r
653 \r
654       fbconfigArray = glXChooseFBConfig(fgDisplay.Display,\r
655                                         fgDisplay.Screen,\r
656                                         attributes,\r
657                                         &fbconfigArraySize);\r
658 \r
659       if (fbconfigArray != NULL)\r
660         {\r
661           int * temp_array;\r
662           int result;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */\r
663           int previous_value;\r
664           int i;\r
665 \r
666           temp_array = malloc(sizeof(int) * fbconfigArraySize);\r
667           previous_value = 0;\r
668 \r
669           for (i = 0; i < fbconfigArraySize; i++)\r
670             {\r
671               int value;\r
672 \r
673               result = glXGetFBConfigAttrib(fgDisplay.Display,\r
674                                             fbconfigArray[i],\r
675                                             attribute_name,\r
676                                             &value);\r
677               if (value > previous_value)\r
678                 {\r
679                   temp_array[*size] = value;\r
680                   previous_value = value;\r
681                   (*size)++;\r
682                 }\r
683             }\r
684 \r
685           array = malloc(sizeof(int) * (*size));\r
686           for (i = 0; i < *size; i++)\r
687             {\r
688               array[i] = temp_array[i];\r
689             }\r
690 \r
691           free(temp_array);\r
692           XFree(fbconfigArray);\r
693         }\r
694 \r
695       break;\r
696 #endif      \r
697 \r
698     default:\r
699       break;\r
700     }\r
701 \r
702   return array;\r
703 }\r
704 \r
705 /*** END OF FILE ***/\r