1b8dd18149900d0951c209a950498e827508c94d
[freeglut] / src / x11 / fg_state_x11_glx.c
1 /*
2  * fg_state_x11_glx.c
3  *
4  * X11-specific freeglut state query methods.
5  *
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
7  * Written by John F. Fay, <fayjf@sourceforge.net>
8  * Creation date: Sat Feb 4 2012
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #include <GL/freeglut.h>
29 #include "fg_internal.h"
30 #include "x11/fg_window_x11_glx.h"
31
32 /*
33  * Queries the GL context about some attributes
34  */
35 int fgPlatformGetConfig( int attribute )
36 {
37   int returnValue = 0;
38   int result __fg_unused;  /*  Not checked  */
39
40   if( fgStructure.CurrentWindow )
41       result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
42                                      fgStructure.CurrentWindow->Window.pContext.FBConfig,
43                                      attribute,
44                                      &returnValue );
45
46   return returnValue;
47 }
48
49 int fghPlatformGlutGetGLX ( GLenum eWhat )
50 {
51     switch( eWhat )
52     {
53     /*
54      * The window/context specific queries are handled mostly by
55      * fgPlatformGetConfig().
56      */
57     case GLUT_WINDOW_NUM_SAMPLES:
58       {
59         int nsamples = 0;
60 #ifdef GLX_VERSION_1_3
61         glGetIntegerv(GL_SAMPLES, &nsamples);
62 #endif
63         return nsamples;
64       }
65
66     /*
67      * The rest of GLX queries under X are general enough to use a macro to
68      * check them
69      */
70 #   define GLX_QUERY(a,b) case a: return fgPlatformGetConfig( b );
71
72     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );
73     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );
74     GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE,         GLX_BUFFER_SIZE         );
75     GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE,        GLX_STENCIL_SIZE        );
76     GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE,          GLX_DEPTH_SIZE          );
77     GLX_QUERY( GLUT_WINDOW_RED_SIZE,            GLX_RED_SIZE            );
78     GLX_QUERY( GLUT_WINDOW_GREEN_SIZE,          GLX_GREEN_SIZE          );
79     GLX_QUERY( GLUT_WINDOW_BLUE_SIZE,           GLX_BLUE_SIZE           );
80     GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE,          GLX_ALPHA_SIZE          );
81     GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE,      GLX_ACCUM_RED_SIZE      );
82     GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE,    GLX_ACCUM_GREEN_SIZE    );
83     GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE,     GLX_ACCUM_BLUE_SIZE     );
84     GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE,    GLX_ACCUM_ALPHA_SIZE    );
85     GLX_QUERY( GLUT_WINDOW_STEREO,              GLX_STEREO              );
86
87 #   undef GLX_QUERY
88
89     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
90     case GLUT_DISPLAY_MODE_POSSIBLE:
91     {
92         /*  We should not have to call fghChooseConfig again here.  */
93         GLXFBConfig config;
94         return fghChooseConfig(&config);
95     }
96
97     /* This is system-dependent */
98     case GLUT_WINDOW_FORMAT_ID:
99         if( fgStructure.CurrentWindow == NULL )
100             return 0;
101
102         return fgPlatformGetConfig( GLX_VISUAL_ID );
103
104     default:
105         fgWarning( "glutGet(): missing enum handle %d", eWhat );
106         break;
107     }
108
109         return -1;
110 }
111
112 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
113 {
114   int *array;
115
116   int attributes[9];
117   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
118   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
119   int attribute_name = 0;
120
121   array = NULL;
122   *size = 0;
123
124   switch (eWhat)
125     {
126     case GLUT_AUX:
127     case GLUT_MULTISAMPLE:
128
129       attributes[0] = GLX_BUFFER_SIZE;
130       attributes[1] = GLX_DONT_CARE;
131
132       switch (eWhat)
133         {
134         case GLUT_AUX:
135           /*
136             FBConfigs are now sorted by increasing number of auxiliary
137             buffers.  We want at least one buffer.
138           */
139           attributes[2] = GLX_AUX_BUFFERS;
140           attributes[3] = 1;
141           attributes[4] = None;
142
143           attribute_name = GLX_AUX_BUFFERS;
144
145           break;
146
147
148         case GLUT_MULTISAMPLE:
149           attributes[2] = GLX_AUX_BUFFERS;
150           attributes[3] = GLX_DONT_CARE;
151           attributes[4] = GLX_SAMPLE_BUFFERS;
152           attributes[5] = 1;
153           /*
154             FBConfigs are now sorted by increasing number of samples per
155             pixel.  We want at least one sample.
156           */
157           attributes[6] = GLX_SAMPLES;
158           attributes[7] = 1;
159           attributes[8] = None;
160
161           attribute_name = GLX_SAMPLES;
162
163           break;
164         }
165
166       fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
167                                         fgDisplay.pDisplay.Screen,
168                                         attributes,
169                                         &fbconfigArraySize);
170
171       if (fbconfigArray != NULL)
172         {
173           int * temp_array;
174           int result __fg_unused;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
175           int previous_value;
176           int i;
177
178           temp_array = malloc(sizeof(int) * fbconfigArraySize);
179           previous_value = 0;
180
181           for (i = 0; i < fbconfigArraySize; i++)
182             {
183               int value;
184
185               result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
186                                             fbconfigArray[i],
187                                             attribute_name,
188                                             &value);
189               if (value > previous_value)
190                 {
191                   temp_array[*size] = value;
192                   previous_value = value;
193                   (*size)++;
194                 }
195             }
196
197           array = malloc(sizeof(int) * (*size));
198           for (i = 0; i < *size; i++)
199             {
200               array[i] = temp_array[i];
201             }
202
203           free(temp_array);
204           XFree(fbconfigArray);
205         }
206
207       break;
208
209     default:
210       break;
211     }
212
213   return array;
214 }