fix logic error, typos
[mesa.git] / progs / xdemos / pbutil.c
1
2 /*
3 * OpenGL pbuffers utility functions.
4 *
5 * Brian Paul
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.
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include "pbutil.h"
15
16
17 /**
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.
24 */
25 int
26 QueryPbuffers(Display *dpy, int screen)
27 {
28 #if defined(GLX_VERSION_1_3)
29 {
30 /* GLX 1.3 supports pbuffers */
31 int glxVersionMajor, glxVersionMinor;
32 if (!glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)) {
33 /* GLX not available! */
34 return 0;
35 }
36 if (glxVersionMajor * 100 + glxVersionMinor >= 103) {
37 return 1;
38 }
39 /* fall-through */
40 }
41 #endif
42
43 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
44 /* Try the SGIX extensions */
45 {
46 char *extensions;
47 extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
48 if (!extensions ||
49 !strstr(extensions,"GLX_SGIX_fbconfig") ||
50 !strstr(extensions,"GLX_SGIX_pbuffer")) {
51 return 0;
52 }
53 return 2;
54 }
55 #endif
56
57 return 0;
58 }
59
60
61
62 FBCONFIG *
63 ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
64 {
65 int pbSupport = QueryPbuffers(dpy, screen);
66 #if defined(GLX_VERSION_1_3)
67 if (pbSupport == 1) {
68 return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
69 }
70 #endif
71 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
72 if (pbSupport == 2) {
73 return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
74 }
75 #endif
76 return NULL;
77 }
78
79
80 FBCONFIG *
81 GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
82 {
83 int pbSupport = QueryPbuffers(dpy, screen);
84 #if defined(GLX_VERSION_1_3)
85 if (pbSupport == 1) {
86 return glXGetFBConfigs(dpy, screen, nConfigs);
87 }
88 #endif
89 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
90 if (pbSupport == 2) {
91 /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
92 * of all available configurations.
93 */
94 return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs);
95 }
96 #endif
97 return NULL;
98 }
99
100
101 XVisualInfo *
102 GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
103 {
104 int pbSupport = QueryPbuffers(dpy, screen);
105 #if defined(GLX_VERSION_1_3)
106 if (pbSupport == 1) {
107 return glXGetVisualFromFBConfig(dpy, config);
108 }
109 #endif
110 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
111 if (pbSupport == 2) {
112 return glXGetVisualFromFBConfigSGIX(dpy, config);
113 }
114 #endif
115 return NULL;
116 }
117
118
119 /**
120 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
121 * to query an fbconfig attribute.
122 */
123 static int
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,
129 #endif
130 int attrib
131 )
132 {
133 int pbSupport = QueryPbuffers(dpy, screen);
134 int value = 0;
135
136 #if defined(GLX_VERSION_1_3)
137 if (pbSupport == 1) {
138 /* ok */
139 if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
140 value = 0;
141 }
142 return value;
143 }
144 /* fall-through */
145 #endif
146
147 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
148 if (pbSupport == 2) {
149 if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
150 value = 0;
151 }
152 return value;
153 }
154 #endif
155
156 return value;
157 }
158
159
160
161 /**
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
167 */
168 void
169 PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
170 {
171 PBUFFER pBuffer;
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;
182
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))
206 xVisual = -1;
207
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);
215 #else
216 optWidth = optHeight = 0;
217 #endif
218 #if defined(GLX_NV_float_buffer)
219 floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV);
220 #endif
221
222 /* See if we can create a pbuffer with this config */
223 pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
224
225 if (horizFormat) {
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" : ".",
238 stereo ? "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,
242 accumAlphaSize);
243 printf(" %2d %2d", sampleBuffers, samples);
244 printf(" %s %c", pBuffer ? "y" : ".",
245 ".y"[floatComponents]);
246 printf("\n");
247 }
248 else {
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");
271 printf("\n");
272 printf(" Render Types: ");
273 if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
274 if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
275 printf("\n");
276 printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
277
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);
284
285 printf(" Float Components: %s\n", floatComponents ? "yes" : "no");
286 }
287
288 if (pBuffer) {
289 DestroyPbuffer(dpy, screen, pBuffer);
290 }
291 }
292
293
294
295 GLXContext
296 CreateContext(Display *dpy, int screen, FBCONFIG config)
297 {
298 int pbSupport = QueryPbuffers(dpy, screen);
299 #if defined(GLX_VERSION_1_3)
300 if (pbSupport == 1) {
301 /* GLX 1.3 */
302 GLXContext c;
303 c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True);
304 if (!c) {
305 /* try indirect */
306 c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, False);
307 }
308 return c;
309 }
310 #endif
311 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
312 if (pbSupport == 2) {
313 GLXContext c;
314 c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);
315 if (!c) {
316 c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, False);
317 }
318 return c;
319 }
320 #endif
321 return 0;
322 }
323
324
325 void
326 DestroyContext(Display *dpy, GLXContext ctx)
327 {
328 glXDestroyContext(dpy, ctx);
329 }
330
331
332 /* This is only used by CreatePbuffer() */
333 static int XErrorFlag = 0;
334 static int HandleXError(Display *dpy, XErrorEvent *event)
335 {
336 XErrorFlag = 1;
337 return 0;
338 }
339
340
341 /**
342 * Create a Pbuffer. Use an X error handler to deal with potential
343 * BadAlloc errors.
344 *
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.
350 */
351 PBUFFER
352 CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
353 int width, int height, Bool largest, Bool preserve)
354 {
355 int (*oldHandler)(Display *, XErrorEvent *);
356 PBUFFER pBuffer = None;
357 int pbSupport = QueryPbuffers(dpy, screen);
358
359 /* Catch X protocol errors with our own error handler */
360 oldHandler = XSetErrorHandler(HandleXError);
361 XErrorFlag = 0;
362
363 #if defined(GLX_VERSION_1_3)
364 if (pbSupport == 1) {
365 /* GLX 1.3 */
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;
375 attribs[i++] = 0;
376 pBuffer = glXCreatePbuffer(dpy, config, attribs);
377 }
378 else
379 #endif
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;
387 attribs[i++] = 0;
388 pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
389 }
390 else
391 #endif
392 {
393 pBuffer = None;
394 }
395
396 /* Restore original X error handler */
397 (void) XSetErrorHandler(oldHandler);
398
399 /* Return pbuffer (may be None) */
400 if (!XErrorFlag && pBuffer != None) {
401 /*printf("config %d worked!\n", i);*/
402 return pBuffer;
403 }
404 else {
405 return None;
406 }
407 }
408
409
410 void
411 DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
412 {
413 int pbSupport = QueryPbuffers(dpy, screen);
414 #if defined(GLX_VERSION_1_3)
415 if (pbSupport == 1) {
416 glXDestroyPbuffer(dpy, pbuffer);
417 return;
418 }
419 #endif
420 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
421 if (pbSupport == 2) {
422 glXDestroyGLXPbufferSGIX(dpy, pbuffer);
423 return;
424 }
425 #endif
426 }