ARB prog parser: fix parameter binding type
[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 = fbconfigs not available.
22 * 1 = fbconfigs are available via GLX 1.3.
23 * 2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig
24 */
25 int
26 QueryFBConfig(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 /* Try the SGIX extensions */
44 {
45 char *extensions;
46 extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
47 if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) {
48 return 2;
49 }
50 }
51
52 return 0;
53 }
54
55 /**
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.
62 */
63 int
64 QueryPbuffers(Display *dpy, int screen)
65 {
66 int ret;
67
68 ret = QueryFBConfig(dpy, screen);
69 if (ret == 2) {
70 char *extensions;
71 extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
72 if (extensions && strstr(extensions, "GLX_SGIX_pbuffer"))
73 return 2;
74 else
75 return 0;
76 }
77 else
78 return ret;
79 }
80
81 FBCONFIG *
82 ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
83 {
84 int fbcSupport = QueryPbuffers(dpy, screen);
85 #if defined(GLX_VERSION_1_3)
86 if (fbcSupport == 1) {
87 return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
88 }
89 #endif
90 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
91 if (fbcSupport == 2) {
92 return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
93 }
94 #endif
95 return NULL;
96 }
97
98
99 FBCONFIG *
100 GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
101 {
102 int fbcSupport = QueryFBConfig(dpy, screen);
103 #if defined(GLX_VERSION_1_3)
104 if (fbcSupport == 1) {
105 return glXGetFBConfigs(dpy, screen, nConfigs);
106 }
107 #endif
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.
112 */
113 return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs);
114 }
115 #endif
116 return NULL;
117 }
118
119
120 XVisualInfo *
121 GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
122 {
123 int fbcSupport = QueryFBConfig(dpy, screen);
124 #if defined(GLX_VERSION_1_3)
125 if (fbcSupport == 1) {
126 return glXGetVisualFromFBConfig(dpy, config);
127 }
128 #endif
129 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
130 if (fbcSupport == 2) {
131 return glXGetVisualFromFBConfigSGIX(dpy, config);
132 }
133 #endif
134 return NULL;
135 }
136
137
138 /**
139 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
140 * to query an fbconfig attribute.
141 */
142 static int
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,
148 #endif
149 int attrib
150 )
151 {
152 int fbcSupport = QueryFBConfig(dpy, screen);
153 int value = 0;
154
155 #if defined(GLX_VERSION_1_3)
156 if (fbcSupport == 1) {
157 /* ok */
158 if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
159 value = 0;
160 }
161 return value;
162 }
163 /* fall-through */
164 #endif
165
166 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
167 if (fbcSupport == 2) {
168 if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
169 value = 0;
170 }
171 return value;
172 }
173 #endif
174
175 return value;
176 }
177
178
179
180 /**
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
186 */
187 void
188 PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
189 {
190 PBUFFER pBuffer;
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;
201
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))
225 xVisual = -1;
226
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);
234 #else
235 optWidth = optHeight = 0;
236 #endif
237 #if defined(GLX_NV_float_buffer)
238 floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV);
239 #endif
240
241 /* See if we can create a pbuffer with this config */
242 pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
243
244 if (horizFormat) {
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" : ".",
257 stereo ? "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,
261 accumAlphaSize);
262 printf(" %2d %2d", sampleBuffers, samples);
263 printf(" %s %c", pBuffer ? "y" : ".",
264 ".y"[floatComponents]);
265 printf("\n");
266 }
267 else {
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");
290 printf("\n");
291 printf(" Render Types: ");
292 if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
293 if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
294 printf("\n");
295 printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
296
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);
303
304 printf(" Float Components: %s\n", floatComponents ? "yes" : "no");
305 }
306
307 if (pBuffer) {
308 DestroyPbuffer(dpy, screen, pBuffer);
309 }
310 }
311
312
313
314 GLXContext
315 CreateContext(Display *dpy, int screen, FBCONFIG config)
316 {
317 int fbcSupport = QueryFBConfig(dpy, screen);
318 #if defined(GLX_VERSION_1_3)
319 if (fbcSupport == 1) {
320 /* GLX 1.3 */
321 GLXContext c;
322 c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True);
323 if (!c) {
324 /* try indirect */
325 c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, False);
326 }
327 return c;
328 }
329 #endif
330 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
331 if (fbcSupport == 2) {
332 GLXContext c;
333 c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);
334 if (!c) {
335 c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, False);
336 }
337 return c;
338 }
339 #endif
340 return 0;
341 }
342
343
344 void
345 DestroyContext(Display *dpy, GLXContext ctx)
346 {
347 glXDestroyContext(dpy, ctx);
348 }
349
350
351 /* This is only used by CreatePbuffer() */
352 static int XErrorFlag = 0;
353 static int HandleXError(Display *dpy, XErrorEvent *event)
354 {
355 XErrorFlag = 1;
356 return 0;
357 }
358
359
360 /**
361 * Create a Pbuffer. Use an X error handler to deal with potential
362 * BadAlloc errors.
363 *
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.
369 */
370 PBUFFER
371 CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
372 int width, int height, Bool largest, Bool preserve)
373 {
374 int (*oldHandler)(Display *, XErrorEvent *);
375 PBUFFER pBuffer = None;
376 int pbSupport = QueryPbuffers(dpy, screen);
377
378 /* Catch X protocol errors with our own error handler */
379 oldHandler = XSetErrorHandler(HandleXError);
380 XErrorFlag = 0;
381
382 #if defined(GLX_VERSION_1_3)
383 if (pbSupport == 1) {
384 /* GLX 1.3 */
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;
394 attribs[i++] = 0;
395 pBuffer = glXCreatePbuffer(dpy, config, attribs);
396 }
397 else
398 #endif
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;
406 attribs[i++] = 0;
407 pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
408 }
409 else
410 #endif
411 {
412 pBuffer = None;
413 }
414
415 XSync(dpy, False);
416 /* Restore original X error handler */
417 (void) XSetErrorHandler(oldHandler);
418
419 /* Return pbuffer (may be None) */
420 if (!XErrorFlag && pBuffer != None) {
421 /*printf("config %d worked!\n", i);*/
422 return pBuffer;
423 }
424 else {
425 return None;
426 }
427 }
428
429
430 void
431 DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
432 {
433 int pbSupport = QueryPbuffers(dpy, screen);
434 #if defined(GLX_VERSION_1_3)
435 if (pbSupport == 1) {
436 glXDestroyPbuffer(dpy, pbuffer);
437 return;
438 }
439 #endif
440 #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
441 if (pbSupport == 2) {
442 glXDestroyGLXPbufferSGIX(dpy, pbuffer);
443 return;
444 }
445 #endif
446 }