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 = pixel buffers not available.
22 * 1 = pixel buffers are available via GLX 1.3.
23 * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
26 QueryPbuffers(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 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
44 /* Try the SGIX extensions */
47 extensions
= (char *) glXQueryServerString(dpy
, screen
, GLX_EXTENSIONS
);
49 !strstr(extensions
,"GLX_SGIX_fbconfig") ||
50 !strstr(extensions
,"GLX_SGIX_pbuffer")) {
63 ChooseFBConfig(Display
*dpy
, int screen
, const int attribs
[], int *nConfigs
)
65 int pbSupport
= QueryPbuffers(dpy
, screen
);
66 #if defined(GLX_VERSION_1_3)
68 return glXChooseFBConfig(dpy
, screen
, attribs
, nConfigs
);
71 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
73 return glXChooseFBConfigSGIX(dpy
, screen
, (int *) attribs
, nConfigs
);
81 GetAllFBConfigs(Display
*dpy
, int screen
, int *nConfigs
)
83 int pbSupport
= QueryPbuffers(dpy
, screen
);
84 #if defined(GLX_VERSION_1_3)
86 return glXGetFBConfigs(dpy
, screen
, nConfigs
);
89 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
91 /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
92 * of all available configurations.
94 return glXChooseFBConfigSGIX(dpy
, screen
, NULL
, nConfigs
);
102 GetVisualFromFBConfig(Display
*dpy
, int screen
, FBCONFIG config
)
104 int pbSupport
= QueryPbuffers(dpy
, screen
);
105 #if defined(GLX_VERSION_1_3)
106 if (pbSupport
== 1) {
107 return glXGetVisualFromFBConfig(dpy
, config
);
110 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
111 if (pbSupport
== 2) {
112 return glXGetVisualFromFBConfigSGIX(dpy
, config
);
120 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
121 * to query an fbconfig attribute.
124 GetFBConfigAttrib(Display
*dpy
, int screen
,
125 #if defined(GLX_VERSION_1_3)
126 const GLXFBConfig config
,
127 #elif defined(GLX_SGIX_fbconfig)
128 const GLXFBConfigSGIX config
,
133 int pbSupport
= QueryPbuffers(dpy
, screen
);
136 #if defined(GLX_VERSION_1_3)
137 if (pbSupport
== 1) {
139 if (glXGetFBConfigAttrib(dpy
, config
, attrib
, &value
) != 0) {
147 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
148 if (pbSupport
== 2) {
149 if (glXGetFBConfigAttribSGIX(dpy
, config
, attrib
, &value
) != 0) {
162 * Print parameters for a GLXFBConfig to stdout.
163 * Input: dpy - the X display
164 * screen - the X screen number
165 * fbConfig - the fbconfig handle
166 * horizFormat - if true, print in horizontal format
169 PrintFBConfigInfo(Display
*dpy
, int screen
, FBCONFIG config
, Bool horizFormat
)
172 int width
=2, height
=2;
173 int bufferSize
, level
, doubleBuffer
, stereo
, auxBuffers
;
174 int redSize
, greenSize
, blueSize
, alphaSize
;
175 int depthSize
, stencilSize
;
176 int accumRedSize
, accumBlueSize
, accumGreenSize
, accumAlphaSize
;
177 int sampleBuffers
, samples
;
178 int drawableType
, renderType
, xRenderable
, xVisual
, id
;
179 int maxWidth
, maxHeight
, maxPixels
;
180 int optWidth
, optHeight
;
181 int floatComponents
= 0;
183 /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
184 bufferSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_BUFFER_SIZE
);
185 level
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_LEVEL
);
186 doubleBuffer
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DOUBLEBUFFER
);
187 stereo
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_STEREO
);
188 auxBuffers
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_AUX_BUFFERS
);
189 redSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_RED_SIZE
);
190 greenSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_GREEN_SIZE
);
191 blueSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_BLUE_SIZE
);
192 alphaSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ALPHA_SIZE
);
193 depthSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DEPTH_SIZE
);
194 stencilSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_STENCIL_SIZE
);
195 accumRedSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_RED_SIZE
);
196 accumGreenSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_GREEN_SIZE
);
197 accumBlueSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_BLUE_SIZE
);
198 accumAlphaSize
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_ACCUM_ALPHA_SIZE
);
199 sampleBuffers
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_SAMPLE_BUFFERS
);
200 samples
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_SAMPLES
);
201 drawableType
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_DRAWABLE_TYPE
);
202 renderType
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_RENDER_TYPE
);
203 xRenderable
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_X_RENDERABLE
);
204 xVisual
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_X_VISUAL_TYPE
);
205 if (!xRenderable
|| !(drawableType
& GLX_WINDOW_BIT_SGIX
))
208 id
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_FBCONFIG_ID
);
209 maxWidth
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_WIDTH
);
210 maxHeight
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_HEIGHT
);
211 maxPixels
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_MAX_PBUFFER_PIXELS
);
212 #if defined(GLX_SGIX_pbuffer)
213 optWidth
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
);
214 optHeight
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
);
216 optWidth
= optHeight
= 0;
218 #if defined(GLX_NV_float_buffer)
219 floatComponents
= GetFBConfigAttrib(dpy
, screen
, config
, GLX_FLOAT_COMPONENTS_NV
);
222 /* See if we can create a pbuffer with this config */
223 pBuffer
= CreatePbuffer(dpy
, screen
, config
, width
, height
, False
, False
);
226 printf("0x%-9x ", id
);
227 if (xVisual
==GLX_STATIC_GRAY
) printf("StaticGray ");
228 else if (xVisual
==GLX_GRAY_SCALE
) printf("GrayScale ");
229 else if (xVisual
==GLX_STATIC_COLOR
) printf("StaticColor ");
230 else if (xVisual
==GLX_PSEUDO_COLOR
) printf("PseudoColor ");
231 else if (xVisual
==GLX_TRUE_COLOR
) printf("TrueColor ");
232 else if (xVisual
==GLX_DIRECT_COLOR
) printf("DirectColor ");
233 else printf(" -none- ");
234 printf(" %3d %3d %s %s %s %2s ", bufferSize
, level
,
235 (renderType
& GLX_RGBA_BIT_SGIX
) ? "y" : ".",
236 (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) ? "y" : ".",
237 doubleBuffer
? "y" : ".",
239 printf("%2d %2d %2d %2d ", redSize
, greenSize
, blueSize
, alphaSize
);
240 printf("%2d %2d ", depthSize
, stencilSize
);
241 printf("%2d %2d %2d %2d", accumRedSize
, accumGreenSize
, accumBlueSize
,
243 printf(" %2d %2d", sampleBuffers
, samples
);
244 printf(" %s %c", pBuffer
? "y" : ".",
245 ".y"[floatComponents
]);
249 printf("Id 0x%x\n", id
);
250 printf(" Buffer Size: %d\n", bufferSize
);
251 printf(" Level: %d\n", level
);
252 printf(" Double Buffer: %s\n", doubleBuffer
? "yes" : "no");
253 printf(" Stereo: %s\n", stereo
? "yes" : "no");
254 printf(" Aux Buffers: %d\n", auxBuffers
);
255 printf(" Red Size: %d\n", redSize
);
256 printf(" Green Size: %d\n", greenSize
);
257 printf(" Blue Size: %d\n", blueSize
);
258 printf(" Alpha Size: %d\n", alphaSize
);
259 printf(" Depth Size: %d\n", depthSize
);
260 printf(" Stencil Size: %d\n", stencilSize
);
261 printf(" Accum Red Size: %d\n", accumRedSize
);
262 printf(" Accum Green Size: %d\n", accumGreenSize
);
263 printf(" Accum Blue Size: %d\n", accumBlueSize
);
264 printf(" Accum Alpha Size: %d\n", accumAlphaSize
);
265 printf(" Sample Buffers: %d\n", sampleBuffers
);
266 printf(" Samples/Pixel: %d\n", samples
);
267 printf(" Drawable Types: ");
268 if (drawableType
& GLX_WINDOW_BIT
) printf("Window ");
269 if (drawableType
& GLX_PIXMAP_BIT
) printf("Pixmap ");
270 if (drawableType
& GLX_PBUFFER_BIT
) printf("PBuffer");
272 printf(" Render Types: ");
273 if (renderType
& GLX_RGBA_BIT_SGIX
) printf("RGBA ");
274 if (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) printf("CI ");
276 printf(" X Renderable: %s\n", xRenderable
? "yes" : "no");
278 printf(" Pbuffer: %s\n", pBuffer
? "yes" : "no");
279 printf(" Max Pbuffer width: %d\n", maxWidth
);
280 printf(" Max Pbuffer height: %d\n", maxHeight
);
281 printf(" Max Pbuffer pixels: %d\n", maxPixels
);
282 printf(" Optimum Pbuffer width: %d\n", optWidth
);
283 printf(" Optimum Pbuffer height: %d\n", optHeight
);
285 printf(" Float Components: %s\n", floatComponents
? "yes" : "no");
289 DestroyPbuffer(dpy
, screen
, pBuffer
);
296 CreateContext(Display
*dpy
, int screen
, FBCONFIG config
)
298 int pbSupport
= QueryPbuffers(dpy
, screen
);
299 #if defined(GLX_VERSION_1_3)
300 if (pbSupport
== 1) {
303 c
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, True
);
306 c
= glXCreateNewContext(dpy
, config
, GLX_RGBA_TYPE
, NULL
, False
);
311 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
312 if (pbSupport
== 2) {
314 c
= glXCreateContextWithConfigSGIX(dpy
, config
, GLX_RGBA_TYPE_SGIX
, NULL
, True
);
316 c
= glXCreateContextWithConfigSGIX(dpy
, config
, GLX_RGBA_TYPE_SGIX
, NULL
, False
);
326 DestroyContext(Display
*dpy
, GLXContext ctx
)
328 glXDestroyContext(dpy
, ctx
);
332 /* This is only used by CreatePbuffer() */
333 static int XErrorFlag
= 0;
334 static int HandleXError(Display
*dpy
, XErrorEvent
*event
)
342 * Create a Pbuffer. Use an X error handler to deal with potential
345 * Input: dpy - the X display
346 * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
347 * width, height - size of pixel buffer to request, in pixels.
348 * pbAttribs - list of optional pixel buffer attributes
349 * Return: a Pbuffer or None.
352 CreatePbuffer(Display
*dpy
, int screen
, FBCONFIG config
,
353 int width
, int height
, Bool largest
, Bool preserve
)
355 int (*oldHandler
)(Display
*, XErrorEvent
*);
356 PBUFFER pBuffer
= None
;
357 int pbSupport
= QueryPbuffers(dpy
, screen
);
359 /* Catch X protocol errors with our own error handler */
360 oldHandler
= XSetErrorHandler(HandleXError
);
363 #if defined(GLX_VERSION_1_3)
364 if (pbSupport
== 1) {
366 int attribs
[100], i
= 0;
367 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
368 attribs
[i
++] = width
;
369 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
370 attribs
[i
++] = height
;
371 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
372 attribs
[i
++] = preserve
;
373 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
374 attribs
[i
++] = largest
;
376 pBuffer
= glXCreatePbuffer(dpy
, config
, attribs
);
380 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
381 if (pbSupport
== 2) {
382 int attribs
[100], i
= 0;
383 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
384 attribs
[i
++] = preserve
;
385 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
386 attribs
[i
++] = largest
;
388 pBuffer
= glXCreateGLXPbufferSGIX(dpy
, config
, width
, height
, attribs
);
396 /* Restore original X error handler */
397 (void) XSetErrorHandler(oldHandler
);
399 /* Return pbuffer (may be None) */
400 if (!XErrorFlag
&& pBuffer
!= None
) {
401 /*printf("config %d worked!\n", i);*/
411 DestroyPbuffer(Display
*dpy
, int screen
, PBUFFER pbuffer
)
413 int pbSupport
= QueryPbuffers(dpy
, screen
);
414 #if defined(GLX_VERSION_1_3)
415 if (pbSupport
== 1) {
416 glXDestroyPbuffer(dpy
, pbuffer
);
420 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
421 if (pbSupport
== 2) {
422 glXDestroyGLXPbufferSGIX(dpy
, pbuffer
);