blob: 50456e9f94f1603b4ecd182d9afbd230b781b073 [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 Paulf72e4422005-01-04 00:58:29 +000081
82XVisualInfo *
83GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
84{
85 int pbSupport = QueryPbuffers(dpy, screen);
86#if defined(GLX_VERSION_1_3)
87 if (pbSupport == 1) {
88 return glXGetVisualFromFBConfig(dpy, config);
89 }
90#endif
91#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
92 if (pbSupport == 2) {
93 return glXGetVisualFromFBConfigSGIX(dpy, config);
94 }
95#endif
96 return NULL;
97}
98
99
100/**
101 * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX()
102 * to query an fbconfig attribute.
103 */
104static int
105GetFBConfigAttrib(Display *dpy,
106#if defined(GLX_VERSION_1_3)
107 const GLXFBConfig config,
108#elif defined(GLX_SGIX_fbconfig)
109 const GLXFBConfigSGIX config,
110#endif
111 int attrib
112 )
113{
114 int value;
115
116#if defined(GLX_VERSION_1_3)
117 int glxVersionMajor, glxVersionMinor;
118 if (glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)
119 && glxVersionMajor * 100 + glxVersionMinor >= 103) {
120 /* ok */
121 if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
122 value = 0;
123 }
124 return value;
125 }
126 /* fall-through */
127#endif
128
129#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
130 if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
131 value = 0;
132 }
133 return value;
134#endif
135
136 return 0;
137}
138
139
140
141/**
Brian Paul21666e32002-10-05 18:30:13 +0000142 * Print parameters for a GLXFBConfig to stdout.
143 * Input: dpy - the X display
Brian Paulf72e4422005-01-04 00:58:29 +0000144 * screen - the X screen number
Brian Paul21666e32002-10-05 18:30:13 +0000145 * fbConfig - the fbconfig handle
146 * horizFormat - if true, print in horizontal format
147 */
148void
Brian Paulf72e4422005-01-04 00:58:29 +0000149PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
Brian Paul21666e32002-10-05 18:30:13 +0000150{
Brian Paulf72e4422005-01-04 00:58:29 +0000151 PBUFFER pBuffer;
Brian Paul21666e32002-10-05 18:30:13 +0000152 int width=2, height=2;
153 int bufferSize, level, doubleBuffer, stereo, auxBuffers;
154 int redSize, greenSize, blueSize, alphaSize;
155 int depthSize, stencilSize;
156 int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
157 int sampleBuffers, samples;
158 int drawableType, renderType, xRenderable, xVisual, id;
159 int maxWidth, maxHeight, maxPixels;
160 int optWidth, optHeight;
Brian Paulf72e4422005-01-04 00:58:29 +0000161 int floatComponents;
Brian Paul21666e32002-10-05 18:30:13 +0000162
Brian Paulf72e4422005-01-04 00:58:29 +0000163 /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
164 bufferSize = GetFBConfigAttrib(dpy, config, GLX_BUFFER_SIZE);
165 level = GetFBConfigAttrib(dpy, config, GLX_LEVEL);
166 doubleBuffer = GetFBConfigAttrib(dpy, config, GLX_DOUBLEBUFFER);
167 stereo = GetFBConfigAttrib(dpy, config, GLX_STEREO);
168 auxBuffers = GetFBConfigAttrib(dpy, config, GLX_AUX_BUFFERS);
169 redSize = GetFBConfigAttrib(dpy, config, GLX_RED_SIZE);
170 greenSize = GetFBConfigAttrib(dpy, config, GLX_GREEN_SIZE);
171 blueSize = GetFBConfigAttrib(dpy, config, GLX_BLUE_SIZE);
172 alphaSize = GetFBConfigAttrib(dpy, config, GLX_ALPHA_SIZE);
173 depthSize = GetFBConfigAttrib(dpy, config, GLX_DEPTH_SIZE);
174 stencilSize = GetFBConfigAttrib(dpy, config, GLX_STENCIL_SIZE);
175 accumRedSize = GetFBConfigAttrib(dpy, config, GLX_ACCUM_RED_SIZE);
176 accumGreenSize = GetFBConfigAttrib(dpy, config, GLX_ACCUM_GREEN_SIZE);
177 accumBlueSize = GetFBConfigAttrib(dpy, config, GLX_ACCUM_BLUE_SIZE);
178 accumAlphaSize = GetFBConfigAttrib(dpy, config, GLX_ACCUM_ALPHA_SIZE);
179 sampleBuffers = GetFBConfigAttrib(dpy, config, GLX_SAMPLE_BUFFERS);
180 samples = GetFBConfigAttrib(dpy, config, GLX_SAMPLES);
181 drawableType = GetFBConfigAttrib(dpy, config, GLX_DRAWABLE_TYPE);
182 renderType = GetFBConfigAttrib(dpy, config, GLX_RENDER_TYPE);
183 xRenderable = GetFBConfigAttrib(dpy, config, GLX_X_RENDERABLE);
184 xVisual = GetFBConfigAttrib(dpy, config, GLX_X_VISUAL_TYPE);
Brian Paul21666e32002-10-05 18:30:13 +0000185 if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
186 xVisual = -1;
Brian Paul21666e32002-10-05 18:30:13 +0000187
Brian Paulf72e4422005-01-04 00:58:29 +0000188 id = GetFBConfigAttrib(dpy, config, GLX_FBCONFIG_ID);
189 maxWidth = GetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_WIDTH);
190 maxHeight = GetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_HEIGHT);
191 maxPixels = GetFBConfigAttrib(dpy, config, GLX_MAX_PBUFFER_PIXELS);
192#if defined(GLX_SGIX_pbuffer)
193 optWidth = GetFBConfigAttrib(dpy, config, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX);
194 optHeight = GetFBConfigAttrib(dpy, config, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX);
195#else
196 optWidth = optHeight = 0;
197#endif
198#if defined(GLX_NV_float_buffer)
199 floatComponents = GetFBConfigAttrib(dpy, config, GLX_FLOAT_COMPONENTS_NV);
200#endif
Brian Paul21666e32002-10-05 18:30:13 +0000201
Brian Paulf72e4422005-01-04 00:58:29 +0000202 /* See if we can create a pbuffer with this config */
203 pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False);
Brian Paul21666e32002-10-05 18:30:13 +0000204
205 if (horizFormat) {
206 printf("0x%03x ", id);
207 if (xVisual==GLX_STATIC_GRAY) printf("StaticGray ");
208 else if (xVisual==GLX_GRAY_SCALE) printf("GrayScale ");
209 else if (xVisual==GLX_STATIC_COLOR) printf("StaticColor ");
210 else if (xVisual==GLX_PSEUDO_COLOR) printf("PseudoColor ");
211 else if (xVisual==GLX_TRUE_COLOR) printf("TrueColor ");
212 else if (xVisual==GLX_DIRECT_COLOR) printf("DirectColor ");
213 else printf(" -none- ");
214 printf(" %3d %3d %s %s %s %2s ", bufferSize, level,
215 (renderType & GLX_RGBA_BIT_SGIX) ? "y" : "n",
216 (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : "n",
217 doubleBuffer ? "y" : "n",
218 stereo ? "y" : "n");
219 printf("%2d %2d %2d %2d ", redSize, greenSize, blueSize, alphaSize);
220 printf("%2d %2d ", depthSize, stencilSize);
221 printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize,
222 accumAlphaSize);
223 printf(" %2d %2d", sampleBuffers, samples);
Brian Paulf72e4422005-01-04 00:58:29 +0000224 printf(" %s %c", pBuffer ? "y" : "n",
225 "ny"[floatComponents]);
Brian Paul21666e32002-10-05 18:30:13 +0000226 printf("\n");
227 }
228 else {
229 printf("Id 0x%x\n", id);
230 printf(" Buffer Size: %d\n", bufferSize);
231 printf(" Level: %d\n", level);
232 printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
233 printf(" Stereo: %s\n", stereo ? "yes" : "no");
234 printf(" Aux Buffers: %d\n", auxBuffers);
235 printf(" Red Size: %d\n", redSize);
236 printf(" Green Size: %d\n", greenSize);
237 printf(" Blue Size: %d\n", blueSize);
238 printf(" Alpha Size: %d\n", alphaSize);
239 printf(" Depth Size: %d\n", depthSize);
240 printf(" Stencil Size: %d\n", stencilSize);
241 printf(" Accum Red Size: %d\n", accumRedSize);
242 printf(" Accum Green Size: %d\n", accumGreenSize);
243 printf(" Accum Blue Size: %d\n", accumBlueSize);
244 printf(" Accum Alpha Size: %d\n", accumAlphaSize);
245 printf(" Sample Buffers: %d\n", sampleBuffers);
246 printf(" Samples/Pixel: %d\n", samples);
247 printf(" Drawable Types: ");
Brian Paulf72e4422005-01-04 00:58:29 +0000248 if (drawableType & GLX_WINDOW_BIT) printf("Window ");
249 if (drawableType & GLX_PIXMAP_BIT) printf("Pixmap ");
250 if (drawableType & GLX_PBUFFER_BIT) printf("PBuffer");
Brian Paul21666e32002-10-05 18:30:13 +0000251 printf("\n");
252 printf(" Render Types: ");
253 if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
254 if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
255 printf("\n");
256 printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
Brian Paulf72e4422005-01-04 00:58:29 +0000257
Brian Paul21666e32002-10-05 18:30:13 +0000258 printf(" Pbuffer: %s\n", pBuffer ? "yes" : "no");
Brian Paulf72e4422005-01-04 00:58:29 +0000259 printf(" Max Pbuffer width: %d\n", maxWidth);
260 printf(" Max Pbuffer height: %d\n", maxHeight);
261 printf(" Max Pbuffer pixels: %d\n", maxPixels);
262 printf(" Optimum Pbuffer width: %d\n", optWidth);
263 printf(" Optimum Pbuffer height: %d\n", optHeight);
264
265 printf(" Float Components: %s\n", floatComponents ? "yes" : "no");
Brian Paul21666e32002-10-05 18:30:13 +0000266 }
267
268 if (pBuffer) {
Brian Paulf72e4422005-01-04 00:58:29 +0000269 DestroyPbuffer(dpy, screen, pBuffer);
Brian Paul21666e32002-10-05 18:30:13 +0000270 }
271}
272
273
274
275/* This is only used by CreatePbuffer() */
276static int XErrorFlag = 0;
Brian Paulf72e4422005-01-04 00:58:29 +0000277static int HandleXError(Display *dpy, XErrorEvent *event)
Brian Paul21666e32002-10-05 18:30:13 +0000278{
279 XErrorFlag = 1;
280 return 0;
281}
282
283
Brian Paulf72e4422005-01-04 00:58:29 +0000284/**
Brian Paul18a94902004-02-02 15:38:26 +0000285 * Create a Pbuffer. Use an X error handler to deal with potential
286 * BadAlloc errors.
Brian Paul21666e32002-10-05 18:30:13 +0000287 *
288 * Input: dpy - the X display
289 * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX().
290 * width, height - size of pixel buffer to request, in pixels.
Brian Paulf72e4422005-01-04 00:58:29 +0000291 * pbAttribs - list of optional pixel buffer attributes
292 * Return: a Pbuffer or None.
Brian Paul21666e32002-10-05 18:30:13 +0000293 */
Brian Paulf72e4422005-01-04 00:58:29 +0000294PBUFFER
295CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
296 int width, int height, Bool largest, Bool preserve)
Brian Paul21666e32002-10-05 18:30:13 +0000297{
Brian Paulf72e4422005-01-04 00:58:29 +0000298 int (*oldHandler)(Display *, XErrorEvent *);
299 PBUFFER pBuffer = None;
300 int pbSupport = QueryPbuffers(dpy, screen);
Brian Paul21666e32002-10-05 18:30:13 +0000301
302 /* Catch X protocol errors with our own error handler */
Brian Paulf72e4422005-01-04 00:58:29 +0000303 oldHandler = XSetErrorHandler(HandleXError);
Brian Paul21666e32002-10-05 18:30:13 +0000304 XErrorFlag = 0;
Brian Paulf72e4422005-01-04 00:58:29 +0000305
306#if defined(GLX_VERSION_1_3)
307 if (pbSupport == 1) {
308 /* GLX 1.3 */
309 int attribs[100], i = 0;
310 attribs[i++] = GLX_PBUFFER_WIDTH;
311 attribs[i++] = width;
312 attribs[i++] = GLX_PBUFFER_HEIGHT;
313 attribs[i++] = height;
314 attribs[i++] = GLX_PRESERVED_CONTENTS;
315 attribs[i++] = preserve;
316 attribs[i++] = GLX_LARGEST_PBUFFER;
317 attribs[i++] = largest;
318 attribs[i++] = 0;
319 pBuffer = glXCreatePbuffer(dpy, config, attribs);
320 }
321 else
322#endif
323#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
324 if (pbSupport == 2) {
325 int attribs[100], i = 0;
326 attribs[i++] = GLX_PRESERVED_CONTENTS;
327 attribs[i++] = preserve;
328 attribs[i++] = GLX_LARGEST_PBUFFER;
329 attribs[i++] = largest;
330 attribs[i++] = 0;
331 pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs);
332 }
333 else
334#endif
335 {
336 pBuffer = None;
337 }
Brian Paul21666e32002-10-05 18:30:13 +0000338
339 /* Restore original X error handler */
Brian Paulf72e4422005-01-04 00:58:29 +0000340 (void) XSetErrorHandler(oldHandler);
Brian Paul21666e32002-10-05 18:30:13 +0000341
342 /* Return pbuffer (may be None) */
Brian Paulf72e4422005-01-04 00:58:29 +0000343 if (!XErrorFlag && pBuffer != None) {
Brian Paul21666e32002-10-05 18:30:13 +0000344 /*printf("config %d worked!\n", i);*/
345 return pBuffer;
346 }
347 else {
348 return None;
349 }
350}
351
352
Brian Paulf72e4422005-01-04 00:58:29 +0000353void
354DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer)
355{
356 int pbSupport = QueryPbuffers(dpy, screen);
357#if defined(GLX_VERSION_1_3)
358 if (pbSupport == 1) {
359 glXDestroyPbuffer(dpy, pbuffer);
360 return;
361 }
362#endif
363#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
364 if (pbSupport == 2) {
365 glXDestroyGLXPbufferSGIX(dpy, pbuffer);
366 return;
367 }
368#endif
369}