3 * OpenGL pbuffers utility functions.
6 * Original code: April 1997
7 * Updated on 5 October 2002
8 * Updated again on 3 January 2005 to use GLX 1.3 functions in preference
9 * to the GLX_SGIX_fbconfig/pbuffer extensions.
18 * Test if we pixel buffers are available for a particular X screen.
19 * Input: dpy - the X display
20 * screen - screen number
21 * Return: 0 = fbconfigs not available.
22 * 1 = fbconfigs are available via GLX 1.3.
23 * 2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig
26 QueryFBConfig(Display
*dpy
, int screen
)
28 #if defined(GLX_VERSION_1_3)
30 /* GLX 1.3 supports pbuffers */
31 int glxVersionMajor
, glxVersionMinor
;
32 if (!glXQueryVersion(dpy
, &glxVersionMajor
, &glxVersionMinor
)) {
33 /* GLX not available! */
36 if (glxVersionMajor
* 100 + glxVersionMinor
>= 103) {
43 /* Try the SGIX extensions */
46 extensions
= (char *) glXQueryServerString(dpy
, screen
, GLX_EXTENSIONS
);
47 if (extensions
&& strstr(extensions
,"GLX_SGIX_fbconfig")) {
56 * Test if we pixel buffers are available for a particular X screen.
57 * Input: dpy - the X display
58 * screen - screen number
59 * Return: 0 = pixel buffers not available.
60 * 1 = pixel buffers are available via GLX 1.3.
61 * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
64 QueryPbuffers(Display
*dpy
, int screen
)
68 ret
= QueryFBConfig(dpy
, screen
);
71 extensions
= (char *) glXQueryServerString(dpy
, screen
, GLX_EXTENSIONS
);
72 if (extensions
&& strstr(extensions
, "GLX_SGIX_pbuffer"))
82 ChooseFBConfig(Display
*dpy
, int screen
, const int attribs
[], int *nConfigs
)
84 int fbcSupport
= QueryPbuffers(dpy
, screen
);
85 #if defined(GLX_VERSION_1_3)
86 if (fbcSupport
== 1) {
87 return glXChooseFBConfig(dpy
, screen
, attribs
, nConfigs
);
90 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
91 if (fbcSupport
== 2) {
92 return glXChooseFBConfigSGIX(dpy
, screen
, (int *) attribs
, nConfigs
);
100 GetAllFBConfigs(Display
*dpy
, int screen
, int *nConfigs
)
102 int fbcSupport
= QueryFBConfig(dpy
, screen
);
103 #if defined(GLX_VERSION_1_3)
104 if (fbcSupport
== 1) {
105 return glXGetFBConfigs(dpy
, screen
, nConfigs
);
108 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
109 if (fbcSupport
== 2) {
110 /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
111 * of all available configurations.
113 return glXChooseFBConfigSGIX(dpy
, screen
, NULL
, nConfigs
);
121 GetVisualFromFBConfig(Display
*dpy
, int screen
, FBCONFIG config
)
123 int fbcSupport
= QueryFBConfig(dpy
, screen
);
124 #if defined(GLX_VERSION_1_3)
125 if (fbcSupport
== 1) {
126 return glXGetVisualFromFBConfig(dpy
, config
);
129 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
130 if (fbcSupport
== 2) {
131 return glXGetVisualFromFBConfigSGIX(dpy
, config
);
139 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
140 * to query an fbconfig attribute.
143 GetFBConfigAttrib(Display
*dpy
, int screen
,
144 #if defined(GLX_VERSION_1_3)
145 const GLXFBConfig config
,
146 #elif defined(GLX_SGIX_fbconfig)
147 const GLXFBConfigSGIX config
,
152 int fbcSupport
= QueryFBConfig(dpy
, screen
);
155 #if defined(GLX_VERSION_1_3)
156 if (fbcSupport
== 1) {
158 if (glXGetFBConfigAttrib(dpy
, config
, attrib
, &value
) != 0) {
166 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
167 if (fbcSupport
== 2) {
168 if (glXGetFBConfigAttribSGIX(dpy
, config
, attrib
, &value
) != 0) {
181 * Print parameters for a GLXFBConfig to stdout.
182 * Input: dpy - the X display
183 * screen - the X screen number
184 * fbConfig - the fbconfig handle
185 * horizFormat - if true, print in horizontal format
188 PrintFBConfigInfo(Display
*dpy
, int screen
, FBCONFIG config
, Bool horizFormat
)
191 int width
=2, height
=2;
192 int bufferSize
, level
, doubleBuffer
, stereo
, auxBuffers
;
193 int redSize
, greenSize
, blueSize
, alphaSize
;
194 int depthSize
, stencilSize
;
195 int accumRedSize
, accumBlueSize
, accumGreenSize
, accumAlphaSize
;
196 int sampleBuffers
, samples
;
197 int drawableType
, renderType
, xRenderable
, xVisual
, id
;
198 int maxWidth
, maxHeight
, maxPixels
;
199 int optWidth
, optHeight
;
200 int floatComponents
= 0;
202 /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
203 bufferSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_BUFFER_SIZE
);
204 level
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_LEVEL
);
205 doubleBuffer
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DOUBLEBUFFER
);
206 stereo
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_STEREO
);
207 auxBuffers
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_AUX_BUFFERS
);
208 redSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_RED_SIZE
);
209 greenSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_GREEN_SIZE
);
210 blueSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_BLUE_SIZE
);
211 alphaSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ALPHA_SIZE
);
212 depthSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DEPTH_SIZE
);
213 stencilSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_STENCIL_SIZE
);
214 accumRedSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_RED_SIZE
);
215 accumGreenSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_GREEN_SIZE
);
216 accumBlueSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_BLUE_SIZE
);
217 accumAlphaSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_ALPHA_SIZE
);
218 sampleBuffers
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_SAMPLE_BUFFERS
);
219 samples
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_SAMPLES
);
220 drawableType
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DRAWABLE_TYPE
);
221 renderType
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_RENDER_TYPE
);
222 xRenderable
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_X_RENDERABLE
);
223 xVisual
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_X_VISUAL_TYPE
);
224 if (!xRenderable
|| !(drawableType
& GLX_WINDOW_BIT_SGIX
))
227 id
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_FBCONFIG_ID
);
228 maxWidth
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_WIDTH
);
229 maxHeight
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_HEIGHT
);
230 maxPixels
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_PIXELS
);
231 #if defined(GLX_SGIX_pbuffer)
232 optWidth
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
);
233 optHeight
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
);
235 optWidth
= optHeight
= 0;
237 #if defined(GLX_NV_float_buffer)
238 floatComponents
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_FLOAT_COMPONENTS_NV
);
241 /* See if we can create a pbuffer with this config */
242 pBuffer
= CreatePbuffer(dpy
, screen
, config
, width
, height
, False
, False
);
245 printf("0x%-9x ", id
);
246 if (xVisual
==GLX_STATIC_GRAY
) printf("StaticGray ");
247 else if (xVisual
==GLX_GRAY_SCALE
) printf("GrayScale ");
248 else if (xVisual
==GLX_STATIC_COLOR
) printf("StaticColor ");
249 else if (xVisual
==GLX_PSEUDO_COLOR
) printf("PseudoColor ");
250 else if (xVisual
==GLX_TRUE_COLOR
) printf("TrueColor ");
251 else if (xVisual
==GLX_DIRECT_COLOR
) printf("DirectColor ");
252 else printf(" -none- ");
253 printf(" %3d %3d %s %s %s %2s ", bufferSize
, level
,
254 (renderType
& GLX_RGBA_BIT_SGIX
) ? "y" : ".",
255 (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) ? "y" : ".",
256 doubleBuffer
? "y" : ".",
258 printf("%2d %2d %2d %2d ", redSize
, greenSize
, blueSize
, alphaSize
);
259 printf("%2d %2d ", depthSize
, stencilSize
);
260 printf("%2d %2d %2d %2d", accumRedSize
, accumGreenSize
, accumBlueSize
,
262 printf(" %2d %2d", sampleBuffers
, samples
);
263 printf(" %s %c", pBuffer
? "y" : ".",
264 ".y"[floatComponents
]);
268 printf("Id 0x%x\n", id
);
269 printf(" Buffer Size: %d\n", bufferSize
);
270 printf(" Level: %d\n", level
);
271 printf(" Double Buffer: %s\n", doubleBuffer
? "yes" : "no");
272 printf(" Stereo: %s\n", stereo
? "yes" : "no");
273 printf(" Aux Buffers: %d\n", auxBuffers
);
274 printf(" Red Size: %d\n", redSize
);
275 printf(" Green Size: %d\n", greenSize
);
276 printf(" Blue Size: %d\n", blueSize
);
277 printf(" Alpha Size: %d\n", alphaSize
);
278 printf(" Depth Size: %d\n", depthSize
);
279 printf(" Stencil Size: %d\n", stencilSize
);
280 printf(" Accum Red Size: %d\n", accumRedSize
);
281 printf(" Accum Green Size: %d\n", accumGreenSize
);
282 printf(" Accum Blue Size: %d\n", accumBlueSize
);
283 printf(" Accum Alpha Size: %d\n", accumAlphaSize
);
284 printf(" Sample Buffers: %d\n", sampleBuffers
);
285 printf(" Samples/Pixel: %d\n", samples
);
286 printf(" Drawable Types: ");
287 if (drawableType
& GLX_WINDOW_BIT
) printf("Window ");
288 if (drawableType
& GLX_PIXMAP_BIT
) printf("Pixmap ");
289 if (drawableType
& GLX_PBUFFER_BIT
) printf("PBuffer");
291 printf(" Render Types: ");
292 if (renderType
& GLX_RGBA_BIT_SGIX
) printf("RGBA ");
293 if (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) printf("CI ");
295 printf(" X Renderable: %s\n", xRenderable
? "yes" : "no");
297 printf(" Pbuffer: %s\n", pBuffer
? "yes" : "no");
298 printf(" Max Pbuffer width: %d\n", maxWidth
);
299 printf(" Max Pbuffer height: %d\n", maxHeight
);
300 printf(" Max Pbuffer pixels: %d\n", maxPixels
);
301 printf(" Optimum Pbuffer width: %d\n", optWidth
);
302 printf(" Optimum Pbuffer height: %d\n", optHeight
);
304 printf(" Float Components: %s\n", floatComponents
? "yes" : "no");
308 DestroyPbuffer(dpy
, screen
, pBuffer
);
315 CreateContext(Display
*dpy
, int screen
, FBCONFIG config
)
317 int fbcSupport
= QueryFBConfig(dpy
, screen
);
318 #if defined(GLX_VERSION_1_3)
319 if (fbcSupport
== 1) {
322 c
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, True
);
325 c
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, False
);
330 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
331 if (fbcSupport
== 2) {
333 c
= glXCreateContextWithConfigSGIX(dpy
, config
, GLX_RGBA_TYPE_SGIX
, NULL
, True
);
335 c
= glXCreateContextWithConfigSGIX(dpy
, config
, GLX_RGBA_TYPE_SGIX
, NULL
, False
);
345 DestroyContext(Display
*dpy
, GLXContext ctx
)
347 glXDestroyContext(dpy
, ctx
);
351 /* This is only used by CreatePbuffer() */
352 static int XErrorFlag
= 0;
353 static int HandleXError(Display
*dpy
, XErrorEvent
*event
)
361 * Create a Pbuffer. Use an X error handler to deal with potential
364 * Input: dpy - the X display
365 * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
366 * width, height - size of pixel buffer to request, in pixels.
367 * pbAttribs - list of optional pixel buffer attributes
368 * Return: a Pbuffer or None.
371 CreatePbuffer(Display
*dpy
, int screen
, FBCONFIG config
,
372 int width
, int height
, Bool largest
, Bool preserve
)
374 int (*oldHandler
)(Display
*, XErrorEvent
*);
375 PBUFFER pBuffer
= None
;
376 int pbSupport
= QueryPbuffers(dpy
, screen
);
378 /* Catch X protocol errors with our own error handler */
379 oldHandler
= XSetErrorHandler(HandleXError
);
382 #if defined(GLX_VERSION_1_3)
383 if (pbSupport
== 1) {
385 int attribs
[100], i
= 0;
386 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
387 attribs
[i
++] = width
;
388 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
389 attribs
[i
++] = height
;
390 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
391 attribs
[i
++] = preserve
;
392 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
393 attribs
[i
++] = largest
;
395 pBuffer
= glXCreatePbuffer(dpy
, config
, attribs
);
399 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
400 if (pbSupport
== 2) {
401 int attribs
[100], i
= 0;
402 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
403 attribs
[i
++] = preserve
;
404 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
405 attribs
[i
++] = largest
;
407 pBuffer
= glXCreateGLXPbufferSGIX(dpy
, config
, width
, height
, attribs
);
416 /* Restore original X error handler */
417 (void) XSetErrorHandler(oldHandler
);
419 /* Return pbuffer (may be None) */
420 if (!XErrorFlag
&& pBuffer
!= None
) {
421 /*printf("config %d worked!\n", i);*/
431 DestroyPbuffer(Display
*dpy
, int screen
, PBUFFER pbuffer
)
433 int pbSupport
= QueryPbuffers(dpy
, screen
);
434 #if defined(GLX_VERSION_1_3)
435 if (pbSupport
== 1) {
436 glXDestroyPbuffer(dpy
, pbuffer
);
440 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
441 if (pbSupport
== 2) {
442 glXDestroyGLXPbufferSGIX(dpy
, pbuffer
);