From b6a9cb70950158e57663faacc21c3794b913d0db Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 3 Feb 2004 16:23:38 +0000 Subject: [PATCH] another pbuffer demo (Andrew Lentvorski) --- progs/xdemos/Makefile.X11 | 1 + progs/xdemos/glxpbdemo.c | 433 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 434 insertions(+) create mode 100644 progs/xdemos/glxpbdemo.c diff --git a/progs/xdemos/Makefile.X11 b/progs/xdemos/Makefile.X11 index 2254fd3d3b4..53436b2cdcd 100644 --- a/progs/xdemos/Makefile.X11 +++ b/progs/xdemos/Makefile.X11 @@ -17,6 +17,7 @@ PROGS = glthreads \ glxheads \ glxinfo \ glxpixmap \ + glxpbdemo \ glxswapcontrol \ manywin \ offset \ diff --git a/progs/xdemos/glxpbdemo.c b/progs/xdemos/glxpbdemo.c new file mode 100644 index 00000000000..9bdf2ff7466 --- /dev/null +++ b/progs/xdemos/glxpbdemo.c @@ -0,0 +1,433 @@ + +/* + * This program demonstrates how to do "off-screen" rendering using + * the GLX pixel buffer extension. + * + * Written by Brian Paul for the "OpenGL and Window System Integration" + * course presented at SIGGRAPH '97. Updated on 5 October 2002. + * + * Updated on 31 January 2004 to use native GLX by + * Andrew P. Lentvorski, Jr. + * + * Usage: + * glxpbdemo width height imgfile + * Where: + * width is the width, in pixels, of the image to generate. + * height is the height, in pixels, of the image to generate. + * imgfile is the name of the PPM image file to write. + * + * + * This demo draws 3-D boxes with random orientation. + * + * On machines such as the SGI Indigo you may have to reconfigure your + * display/X server to enable pbuffers. Look in the /usr/gfx/ucode/MGRAS/vof/ + * directory for display configurations with the _pbuf suffix. Use + * setmon -x to configure your X server and display for pbuffers. + * + * O2 systems seem to support pbuffers well. + * + */ + +#include +#include +#include +#include +#include + +/* Some ugly global vars */ +static GLXFBConfig gFBconfig = 0; +static Display *gDpy = NULL; +static int gScreen = 0; +static GLXPbuffer gPBuffer = 0; +static int gWidth, gHeight; + + +/* + * Test for appropriate version of GLX to run this program + * Input: dpy - the X display + * screen - screen number + * Return: 0 = GLX not available. + * 1 = GLX available. + */ +static int +RuntimeQueryGLXVersion(Display *dpy, int screen) +{ +#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4) + char *glxversion; + + glxversion = (char *) glXGetClientString(dpy, GLX_VERSION); + if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4"))) + return 0; + + glxversion = (char *) glXQueryServerString(dpy, screen, GLX_VERSION); + if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4"))) + return 0; + + return 1; +#else + return 0; +#endif +} + + + +/* + * Create the pbuffer and return a GLXPbuffer handle. + */ +static GLXPbuffer +MakePbuffer( Display *dpy, int screen, int width, int height ) +{ + GLXFBConfig *fbConfigs; + GLXFBConfig chosenFBConfig; + GLXPbuffer pBuffer = None; + + int nConfigs; + int fbconfigid; + + int fbAttribs[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DEPTH_SIZE, 1, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, + None + }; + + int pbAttribs[] = { + GLX_PBUFFER_WIDTH, 0, + GLX_PBUFFER_HEIGHT, 0, + GLX_LARGEST_PBUFFER, False, + GLX_PRESERVED_CONTENTS, False, + None + }; + + pbAttribs[1] = width; + pbAttribs[3] = height; + + fbConfigs = glXChooseFBConfig(dpy, screen, fbAttribs, &nConfigs); + + if (0 == nConfigs || !fbConfigs) { + printf("Error: glxChooseFBConfig failed\n"); + XCloseDisplay(dpy); + return 0; + } + + chosenFBConfig = fbConfigs[0]; + + glXGetFBConfigAttrib(dpy, chosenFBConfig, GLX_FBCONFIG_ID, &fbconfigid); + printf("Chose 0x%x as fbconfigid\n", fbconfigid); + + /* Create the pbuffer using first fbConfig in the list that works. */ + pBuffer = glXCreatePbuffer(dpy, chosenFBConfig, pbAttribs); + + if (pBuffer) { + gFBconfig = chosenFBConfig; + gWidth = width; + gHeight = height; + } + + XFree(fbConfigs); + + return pBuffer; +} + + + +/* + * Do all the X / GLX setup stuff. + */ +static int +Setup(int width, int height) +{ +#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4) + XVisualInfo *visInfo; + GLXContext glCtx; + + /* Open the X display */ + gDpy = XOpenDisplay(NULL); + if (!gDpy) { + printf("Error: couldn't open default X display.\n"); + return 0; + } + + /* Get default screen */ + gScreen = DefaultScreen(gDpy); + + /* Test that GLX is available */ + if (!RuntimeQueryGLXVersion(gDpy, gScreen)) { + printf("Error: GLX 1.3 or 1.4 not available\n"); + XCloseDisplay(gDpy); + return 0; + } + + /* Create Pbuffer */ + gPBuffer = MakePbuffer( gDpy, gScreen, width, height ); + if (gPBuffer==None) { + printf("Error: couldn't create pbuffer\n"); + XCloseDisplay(gDpy); + return 0; + } + + /* Create GLX context */ + glCtx = glXCreateNewContext(gDpy, gFBconfig, GLX_RGBA_TYPE, NULL, True); + if (glCtx) { + if (!glXIsDirect(gDpy, glCtx)) { + printf("Warning: using indirect GLXContext\n"); + } + } + else { + printf("Error: Couldn't create GLXContext\n"); + XFree(visInfo); + XCloseDisplay(gDpy); + return 0; + } + + /* Bind context to pbuffer */ + if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) { + printf("Error: glXMakeCurrent failed\n"); + XFree(visInfo); + XCloseDisplay(gDpy); + return 0; + } + + return 1; /* Success!! */ +#else + printf("Error: GLX version 1.3 or 1.4 not available at compile time\n"); + return 0; +#endif +} + + + +/* One-time GL setup */ +static void +InitGL(void) +{ + static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0}; + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_NORMALIZE); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glViewport(0, 0, gWidth, gHeight); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -15.0 ); + +} + + +/* Return random float in [0,1] */ +static float +Random(void) +{ + int i = rand(); + return (float) (i % 1000) / 1000.0; +} + + +static void +RandomColor(void) +{ + GLfloat c[4]; + c[0] = Random(); + c[1] = Random(); + c[2] = Random(); + c[3] = 1.0; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c); +} + + +/* This function borrowed from Mark Kilgard's GLUT */ +static void +drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1, + GLfloat z0, GLfloat z1, GLenum type) +{ + static GLfloat n[6][3] = + { + {-1.0, 0.0, 0.0}, + {0.0, 1.0, 0.0}, + {1.0, 0.0, 0.0}, + {0.0, -1.0, 0.0}, + {0.0, 0.0, 1.0}, + {0.0, 0.0, -1.0} + }; + static GLint faces[6][4] = + { + {0, 1, 2, 3}, + {3, 2, 6, 7}, + {7, 6, 5, 4}, + {4, 5, 1, 0}, + {5, 6, 2, 1}, + {7, 4, 0, 3} + }; + GLfloat v[8][3], tmp; + GLint i; + + if (x0 > x1) { + tmp = x0; + x0 = x1; + x1 = tmp; + } + if (y0 > y1) { + tmp = y0; + y0 = y1; + y1 = tmp; + } + if (z0 > z1) { + tmp = z0; + z0 = z1; + z1 = tmp; + } + v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0; + v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1; + v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0; + v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1; + v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0; + v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1; + + for (i = 0; i < 6; i++) { + glBegin(type); + glNormal3fv(&n[i][0]); + glVertex3fv(&v[faces[i][0]][0]); + glVertex3fv(&v[faces[i][1]][0]); + glVertex3fv(&v[faces[i][2]][0]); + glVertex3fv(&v[faces[i][3]][0]); + glEnd(); + } +} + + + +/* Render a scene */ +static void +Render(void) +{ + int NumBoxes = 100; + int i; + + InitGL(); + glClearColor(0.2, 0.2, 0.9, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + for (i=0;i