- fallback to non-sRGB visuals if the context creation failed (GLX-only)
[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     GLX_QUERY( GLUT_WINDOW_SRGB,                GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
87
88 #   undef GLX_QUERY
89
90     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
91     case GLUT_DISPLAY_MODE_POSSIBLE:
92     {
93         /*  We should not have to call fghChooseConfig again here.  */
94         GLXFBConfig config;
95         return fghChooseConfig(&config);
96     }
97
98     /* This is system-dependent */
99     case GLUT_WINDOW_FORMAT_ID:
100         if( fgStructure.CurrentWindow == NULL )
101             return 0;
102
103         return fgPlatformGetConfig( GLX_VISUAL_ID );
104
105     default:
106         fgWarning( "glutGet(): missing enum handle %d", eWhat );
107         break;
108     }
109
110         return -1;
111 }
112
113 int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
114 {
115   int *array;
116
117   int attributes[9];
118   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
119   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
120   int attribute_name = 0;
121
122   array = NULL;
123   *size = 0;
124
125   switch (eWhat)
126     {
127     case GLUT_AUX:
128     case GLUT_MULTISAMPLE:
129
130       attributes[0] = GLX_BUFFER_SIZE;
131       attributes[1] = GLX_DONT_CARE;
132
133       switch (eWhat)
134         {
135         case GLUT_AUX:
136           /*
137             FBConfigs are now sorted by increasing number of auxiliary
138             buffers.  We want at least one buffer.
139           */
140           attributes[2] = GLX_AUX_BUFFERS;
141           attributes[3] = 1;
142           attributes[4] = None;
143
144           attribute_name = GLX_AUX_BUFFERS;
145
146           break;
147
148
149         case GLUT_MULTISAMPLE:
150           attributes[2] = GLX_AUX_BUFFERS;
151           attributes[3] = GLX_DONT_CARE;
152           attributes[4] = GLX_SAMPLE_BUFFERS;
153           attributes[5] = 1;
154           /*
155             FBConfigs are now sorted by increasing number of samples per
156             pixel.  We want at least one sample.
157           */
158           attributes[6] = GLX_SAMPLES;
159           attributes[7] = 1;
160           attributes[8] = None;
161
162           attribute_name = GLX_SAMPLES;
163
164           break;
165         }
166
167       fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
168                                         fgDisplay.pDisplay.Screen,
169                                         attributes,
170                                         &fbconfigArraySize);
171
172       if (fbconfigArray != NULL)
173         {
174           int * temp_array;
175           int result __fg_unused;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
176           int previous_value;
177           int i;
178
179           temp_array = malloc(sizeof(int) * fbconfigArraySize);
180           previous_value = 0;
181
182           for (i = 0; i < fbconfigArraySize; i++)
183             {
184               int value;
185
186               result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
187                                             fbconfigArray[i],
188                                             attribute_name,
189                                             &value);
190               if (value > previous_value)
191                 {
192                   temp_array[*size] = value;
193                   previous_value = value;
194                   (*size)++;
195                 }
196             }
197
198           array = malloc(sizeof(int) * (*size));
199           for (i = 0; i < *size; i++)
200             {
201               array[i] = temp_array[i];
202             }
203
204           free(temp_array);
205           XFree(fbconfigArray);
206         }
207
208       break;
209
210     default:
211       break;
212     }
213
214   return array;
215 }