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