blob: 479abc983caa048966f0ee56d5c075f3ba57b3b8 [file] [log] [blame]
Brian Paul21666e32002-10-05 18:30:13 +00001
2/*
3 * OpenGL pbuffers utility functions.
4 *
5 * Brian Paul
Brian Paulf72e4422005-01-04 00:58:29 +00006 * Original code: April 1997
Brian Paul21666e32002-10-05 18:30:13 +00007 * Updated on 5 October 2002
Brian Paulf72e4422005-01-04 00:58:29 +00008 * Updated again on 3 January 2005 to use GLX 1.3 functions in preference
9 * to the GLX_SGIX_fbconfig/pbuffer extensions.
Brian Paul21666e32002-10-05 18:30:13 +000010 */
11
12
13#include <stdio.h>
14#include <string.h>
15#include "pbutil.h"
16
17
Brian Paulf72e4422005-01-04 00:58:29 +000018/**
Brian Paul21666e32002-10-05 18:30:13 +000019 * 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.
Brian Paulf72e4422005-01-04 00:58:29 +000023 * 1 = pixel buffers are available via GLX 1.3.
24 * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
Brian Paul21666e32002-10-05 18:30:13 +000025 */
26int
27QueryPbuffers(Display *dpy, int screen)
28{
Brian Paulf72e4422005-01-04 00:58:29 +000029#if defined(GLX_VERSION_1_3)
30 {
31 /* GLX 1.3 supports pbuffers */
32 int glxVersionMajor, glxVersionMinor;
33 if (!glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)) {
34 /* GLX not available! */
35 return 0;
36 }
37 if (glxVersionMajor * 100 + glxVersionMinor >= 103) {
38 return 1;
39 }
40 /* fall-through */
Brian Paul21666e32002-10-05 18:30:13 +000041 }
Brian Paul21666e32002-10-05 18:30:13 +000042#endif
Brian Paulf72e4422005-01-04 00:58:29 +000043
44#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
45 /* Try the SGIX extensions */
46 {
47 char *extensions;
48 extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
49 if (!extensions ||
50 !strstr(extensions,"GLX_SGIX_fbconfig") ||
51 !strstr(extensions,"GLX_SGIX_pbuffer")) {
52 return 0;
53 }
54 return 2;
55 }
56#endif
57
58 return 0;
Brian Paul21666e32002-10-05 18:30:13 +000059}
60
61
62
Brian Paulf72e4422005-01-04 00:58:29 +000063FBCONFIG *
64ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
65{
66 int pbSupport = QueryPbuffers(dpy, screen);
67#if defined(GLX_VERSION_1_3)
68 if (pbSupport == 1) {
69 return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
70 }
71#endif
72#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
73 if (pbSupport == 2) {
74 return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
75 }
76#endif
77 return NULL;
78}
Brian Paul21666e32002-10-05 18:30:13 +000079
80
Brian Paulba5ceda2005-01-07 01:17:42 +000081FBCONFIG *
82GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
83{
84 int pbSupport = QueryPbuffers(dpy, screen);
85#if defined(GLX_VERSION_1_3)
86 if (pbSupport == 1) {
87 return glXGetFBConfigs(dpy, screen, nConfigs);
88 }
89#endif
90#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
91 if (pbSupport == 2) {
Brian Paulc3984fc2005-04-06 22:40:39 +000092 /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
93 * of all available configurations.
94 */
95 return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs);
Brian Paulba5ceda2005-01-07 01:17:42 +000096 }
97#endif
98 return NULL;
99}
100
Brian Paulf72e4422005-01-04 00:58:29 +0000101
102XVisualInfo *
103GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
104{
105 int pbSupport = QueryPbuffers(dpy, screen);
106#if defined(GLX_VERSION_1_3)
107 if (pbSupport == 1) {
108 return glXGetVisualFromFBConfig(dpy, config);
109 }
110#endif
111#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
112 if (pbSupport == 2) {
113 return glXGetVisualFromFBConfigSGIX(dpy, config);
114 }
115#endif
116 return NULL;
117}
118
119
120/**
121 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
122 * to query an fbconfig attribute.
123 */
124static int
Brian Paulff53a4e2005-01-10 23:15:59 +0000125GetFBConfigAttrib(Display *dpy, int screen,
Brian Paulf72e4422005-01-04 00:58:29 +0000126#if defined(GLX_VERSION_1_3)
127 const GLXFBConfig config,
128#elif defined(GLX_SGIX_fbconfig)
129 const GLXFBConfigSGIX config,
130#endif
131 int attrib
132 )
133{
Brian Paulff53a4e2005-01-10 23:15:59 +0000134 int pbSupport = QueryPbuffers(dpy, screen);
135 int value = 0;
Brian Paulf72e4422005-01-04 00:58:29 +0000136
137#if defined(GLX_VERSION_1_3)
Brian Paulff53a4e2005-01-10 23:15:59 +0000138 if (pbSupport == 1) {
Brian Paulf72e4422005-01-04 00:58:29 +0000139 /* ok */
140 if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
141 value = 0;
142 }
143 return value;
144 }
145 /* fall-through */
146#endif
147
148#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
Brian Paulff53a4e2005-01-10 23:15:59 +0000149 if (pbSupport == 2) {
150 if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
151 value = 0;
152 }
153 return value;
Brian Paulf72e4422005-01-04 00:58:29 +0000154 }
Brian Paulf72e4422005-01-04 00:58:29 +0000155#endif
156
Brian Paulff53a4e2005-01-10 23:15:59 +0000157 return value;
Brian Paulf72e4422005-01-04 00:58:29 +0000158}
159
160
161
162/**
Brian Paul21666e32002-10-05 18:30:13 +0000163 * Print parameters for a GLXFBConfig to stdout.
164 * Input: dpy - the X display
Brian Paulf72e4422005-01-04 00:58:29 +0000165 * screen - the X screen number
Brian Paul21666e32002-10-05 18:30:13 +0000166 * fbConfig - the fbconfig handle
167 * horizFormat - if true, print in horizontal format
168 */
169void
Brian Paulf72e4422005-01-04 00:58:29 +0000170PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
Brian Paul21666e32002-10-05 18:30:13 +0000171{
Brian Paulf72e4422005-01-04 00:58:29 +0000172 PBUFFER pBuffer;
Brian Paul21666e32002-10-05 18:30:13 +0000173 int width=2, height=2;
174 int bufferSize, level, doubleBuffer, stereo, auxBuffers;
175 int redSize, greenSize, blueSize, alphaSize;
176 int depthSize, stencilSize;
177 int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
178 int sampleBuffers, samples;
179 int drawableType, renderType, xRenderable, xVisual, id;
180 int maxWidth, maxHeight, maxPixels;
181 int optWidth, optHeight;
Brian Paulff53a4e2005-01-10 23:15:59 +0000182 int floatComponents = 0;
Brian Paul21666e32002-10-05 18:30:13 +0000183
Brian Paulf72e4422005-01-04 00:58:29 +0000184 /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
Brian Paulff53a4e2005-01-10 23:15:59 +0000185 bufferSize = GetFBConfigAttrib(dpy, screen, config, GLX_BUFFER_SIZE);
186 level = GetFBConfigAttrib(dpy, screen, config, GLX_LEVEL);
187 doubleBuffer = GetFBConfigAttrib(dpy, screen, config, GLX_DOUBLEBUFFER);
188 stereo = GetFBConfigAttrib(dpy, screen, config, GLX_STEREO);
189 auxBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_AUX_BUFFERS);
190 redSize = GetFBConfigAttrib(dpy, screen, config, GLX_RED_SIZE);
191 greenSize = GetFBConfigAttrib(dpy, screen, config, GLX_GREEN_SIZE);
192 blueSize = GetFBConfigAttrib(dpy, screen, config, GLX_BLUE_SIZE);
193 alphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ALPHA_SIZE);
194 depthSize = GetFBConfigAttrib(dpy, screen, config, GLX_DEPTH_SIZE);
195 stencilSize = GetFBConfigAttrib(dpy, screen, config, GLX_STENCIL_SIZE);
196 accumRedSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_RED_SIZE);
197 accumGreenSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_GREEN_SIZE);
198 accumBlueSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_BLUE_SIZE);
199 accumAlphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_ALPHA_SIZE);
200 sampleBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLE_BUFFERS);
201 samples = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLES);
202 drawableType = GetFBConfigAttrib(dpy, screen, config, GLX_DRAWABLE_TYPE);
203 renderType = GetFBConfigAttrib(dpy, screen, config, GLX_RENDER_TYPE);
204 xRenderable = GetFBConfigAttrib(dpy, screen, config, GLX_X_RENDERABLE);
205 xVisual = GetFBConfigAttrib(dpy, screen, config, GLX_X_VISUAL_TYPE);
Brian Paul21666e32002-10-05 18:30:13 +0000206 if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
207 xVisual = -1;
Brian Paul21666e32002-10-05 18:30:13 +0000208
Brian Paulff53a4e2005-01-10 23:15:59 +0000209 id = GetFBConfigAttrib(dpy, screen, config, GLX_FBCONFIG_ID);
210 maxWidth = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_WIDTH);
211 maxHeight = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_HEIGHT);
212 maxPixels = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_PIXELS);
Brian Paulf72e4422005-01-04 00:58:29 +0000213#if defined(GLX_SGIX_pbuffer)
Brian Paulff53a4e2005-01-10 23:15:59 +0000214 optWidth = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX);
215 optHeight = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX);
Brian Paulf72e4422005-01-04 00:58:29 +0000216#else
217 optWidth = optHeight = 0;
218#endif
219#if defined(GLX_NV_float_buffer)
Brian Paulff53a4e2005-01-10 23:15:59 +0000220 floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV);
Brian Paulf72e4422005-01-04 00:58:29 +0000221#endif
Brian Paul21666e32002-10-05 18:30:13 +0000222
Brian Paulf72e4422005-01-04 00:58:29 +0000223 /* See if we can create a pbuffer with this config */
224 pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
Brian Paul21666e32002-10-05 18:30:13 +0000225
226 if (horizFormat) {
Brian Paulff53a4e2005-01-10 23:15:59 +0000227 printf("0x%-9x ", id);
Brian Paul21666e32002-10-05 18:30:13 +0000228 if (xVisual==GLX_STATIC_GRAY) printf("StaticGray ");
229 else if (xVisual==GLX_GRAY_SCALE) printf("GrayScale ");
230 else if (xVisual==GLX_STATIC_COLOR) printf("StaticColor ");
231 else if (xVisual==GLX_PSEUDO_COLOR) printf("PseudoColor ");
232 else if (xVisual==GLX_TRUE_COLOR) printf("TrueColor ");
233 else if (xVisual==GLX_DIRECT_COLOR) printf("DirectColor ");
234 else printf(" -none- ");
235 printf(" %3d %3d %s %s %s %2s ", bufferSize, level,
Brian Paulff53a4e2005-01-10 23:15:59 +0000236 (renderType & GLX_RGBA_BIT_SGIX) ? "y" : ".",
237 (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : ".",
238 doubleBuffer ? "y" : ".",
239 stereo ? "y" : ".");
Brian Paul21666e32002-10-05 18:30:13 +0000240 printf("%2d %2d %2d %2d ", redSize, greenSize, blueSize, alphaSize);
241 printf("%2d %2d ", depthSize, stencilSize);
242 printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize,
243 accumAlphaSize);
244 printf(" %2d %2d", sampleBuffers, samples);
Brian Paulff53a4e2005-01-10 23:15:59 +0000245 printf(" %s %c", pBuffer ? "y" : ".",
246 ".y"[floatComponents]);
Brian Paul21666e32002-10-05 18:30:13 +0000247 printf("\n");
248 }
249 else {
250 printf("Id 0x%x\n", id);
251 printf(" Buffer Size: %d\n", bufferSize);
252 printf(" Level: %d\n", level);
253 printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
254 printf(" Stereo: %s\n", stereo ? "yes" : "no");
255 printf(" Aux Buffers: %d\n", auxBuffers);
256 printf(" Red Size: %d\n", redSize);
257 printf(" Green Size: %d\n", greenSize);
258 printf(" Blue Size: %d\n", blueSize);
259 printf(" Alpha Size: %d\n", alphaSize);
260 printf(" Depth Size: %d\n", depthSize);
261 printf(" Stencil Size: %d\n", stencilSize);
262 printf(" Accum Red Size: %d\n", accumRedSize);
263 printf(" Accum Green Size: %d\n", accumGreenSize);
264 printf(" Accum Blue Size: %d\n", accumBlueSize);
265 printf(" Accum Alpha Size: %d\n", accumAlphaSize);
266 printf(" Sample Buffers: %d\n", sampleBuffers);
267 printf(" Samples/Pixel: %d\n", samples);
268 printf(" Drawable Types: ");
Brian Paulf72e4422005-01-04 00:58:29 +0000269 if (drawableType & GLX_WINDOW_BIT) printf("Window ");
270 if (drawableType & GLX_PIXMAP_BIT) printf("Pixmap ");
271 if (drawableType & GLX_PBUFFER_BIT) printf("PBuffer");
Brian Paul21666e32002-10-05 18:30:13 +0000272 printf("\n");
273 printf(" Render Types: ");
274 if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
275 if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
276 printf("\n");
277 printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
Brian Paulf72e4422005-01-04 00:58:29 +0000278
Brian Paul21666e32002-10-05 18:30:13 +0000279 printf(" Pbuffer: %s\n", pBuffer ? "yes" : "no");
Brian Paulf72e4422005-01-04 00:58:29 +0000280 printf(" Max Pbuffer width: %d\n", maxWidth);
281 printf(" Max Pbuffer height: %d\n", maxHeight);
282 printf(" Max Pbuffer pixels: %d\n", maxPixels);
283 printf(" Optimum Pbuffer width: %d\n", optWidth);
284 printf(" Optimum Pbuffer height: %d\n", optHeight);
285
286 printf(" Float Components: %s\n", floatComponents ? "yes" : "no");
Brian Paul21666e32002-10-05 18:30:13 +0000287 }
288
289 if (pBuffer) {
Brian Paulf72e4422005-01-04 00:58:29 +0000290 DestroyPbuffer(dpy, screen, pBuffer);
Brian Paul21666e32002-10-05 18:30:13 +0000291 }
292}
293
294
295
296/* This is only used by CreatePbuffer() */
297static int XErrorFlag = 0;
Brian Paulf72e4422005-01-04 00:58:29 +0000298static int HandleXError(Display *dpy, XErrorEvent *event)
Brian Paul21666e32002-10-05 18:30:13 +0000299{
300 XErrorFlag = 1;
301 return 0;
302}
303
304
Brian Paulf72e4422005-01-04 00:58:29 +0000305/**
Brian Paul18a94902004-02-02 15:38:26 +0000306 * Create a Pbuffer. Use an X error handler to deal with potential
307 * BadAlloc errors.
Brian Paul21666e32002-10-05 18:30:13 +0000308 *
309 * Input: dpy - the X display
310 * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
311 * width, height - size of pixel buffer to request, in pixels.
Brian Paulf72e4422005-01-04 00:58:29 +0000312 * pbAttribs - list of optional pixel buffer attributes
313 * Return: a Pbuffer or None.
Brian Paul21666e32002-10-05 18:30:13 +0000314 */
Brian Paulf72e4422005-01-04 00:58:29 +0000315PBUFFER
316CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
317 int width, int height, Bool largest, Bool preserve)
Brian Paul21666e32002-10-05 18:30:13 +0000318{
Brian Paulf72e4422005-01-04 00:58:29 +0000319 int (*oldHandler)(Display *, XErrorEvent *);
320 PBUFFER pBuffer = None;
321 int pbSupport = QueryPbuffers(dpy, screen);
Brian Paul21666e32002-10-05 18:30:13 +0000322
323 /* Catch X protocol errors with our own error handler */
Brian Paulf72e4422005-01-04 00:58:29 +0000324 oldHandler = XSetErrorHandler(HandleXError);
Brian Paul21666e32002-10-05 18:30:13 +0000325 XErrorFlag = 0;
Brian Paulf72e4422005-01-04 00:58:29 +0000326
327#if defined(GLX_VERSION_1_3)
328 if (pbSupport == 1) {
329 /* GLX 1.3 */
330 int attribs[100], i = 0;
331 attribs[i++] = GLX_PBUFFER_WIDTH;
332 attribs[i++] = width;
333 attribs[i++] = GLX_PBUFFER_HEIGHT;
334 attribs[i++] = height;
335 attribs[i++] = GLX_PRESERVED_CONTENTS;
336 attribs[i++] = preserve;
337 attribs[i++] = GLX_LARGEST_PBUFFER;
338 attribs[i++] = largest;
339 attribs[i++] = 0;
340 pBuffer = glXCreatePbuffer(dpy, config, attribs);
341 }
342 else
343#endif
344#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
345 if (pbSupport == 2) {
346 int attribs[100], i = 0;
347 attribs[i++] = GLX_PRESERVED_CONTENTS;
348 attribs[i++] = preserve;
349 attribs[i++] = GLX_LARGEST_PBUFFER;
350 attribs[i++] = largest;
351 attribs[i++] = 0;
352 pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
353 }
354 else
355#endif
356 {
357 pBuffer = None;
358 }
Brian Paul21666e32002-10-05 18:30:13 +0000359
360 /* Restore original X error handler */
Brian Paulf72e4422005-01-04 00:58:29 +0000361 (void) XSetErrorHandler(oldHandler);
Brian Paul21666e32002-10-05 18:30:13 +0000362
363 /* Return pbuffer (may be None) */
Brian Paulf72e4422005-01-04 00:58:29 +0000364 if (!XErrorFlag && pBuffer != None) {
Brian Paul21666e32002-10-05 18:30:13 +0000365 /*printf("config %d worked!\n", i);*/
366 return pBuffer;
367 }
368 else {
369 return None;
370 }
371}
372
373
Brian Paulf72e4422005-01-04 00:58:29 +0000374void
375DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
376{
377 int pbSupport = QueryPbuffers(dpy, screen);
378#if defined(GLX_VERSION_1_3)
379 if (pbSupport == 1) {
380 glXDestroyPbuffer(dpy, pbuffer);
381 return;
382 }
383#endif
384#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
385 if (pbSupport == 2) {
386 glXDestroyGLXPbufferSGIX(dpy, pbuffer);
387 return;
388 }
389#endif
390}