Brian Paul | 21666e3 | 2002-10-05 18:30:13 +0000 | [diff] [blame^] | 1 | /* $Id: pbutil.c,v 1.1 2002/10/05 18:30:13 brianp Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * OpenGL pbuffers utility functions. |
| 5 | * |
| 6 | * Brian Paul |
| 7 | * April 1997 |
| 8 | * Updated on 5 October 2002 |
| 9 | */ |
| 10 | |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <string.h> |
| 14 | #include "pbutil.h" |
| 15 | |
| 16 | |
| 17 | |
| 18 | /* |
| 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. |
| 24 | */ |
| 25 | int |
| 26 | QueryPbuffers(Display *dpy, int screen) |
| 27 | { |
| 28 | #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) |
| 29 | char *extensions; |
| 30 | |
| 31 | extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS); |
| 32 | if (!strstr(extensions,"GLX_SGIX_fbconfig")) { |
| 33 | return 0; |
| 34 | } |
| 35 | if (!strstr(extensions,"GLX_SGIX_pbuffer")) { |
| 36 | return 0; |
| 37 | } |
| 38 | return 1; |
| 39 | #else |
| 40 | return 0; |
| 41 | #endif |
| 42 | } |
| 43 | |
| 44 | |
| 45 | |
| 46 | #ifdef GLX_SGIX_fbconfig |
| 47 | |
| 48 | |
| 49 | /* |
| 50 | * Print parameters for a GLXFBConfig to stdout. |
| 51 | * Input: dpy - the X display |
| 52 | * fbConfig - the fbconfig handle |
| 53 | * horizFormat - if true, print in horizontal format |
| 54 | */ |
| 55 | void |
| 56 | PrintFBConfigInfo(Display *dpy, GLXFBConfigSGIX fbConfig, Bool horizFormat) |
| 57 | { |
| 58 | int pbAttribs[] = {GLX_LARGEST_PBUFFER_SGIX, True, |
| 59 | GLX_PRESERVED_CONTENTS_SGIX, False, |
| 60 | None}; |
| 61 | GLXPbufferSGIX pBuffer; |
| 62 | int width=2, height=2; |
| 63 | int bufferSize, level, doubleBuffer, stereo, auxBuffers; |
| 64 | int redSize, greenSize, blueSize, alphaSize; |
| 65 | int depthSize, stencilSize; |
| 66 | int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize; |
| 67 | int sampleBuffers, samples; |
| 68 | int drawableType, renderType, xRenderable, xVisual, id; |
| 69 | int maxWidth, maxHeight, maxPixels; |
| 70 | int optWidth, optHeight; |
| 71 | |
| 72 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_BUFFER_SIZE, &bufferSize); |
| 73 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_LEVEL, &level); |
| 74 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_DOUBLEBUFFER, &doubleBuffer); |
| 75 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_STEREO, &stereo); |
| 76 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_AUX_BUFFERS, &auxBuffers); |
| 77 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_RED_SIZE, &redSize); |
| 78 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_GREEN_SIZE, &greenSize); |
| 79 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_BLUE_SIZE, &blueSize); |
| 80 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_ALPHA_SIZE, &alphaSize); |
| 81 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_DEPTH_SIZE, &depthSize); |
| 82 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_STENCIL_SIZE, &stencilSize); |
| 83 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_ACCUM_RED_SIZE, &accumRedSize); |
| 84 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_ACCUM_GREEN_SIZE, &accumGreenSize); |
| 85 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_ACCUM_BLUE_SIZE, &accumBlueSize); |
| 86 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_ACCUM_ALPHA_SIZE, &accumAlphaSize); |
| 87 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_SAMPLE_BUFFERS_SGIS, &sampleBuffers); |
| 88 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_SAMPLES_SGIS, &samples); |
| 89 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_DRAWABLE_TYPE_SGIX, &drawableType); |
| 90 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_RENDER_TYPE_SGIX, &renderType); |
| 91 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_X_RENDERABLE_SGIX, &xRenderable); |
| 92 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_X_VISUAL_TYPE_EXT, &xVisual); |
| 93 | if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX)) |
| 94 | xVisual = -1; |
| 95 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_FBCONFIG_ID_SGIX, &id); |
| 96 | |
| 97 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_MAX_PBUFFER_WIDTH_SGIX, |
| 98 | &maxWidth); |
| 99 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_MAX_PBUFFER_HEIGHT_SGIX, |
| 100 | &maxHeight); |
| 101 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_MAX_PBUFFER_PIXELS_SGIX, |
| 102 | &maxPixels); |
| 103 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX, |
| 104 | &optWidth); |
| 105 | glXGetFBConfigAttribSGIX(dpy, fbConfig, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX, |
| 106 | &optHeight); |
| 107 | |
| 108 | pBuffer = CreatePbuffer(dpy, fbConfig, width, height, pbAttribs); |
| 109 | |
| 110 | if (horizFormat) { |
| 111 | printf("0x%03x ", id); |
| 112 | if (xVisual==GLX_STATIC_GRAY) printf("StaticGray "); |
| 113 | else if (xVisual==GLX_GRAY_SCALE) printf("GrayScale "); |
| 114 | else if (xVisual==GLX_STATIC_COLOR) printf("StaticColor "); |
| 115 | else if (xVisual==GLX_PSEUDO_COLOR) printf("PseudoColor "); |
| 116 | else if (xVisual==GLX_TRUE_COLOR) printf("TrueColor "); |
| 117 | else if (xVisual==GLX_DIRECT_COLOR) printf("DirectColor "); |
| 118 | else printf(" -none- "); |
| 119 | printf(" %3d %3d %s %s %s %2s ", bufferSize, level, |
| 120 | (renderType & GLX_RGBA_BIT_SGIX) ? "y" : "n", |
| 121 | (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : "n", |
| 122 | doubleBuffer ? "y" : "n", |
| 123 | stereo ? "y" : "n"); |
| 124 | printf("%2d %2d %2d %2d ", redSize, greenSize, blueSize, alphaSize); |
| 125 | printf("%2d %2d ", depthSize, stencilSize); |
| 126 | printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize, |
| 127 | accumAlphaSize); |
| 128 | printf(" %2d %2d", sampleBuffers, samples); |
| 129 | printf(" %s", pBuffer ? "y" : "n"); |
| 130 | printf("\n"); |
| 131 | } |
| 132 | else { |
| 133 | printf("Id 0x%x\n", id); |
| 134 | printf(" Buffer Size: %d\n", bufferSize); |
| 135 | printf(" Level: %d\n", level); |
| 136 | printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no"); |
| 137 | printf(" Stereo: %s\n", stereo ? "yes" : "no"); |
| 138 | printf(" Aux Buffers: %d\n", auxBuffers); |
| 139 | printf(" Red Size: %d\n", redSize); |
| 140 | printf(" Green Size: %d\n", greenSize); |
| 141 | printf(" Blue Size: %d\n", blueSize); |
| 142 | printf(" Alpha Size: %d\n", alphaSize); |
| 143 | printf(" Depth Size: %d\n", depthSize); |
| 144 | printf(" Stencil Size: %d\n", stencilSize); |
| 145 | printf(" Accum Red Size: %d\n", accumRedSize); |
| 146 | printf(" Accum Green Size: %d\n", accumGreenSize); |
| 147 | printf(" Accum Blue Size: %d\n", accumBlueSize); |
| 148 | printf(" Accum Alpha Size: %d\n", accumAlphaSize); |
| 149 | printf(" Sample Buffers: %d\n", sampleBuffers); |
| 150 | printf(" Samples/Pixel: %d\n", samples); |
| 151 | printf(" Drawable Types: "); |
| 152 | if (drawableType & GLX_WINDOW_BIT_SGIX) printf("Window "); |
| 153 | if (drawableType & GLX_PIXMAP_BIT_SGIX) printf("Pixmap "); |
| 154 | if (drawableType & GLX_PBUFFER_BIT_SGIX) printf("PBuffer"); |
| 155 | printf("\n"); |
| 156 | printf(" Render Types: "); |
| 157 | if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA "); |
| 158 | if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI "); |
| 159 | printf("\n"); |
| 160 | printf(" X Renderable: %s\n", xRenderable ? "yes" : "no"); |
| 161 | /* |
| 162 | printf(" Max width: %d\n", maxWidth); |
| 163 | printf(" Max height: %d\n", maxHeight); |
| 164 | printf(" Max pixels: %d\n", maxPixels); |
| 165 | printf(" Optimum width: %d\n", optWidth); |
| 166 | printf(" Optimum height: %d\n", optHeight); |
| 167 | */ |
| 168 | printf(" Pbuffer: %s\n", pBuffer ? "yes" : "no"); |
| 169 | } |
| 170 | |
| 171 | if (pBuffer) { |
| 172 | glXDestroyGLXPbufferSGIX(dpy, pBuffer); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | |
| 177 | |
| 178 | /* This is only used by CreatePbuffer() */ |
| 179 | static int XErrorFlag = 0; |
| 180 | static int HandleXError( Display *dpy, XErrorEvent *event ) |
| 181 | { |
| 182 | XErrorFlag = 1; |
| 183 | return 0; |
| 184 | } |
| 185 | |
| 186 | |
| 187 | /* |
| 188 | * Create a pixel buffer. We loop over the list of fbconfigs trying to create |
| 189 | * a pixel buffer. We return the first pixel buffer which we successfully |
| 190 | * create. This function hides the ugliness of dealing with BadAlloc X |
| 191 | * protocol errors. |
| 192 | * |
| 193 | * Input: dpy - the X display |
| 194 | * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX(). |
| 195 | * width, height - size of pixel buffer to request, in pixels. |
| 196 | * pbAttribs - list of pixel buffer attributes as used by |
| 197 | * glXCreateGLXPbufferSGIX(). |
| 198 | * Return: a pixel buffer or None. |
| 199 | */ |
| 200 | GLXPbufferSGIX |
| 201 | CreatePbuffer( Display *dpy, GLXFBConfigSGIX fbConfig, |
| 202 | int width, int height, int *pbAttribs ) |
| 203 | { |
| 204 | int (*oldHandler)( Display *, XErrorEvent * ); |
| 205 | GLXPbufferSGIX pBuffer = None; |
| 206 | |
| 207 | /* Catch X protocol errors with our own error handler */ |
| 208 | oldHandler = XSetErrorHandler( HandleXError ); |
| 209 | |
| 210 | XErrorFlag = 0; |
| 211 | pBuffer = glXCreateGLXPbufferSGIX(dpy, fbConfig, width, height, pbAttribs); |
| 212 | |
| 213 | /* Restore original X error handler */ |
| 214 | (void) XSetErrorHandler( oldHandler ); |
| 215 | |
| 216 | /* Return pbuffer (may be None) */ |
| 217 | if (!XErrorFlag && pBuffer!=None) { |
| 218 | /*printf("config %d worked!\n", i);*/ |
| 219 | return pBuffer; |
| 220 | } |
| 221 | else { |
| 222 | return None; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | |
| 227 | |
| 228 | #endif /*GLX_SGIX_fbconfig*/ |
| 229 | |
| 230 | |