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.
19 * Test if we pixel buffers are available for a particular X screen.
20 * Input: dpy - the X display
21 * screen - screen number
22 * Return: 0 = pixel buffers not available.
23 * 1 = pixel buffers are available via GLX 1.3.
24 * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
27 QueryPbuffers(Display
*dpy
, int screen
)
29 #if defined(GLX_VERSION_1_3)
31 /* GLX 1.3 supports pbuffers */
32 int glxVersionMajor
, glxVersionMinor
;
33 if (!glXQueryVersion(dpy
, &glxVersionMajor
, &glxVersionMinor
)) {
34 /* GLX not available! */
37 if (glxVersionMajor
* 100 + glxVersionMinor
>= 103) {
44 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
45 /* Try the SGIX extensions */
48 extensions
= (char *) glXQueryServerString(dpy
, screen
, GLX_EXTENSIONS
);
50 !strstr(extensions
,"GLX_SGIX_fbconfig") ||
51 !strstr(extensions
,"GLX_SGIX_pbuffer")) {
64 ChooseFBConfig(Display
*dpy
, int screen
, const int attribs
[], int *nConfigs
)
66 int pbSupport
= QueryPbuffers(dpy
, screen
);
67 #if defined(GLX_VERSION_1_3)
69 return glXChooseFBConfig(dpy
, screen
, attribs
, nConfigs
);
72 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
74 return glXChooseFBConfigSGIX(dpy
, screen
, (int *) attribs
, nConfigs
);
82 GetAllFBConfigs(Display
*dpy
, int screen
, int *nConfigs
)
84 int pbSupport
= QueryPbuffers(dpy
, screen
);
85 #if defined(GLX_VERSION_1_3)
87 return glXGetFBConfigs(dpy
, screen
, nConfigs
);
90 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
92 /* this *seems* to work, but may not be perfect */
93 static int fbAttribs
[] = {
98 return glXChooseFBConfigSGIX(dpy
, screen
, fbAttribs
, nConfigs
);
106 GetVisualFromFBConfig(Display
*dpy
, int screen
, FBCONFIG config
)
108 int pbSupport
= QueryPbuffers(dpy
, screen
);
109 #if defined(GLX_VERSION_1_3)
110 if (pbSupport
== 1) {
111 return glXGetVisualFromFBConfig(dpy
, config
);
114 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
115 if (pbSupport
== 2) {
116 return glXGetVisualFromFBConfigSGIX(dpy
, config
);
124 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
125 * to query an fbconfig attribute.
128 GetFBConfigAttrib(Display
*dpy
,
129 #if defined(GLX_VERSION_1_3)
130 const GLXFBConfig config
,
131 #elif defined(GLX_SGIX_fbconfig)
132 const GLXFBConfigSGIX config
,
139 #if defined(GLX_VERSION_1_3)
140 int glxVersionMajor
, glxVersionMinor
;
141 if (glXQueryVersion(dpy
, &glxVersionMajor
, &glxVersionMinor
)
142 && glxVersionMajor
* 100 + glxVersionMinor
>= 103) {
144 if (glXGetFBConfigAttrib(dpy
, config
, attrib
, &value
) != 0) {
152 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
153 if (glXGetFBConfigAttribSGIX(dpy
, config
, attrib
, &value
) != 0) {
165 * Print parameters for a GLXFBConfig to stdout.
166 * Input: dpy - the X display
167 * screen - the X screen number
168 * fbConfig - the fbconfig handle
169 * horizFormat - if true, print in horizontal format
172 PrintFBConfigInfo(Display
*dpy
, int screen
, FBCONFIG config
, Bool horizFormat
)
175 int width
=2, height
=2;
176 int bufferSize
, level
, doubleBuffer
, stereo
, auxBuffers
;
177 int redSize
, greenSize
, blueSize
, alphaSize
;
178 int depthSize
, stencilSize
;
179 int accumRedSize
, accumBlueSize
, accumGreenSize
, accumAlphaSize
;
180 int sampleBuffers
, samples
;
181 int drawableType
, renderType
, xRenderable
, xVisual
, id
;
182 int maxWidth
, maxHeight
, maxPixels
;
183 int optWidth
, optHeight
;
186 /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
187 bufferSize
= GetFBConfigAttrib(dpy
, config
, GLX_BUFFER_SIZE
);
188 level
= GetFBConfigAttrib(dpy
, config
, GLX_LEVEL
);
189 doubleBuffer
= GetFBConfigAttrib(dpy
, config
, GLX_DOUBLEBUFFER
);
190 stereo
= GetFBConfigAttrib(dpy
, config
, GLX_STEREO
);
191 auxBuffers
= GetFBConfigAttrib(dpy
, config
, GLX_AUX_BUFFERS
);
192 redSize
= GetFBConfigAttrib(dpy
, config
, GLX_RED_SIZE
);
193 greenSize
= GetFBConfigAttrib(dpy
, config
, GLX_GREEN_SIZE
);
194 blueSize
= GetFBConfigAttrib(dpy
, config
, GLX_BLUE_SIZE
);
195 alphaSize
= GetFBConfigAttrib(dpy
, config
, GLX_ALPHA_SIZE
);
196 depthSize
= GetFBConfigAttrib(dpy
, config
, GLX_DEPTH_SIZE
);
197 stencilSize
= GetFBConfigAttrib(dpy
, config
, GLX_STENCIL_SIZE
);
198 accumRedSize
= GetFBConfigAttrib(dpy
, config
, GLX_ACCUM_RED_SIZE
);
199 accumGreenSize
= GetFBConfigAttrib(dpy
, config
, GLX_ACCUM_GREEN_SIZE
);
200 accumBlueSize
= GetFBConfigAttrib(dpy
, config
, GLX_ACCUM_BLUE_SIZE
);
201 accumAlphaSize
= GetFBConfigAttrib(dpy
, config
, GLX_ACCUM_ALPHA_SIZE
);
202 sampleBuffers
= GetFBConfigAttrib(dpy
, config
, GLX_SAMPLE_BUFFERS
);
203 samples
= GetFBConfigAttrib(dpy
, config
, GLX_SAMPLES
);
204 drawableType
= GetFBConfigAttrib(dpy
, config
, GLX_DRAWABLE_TYPE
);
205 renderType
= GetFBConfigAttrib(dpy
, config
, GLX_RENDER_TYPE
);
206 xRenderable
= GetFBConfigAttrib(dpy
, config
, GLX_X_RENDERABLE
);
207 xVisual
= GetFBConfigAttrib(dpy
, config
, GLX_X_VISUAL_TYPE
);
208 if (!xRenderable
|| !(drawableType
& GLX_WINDOW_BIT_SGIX
))
211 id
= GetFBConfigAttrib(dpy
, config
, GLX_FBCONFIG_ID
);
212 maxWidth
= GetFBConfigAttrib(dpy
, config
, GLX_MAX_PBUFFER_WIDTH
);
213 maxHeight
= GetFBConfigAttrib(dpy
, config
, GLX_MAX_PBUFFER_HEIGHT
);
214 maxPixels
= GetFBConfigAttrib(dpy
, config
, GLX_MAX_PBUFFER_PIXELS
);
215 #if defined(GLX_SGIX_pbuffer)
216 optWidth
= GetFBConfigAttrib(dpy
, config
, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX
);
217 optHeight
= GetFBConfigAttrib(dpy
, config
, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX
);
219 optWidth
= optHeight
= 0;
221 #if defined(GLX_NV_float_buffer)
222 floatComponents
= GetFBConfigAttrib(dpy
, config
, GLX_FLOAT_COMPONENTS_NV
);
225 /* See if we can create a pbuffer with this config */
226 pBuffer
= CreatePbuffer(dpy
, screen
, config
, width
, height
, False
, False
);
229 printf("0x%03x ", id
);
230 if (xVisual
==GLX_STATIC_GRAY
) printf("StaticGray ");
231 else if (xVisual
==GLX_GRAY_SCALE
) printf("GrayScale ");
232 else if (xVisual
==GLX_STATIC_COLOR
) printf("StaticColor ");
233 else if (xVisual
==GLX_PSEUDO_COLOR
) printf("PseudoColor ");
234 else if (xVisual
==GLX_TRUE_COLOR
) printf("TrueColor ");
235 else if (xVisual
==GLX_DIRECT_COLOR
) printf("DirectColor ");
236 else printf(" -none- ");
237 printf(" %3d %3d %s %s %s %2s ", bufferSize
, level
,
238 (renderType
& GLX_RGBA_BIT_SGIX
) ? "y" : "n",
239 (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) ? "y" : "n",
240 doubleBuffer
? "y" : "n",
242 printf("%2d %2d %2d %2d ", redSize
, greenSize
, blueSize
, alphaSize
);
243 printf("%2d %2d ", depthSize
, stencilSize
);
244 printf("%2d %2d %2d %2d", accumRedSize
, accumGreenSize
, accumBlueSize
,
246 printf(" %2d %2d", sampleBuffers
, samples
);
247 printf(" %s %c", pBuffer
? "y" : "n",
248 "ny"[floatComponents
]);
252 printf("Id 0x%x\n", id
);
253 printf(" Buffer Size: %d\n", bufferSize
);
254 printf(" Level: %d\n", level
);
255 printf(" Double Buffer: %s\n", doubleBuffer
? "yes" : "no");
256 printf(" Stereo: %s\n", stereo
? "yes" : "no");
257 printf(" Aux Buffers: %d\n", auxBuffers
);
258 printf(" Red Size: %d\n", redSize
);
259 printf(" Green Size: %d\n", greenSize
);
260 printf(" Blue Size: %d\n", blueSize
);
261 printf(" Alpha Size: %d\n", alphaSize
);
262 printf(" Depth Size: %d\n", depthSize
);
263 printf(" Stencil Size: %d\n", stencilSize
);
264 printf(" Accum Red Size: %d\n", accumRedSize
);
265 printf(" Accum Green Size: %d\n", accumGreenSize
);
266 printf(" Accum Blue Size: %d\n", accumBlueSize
);
267 printf(" Accum Alpha Size: %d\n", accumAlphaSize
);
268 printf(" Sample Buffers: %d\n", sampleBuffers
);
269 printf(" Samples/Pixel: %d\n", samples
);
270 printf(" Drawable Types: ");
271 if (drawableType
& GLX_WINDOW_BIT
) printf("Window ");
272 if (drawableType
& GLX_PIXMAP_BIT
) printf("Pixmap ");
273 if (drawableType
& GLX_PBUFFER_BIT
) printf("PBuffer");
275 printf(" Render Types: ");
276 if (renderType
& GLX_RGBA_BIT_SGIX
) printf("RGBA ");
277 if (renderType
& GLX_COLOR_INDEX_BIT_SGIX
) printf("CI ");
279 printf(" X Renderable: %s\n", xRenderable
? "yes" : "no");
281 printf(" Pbuffer: %s\n", pBuffer
? "yes" : "no");
282 printf(" Max Pbuffer width: %d\n", maxWidth
);
283 printf(" Max Pbuffer height: %d\n", maxHeight
);
284 printf(" Max Pbuffer pixels: %d\n", maxPixels
);
285 printf(" Optimum Pbuffer width: %d\n", optWidth
);
286 printf(" Optimum Pbuffer height: %d\n", optHeight
);
288 printf(" Float Components: %s\n", floatComponents
? "yes" : "no");
292 DestroyPbuffer(dpy
, screen
, pBuffer
);
298 /* This is only used by CreatePbuffer() */
299 static int XErrorFlag
= 0;
300 static int HandleXError(Display
*dpy
, XErrorEvent
*event
)
308 * Create a Pbuffer. Use an X error handler to deal with potential
311 * Input: dpy - the X display
312 * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
313 * width, height - size of pixel buffer to request, in pixels.
314 * pbAttribs - list of optional pixel buffer attributes
315 * Return: a Pbuffer or None.
318 CreatePbuffer(Display
*dpy
, int screen
, FBCONFIG config
,
319 int width
, int height
, Bool largest
, Bool preserve
)
321 int (*oldHandler
)(Display
*, XErrorEvent
*);
322 PBUFFER pBuffer
= None
;
323 int pbSupport
= QueryPbuffers(dpy
, screen
);
325 /* Catch X protocol errors with our own error handler */
326 oldHandler
= XSetErrorHandler(HandleXError
);
329 #if defined(GLX_VERSION_1_3)
330 if (pbSupport
== 1) {
332 int attribs
[100], i
= 0;
333 attribs
[i
++] = GLX_PBUFFER_WIDTH
;
334 attribs
[i
++] = width
;
335 attribs
[i
++] = GLX_PBUFFER_HEIGHT
;
336 attribs
[i
++] = height
;
337 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
338 attribs
[i
++] = preserve
;
339 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
340 attribs
[i
++] = largest
;
342 pBuffer
= glXCreatePbuffer(dpy
, config
, attribs
);
346 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
347 if (pbSupport
== 2) {
348 int attribs
[100], i
= 0;
349 attribs
[i
++] = GLX_PRESERVED_CONTENTS
;
350 attribs
[i
++] = preserve
;
351 attribs
[i
++] = GLX_LARGEST_PBUFFER
;
352 attribs
[i
++] = largest
;
354 pBuffer
= glXCreateGLXPbufferSGIX(dpy
, config
, width
, height
, attribs
);
362 /* Restore original X error handler */
363 (void) XSetErrorHandler(oldHandler
);
365 /* Return pbuffer (may be None) */
366 if (!XErrorFlag
&& pBuffer
!= None
) {
367 /*printf("config %d worked!\n", i);*/
377 DestroyPbuffer(Display
*dpy
, int screen
, PBUFFER pbuffer
)
379 int pbSupport
= QueryPbuffers(dpy
, screen
);
380 #if defined(GLX_VERSION_1_3)
381 if (pbSupport
== 1) {
382 glXDestroyPbuffer(dpy
, pbuffer
);
386 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
387 if (pbSupport
== 2) {
388 glXDestroyGLXPbufferSGIX(dpy
, pbuffer
);