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