From 2f61cbd30cdf0534da5e8281bc27886edb834b06 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Wed, 16 May 2007 14:46:13 -0700 Subject: Add simple program to test GL_MESA_texture_array. --- progs/tests/Makefile | 7 + progs/tests/arraytexture.c | 337 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+) create mode 100644 progs/tests/arraytexture.c (limited to 'progs') diff --git a/progs/tests/Makefile b/progs/tests/Makefile index 9edef74fb2..b506db3e7b 100644 --- a/progs/tests/Makefile +++ b/progs/tests/Makefile @@ -23,6 +23,7 @@ SOURCES = \ arbvptest3.c \ arbvptorus.c \ arbvpwarpmesh.c \ + arraytexture.c \ blendminmax.c \ blendsquare.c \ bufferobj.c \ @@ -117,6 +118,12 @@ getprocaddress: getprocaddress.c getproclist.h getproclist.h: $(TOP)/src/mesa/glapi/gl_API.xml getprocaddress.c getprocaddress.py python getprocaddress.py > getproclist.h +arraytexture: arraytexture.o readtex.o + $(CC) $(CFLAGS) arraytexture.o readtex.o $(LIBS) -o $@ + +arraytexture.o: arraytexture.c readtex.h + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + afsmultiarb: afsmultiarb.o readtex.o $(CC) $(CFLAGS) afsmultiarb.o readtex.o $(LIBS) -o $@ diff --git a/progs/tests/arraytexture.c b/progs/tests/arraytexture.c new file mode 100644 index 0000000000..48c622be30 --- /dev/null +++ b/progs/tests/arraytexture.c @@ -0,0 +1,337 @@ +/* + * (C) Copyright IBM Corporation 2007 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/** + * \file arraytexture.c + * + * + * \author Ian Romanick + */ + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(GL_EXT_texture_array) && !defined(GL_MESA_texture_array) +# error "This demo requires enums for either GL_EXT_texture_array or GL_MESA_texture_array to build." +#endif + +#include "readtex.h" + +#define GL_CHECK_ERROR() \ + do { \ + GLenum err = glGetError(); \ + if (err) { \ + printf("%s:%u: %s (0x%04x)\n", __FILE__, __LINE__, \ + gluErrorString(err), err); \ + } \ + } while (0) + +static const char *const textures[] = { + "../images/girl.rgb", + "../images/girl2.rgb", + "../images/arch.rgb", + "../images/s128.rgb", + + "../images/tree3.rgb", + "../images/bw.rgb", + "../images/reflect.rgb", + "../images/wrs_logo.rgb", + NULL +}; + +static const char frag_prog[] = + "!!ARBfp1.0\n" + "OPTION MESA_texture_array;\n" + "TEX result.color, fragment.texcoord[0], texture[0], ARRAY2D;\n" + "END\n"; + +static GLfloat Xrot = 0, Yrot = -30, Zrot = 0; +static GLfloat texZ = 0.0; +static GLfloat texZ_dir = 0.01; +static GLint num_layers; + +static PFNGLBINDPROGRAMARBPROC bind_program; +static PFNGLPROGRAMSTRINGARBPROC program_string; +static PFNGLGENPROGRAMSARBPROC gen_programs; + + +static void +PrintString(const char *s) +{ + while (*s) { + glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); + s++; + } +} + + +static void Idle(void) +{ + static int lastTime = 0; + int t = glutGet(GLUT_ELAPSED_TIME); + + if (lastTime == 0) + lastTime = t; + else if (t - lastTime < 10) + return; + + lastTime = t; + + texZ += texZ_dir; + if ((texZ < 0.0) || ((GLint) texZ > num_layers)) { + texZ_dir = -texZ_dir; + } + + glutPostRedisplay(); +} + + +static void Display(void) +{ + char str[100]; + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1, 1, -1, 1, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + (*bind_program)(GL_FRAGMENT_PROGRAM_ARB, 0); + glColor3f(1,1,1); + glRasterPos3f(-0.9, -0.9, 0.0); + sprintf(str, "Texture Z coordinate = %4.1f", texZ); + PrintString(str); + + (*bind_program)(GL_FRAGMENT_PROGRAM_ARB, 1); + GL_CHECK_ERROR(); + glEnable(GL_TEXTURE_2D_ARRAY_EXT); + GL_CHECK_ERROR(); + + 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, -8.0); + + glPushMatrix(); + glRotatef(Xrot, 1, 0, 0); + glRotatef(Yrot, 0, 1, 0); + glRotatef(Zrot, 0, 0, 1); + + glBegin(GL_QUADS); + glTexCoord3f(0.0, 0.0, texZ); glVertex2f(-1.0, -1.0); + glTexCoord3f(2.0, 0.0, texZ); glVertex2f(1.0, -1.0); + glTexCoord3f(2.0, 2.0, texZ); glVertex2f(1.0, 1.0); + glTexCoord3f(0.0, 2.0, texZ); glVertex2f(-1.0, 1.0); + glEnd(); + + glPopMatrix(); + + glDisable(GL_TEXTURE_2D_ARRAY_EXT); + GL_CHECK_ERROR(); + (*bind_program)(GL_FRAGMENT_PROGRAM_ARB, 0); + GL_CHECK_ERROR(); + + glutSwapBuffers(); +} + + +static void Reshape(int width, int height) +{ + glViewport(0, 0, width, height); +} + + +static void Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case 27: + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void SpecialKey(int key, int x, int y) +{ + const GLfloat step = 3.0; + (void) x; + (void) y; + switch (key) { + case GLUT_KEY_UP: + Xrot -= step; + break; + case GLUT_KEY_DOWN: + Xrot += step; + break; + case GLUT_KEY_LEFT: + Yrot -= step; + break; + case GLUT_KEY_RIGHT: + Yrot += step; + break; + } + glutPostRedisplay(); +} + + +static int FindLine(const char *program, int position) +{ + int i, line = 1; + for (i = 0; i < position; i++) { + if (program[i] == '\n') + line++; + } + return line; +} + + +static void +compile_fragment_program(GLuint id, const char *prog) +{ + int errorPos; + int err; + + err = glGetError(); + (*bind_program)(GL_FRAGMENT_PROGRAM_ARB, id); + (*program_string)(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(prog), (const GLubyte *) prog); + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); + err = glGetError(); + if (err != GL_NO_ERROR || errorPos != -1) { + int l = FindLine(prog, errorPos); + + printf("Fragment Program Error (err=%d, pos=%d line=%d): %s\n", + err, errorPos, l, + (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + exit(0); + } +} + + +static void require_extension(const char *ext) +{ + if (!glutExtensionSupported(ext)) { + printf("Sorry, %s not supported by this renderer.\n", ext); + exit(1); + } +} + + +static void Init(void) +{ + const char *const ver_string = (const char *const) glGetString(GL_VERSION); + unsigned i; + + printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + printf("GL_VERSION = %s\n", ver_string); + + require_extension("GL_ARB_fragment_program"); + require_extension("GL_MESA_texture_array"); + require_extension("GL_SGIS_generate_mipmap"); + + bind_program = glutGetProcAddress("glBindProgramARB"); + program_string = glutGetProcAddress("glProgramStringARB"); + gen_programs = glutGetProcAddress("glGenProgramsARB"); + + + for (num_layers = 0; textures[num_layers] != NULL; num_layers++) + /* empty */ ; + + glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 1); + glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGB8, + 256, 256, num_layers, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + GL_CHECK_ERROR(); + + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_GENERATE_MIPMAP_SGIS, + GL_TRUE); + + for (i = 0; textures[i] != NULL; i++) { + GLint width, height; + GLenum format; + + GLubyte *image = LoadRGBImage(textures[i], &width, &height, &format); + if (!image) { + printf("Error: could not load texture image %s\n", textures[i]); + exit(1); + } + + /* resize to 256 x 256 */ + if (width != 256 || height != 256) { + GLubyte *newImage = malloc(256 * 256 * 4); + gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, + 256, 256, GL_UNSIGNED_BYTE, newImage); + free(image); + image = newImage; + } + + glTexSubImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, + 0, 0, i, 256, 256, 1, + format, GL_UNSIGNED_BYTE, image); + free(image); + } + GL_CHECK_ERROR(); + + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + GL_CHECK_ERROR(); + glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GL_CHECK_ERROR(); + + compile_fragment_program(1, frag_prog); + GL_CHECK_ERROR(); +} + + +int main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(350, 350); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutCreateWindow("Array texture test"); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutSpecialFunc(SpecialKey); + glutDisplayFunc(Display); + glutIdleFunc(Idle); + Init(); + glutMainLoop(); + return 0; +} -- cgit v1.2.3 From 4465377ca3be3f61c4be835ef47bd569f665a8c4 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 19 May 2007 08:28:41 -0600 Subject: GLX_EXT_texture_from_pixmap test --- progs/xdemos/Makefile | 1 + progs/xdemos/texture_from_pixmap.c | 381 +++++++++++++++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 progs/xdemos/texture_from_pixmap.c (limited to 'progs') diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index ec85464bec..d1d7fecea1 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -23,6 +23,7 @@ PROGS = glthreads \ overlay \ pbinfo \ pbdemo \ + texture_from_pixmap \ wincopy \ xfont \ xrotfontdemo \ diff --git a/progs/xdemos/texture_from_pixmap.c b/progs/xdemos/texture_from_pixmap.c new file mode 100644 index 0000000000..2222956703 --- /dev/null +++ b/progs/xdemos/texture_from_pixmap.c @@ -0,0 +1,381 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Test the GLX_EXT_texture_from_pixmap extension + * Brian Paul + * 19 May 2007 + */ + + +#define GL_GLEXT_PROTOTYPES +#define GLX_GLXEXT_PROTOTYPES +#include +#include +#include +#include +#include +#include +#include + + +static Display * +OpenDisplay(void) +{ + int screen; + Display *dpy; + const char *ext; + + dpy = XOpenDisplay(NULL); + if (!dpy) { + printf("Couldn't open default display!\n"); + exit(1); + } + + screen = DefaultScreen(dpy); + ext = glXQueryExtensionsString(dpy, screen); + if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) { + printf("GLX_EXT_texture_from_pixmap not supported by GLX\n"); + exit(1); + } + + return dpy; +} + + +static GLXFBConfig +ChoosePixmapFBConfig(Display *display) +{ + int screen = DefaultScreen(display); + GLXFBConfig *fbconfigs; + int i, nfbconfigs, value; + float top, bottom; + + fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs); + for (i = 0; i < nfbconfigs; i++) { + + glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value); + if (!(value & GLX_PIXMAP_BIT)) + continue; + + glXGetFBConfigAttrib(display, fbconfigs[i], + GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value); + if (!(value & GLX_TEXTURE_2D_BIT_EXT)) + continue; + + glXGetFBConfigAttrib(display, fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGBA_EXT, &value); + if (value == False) { + glXGetFBConfigAttrib(display, fbconfigs[i], + GLX_BIND_TO_TEXTURE_RGB_EXT, &value); + if (value == False) + continue; + } + + glXGetFBConfigAttrib(display, fbconfigs[i], + GLX_Y_INVERTED_EXT, &value); + if (value == True) { + top = 0.0f; + bottom = 1.0f; + } + else { + top = 1.0f; + bottom = 0.0f; + } + + break; + } + + if (i == nfbconfigs) { + printf("Unable to find FBconfig for texturing\n"); + exit(1); + } + + return fbconfigs[i]; +} + + +static GLXPixmap +CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p) +{ + GLXPixmap gp; + const int pixmapAttribs[] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, + None + }; + Window root = RootWindow(dpy, 0); + + *p = XCreatePixmap(dpy, root, w, h, 24); + XSync(dpy, 0); + gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs); + XSync(dpy, 0); + + return gp; +} + + +static void +DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h) +{ + XGCValues gcvals; + GC gc; + + gcvals.background = 0; + gc = XCreateGC(dpy, pm, GCBackground, &gcvals); + + XSetForeground(dpy, gc, 0x0); + XFillRectangle(dpy, pm, gc, 0, 0, w, h); + + XSetForeground(dpy, gc, 0xff0000); + XFillRectangle(dpy, pm, gc, 0, 0, 50, 50); + + XSetForeground(dpy, gc, 0x00ff00); + XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50); + + XSetForeground(dpy, gc, 0x0000ff); + XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50); + + XSetForeground(dpy, gc, 0xffffff); + XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50); + + XSetForeground(dpy, gc, 0xffff00); + XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel); + XDrawLine(dpy, pm, gc, 0, 0, w, h); + XDrawLine(dpy, pm, gc, 0, h, w, 0); + + XFreeGC(dpy, gc); +} + + +static XVisualInfo * +ChooseWindowVisual(Display *dpy) +{ + int screen = DefaultScreen(dpy); + XVisualInfo *visinfo; + int attribs[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + None + }; + + visinfo = glXChooseVisual(dpy, screen, attribs); + if (!visinfo) { + printf("Unable to find RGB, double-buffered visual\n"); + exit(1); + } + + return visinfo; +} + + +static Window +CreateWindow(Display *dpy, XVisualInfo *visinfo, + int width, int height, const char *name) +{ + int screen = DefaultScreen(dpy); + Window win; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + + root = RootWindow(dpy, screen); + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow(dpy, root, 0, 0, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr); + if (win) { + XSizeHints sizehints; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize; + XSetNormalHints(dpy, win, &sizehints); + XSetStandardProperties(dpy, win, name, name, + None, (char **)NULL, 0, &sizehints); + + XMapWindow(dpy, win); + } + return win; +} + + +static void +BindPixmapTexture(Display *dpy, GLXPixmap gp) +{ + GLuint texture; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glXBindTexImageEXT(dpy, gp, GLX_FRONT_LEFT_EXT, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEnable(GL_TEXTURE_2D); + /* + glXReleaseTexImageEXT (display, glxpixmap, GLX_FRONT_LEFT_EXT); + */ +} + + +static void +Resize(Window win, unsigned int width, unsigned int height) +{ + float sz = 1.5; + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-sz, sz, -sz, sz, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); +} + + +static void +Redraw(Display *dpy, Window win, float rot) +{ + glClearColor(0.25, 0.25, 0.25, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + glPushMatrix(); + glRotatef(rot, 0, 0, 1); + glRotatef(2.0 * rot, 1, 0, 0); + + glBegin(GL_QUADS); + glTexCoord2d(0.0, 0.0); + glVertex2f(-1, -1); + glTexCoord2d(1.0, 0.0); + glVertex2f( 1, -1); + glTexCoord2d(1.0, 1.0); + glVertex2d(1.0, 1.0); + glTexCoord2d(0.0, 1.0); + glVertex2f(-1.0, 1.0); + glEnd(); + + glPopMatrix(); + + glXSwapBuffers(dpy, win); +} + + +static void +EventLoop(Display *dpy, Window win) +{ + GLfloat rot = 0.0; + int anim = 0; + + while (1) { + if (!anim || XPending(dpy) > 0) { + XEvent event; + XNextEvent(dpy, &event); + + switch (event.type) { + case Expose: + Redraw(dpy, win, rot); + break; + case ConfigureNotify: + Resize(event.xany.window, + event.xconfigure.width, + event.xconfigure.height); + break; + case KeyPress: + { + char buf[100]; + KeySym keySym; + XComposeStatus stat; + XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); + if (keySym == XK_Escape) { + return; /* exit */ + } + else if (keySym == XK_r) { + rot += 1.0; + Redraw(dpy, win, rot); + } + else if (keySym == XK_a) { + anim = !anim; + } + else if (keySym == XK_R) { + rot -= 1.0; + Redraw(dpy, win, rot); + } + } + break; + default: + ; /*no-op*/ + } + } + else { + /* animate */ + rot += 1.0; + Redraw(dpy, win, rot); + } + } +} + + + +int +main(int argc, char *argv[]) +{ + Display *dpy; + GLXFBConfig pixmapConfig; + XVisualInfo *windowVis; + GLXPixmap gp; + Window win; + GLXContext ctx; + Pixmap p; + + dpy = OpenDisplay(); + + pixmapConfig = ChoosePixmapFBConfig(dpy); + windowVis = ChooseWindowVisual(dpy); + win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap"); + + gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p); + DrawPixmapImage(dpy, p, 512, 512); + + ctx = glXCreateContext(dpy, windowVis, NULL, True); + if (!ctx) { + printf("Couldn't create GLX context\n"); + exit(1); + } + + glXMakeCurrent(dpy, win, ctx); + + BindPixmapTexture(dpy, gp); + + EventLoop(dpy, win); + + return 0; +} -- cgit v1.2.3 From b4f8d4455bd73f025948498157f2076738819f43 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 21 May 2007 20:57:09 -0600 Subject: set texcoords depending on GLX_Y_INVERTED_EXT --- progs/xdemos/texture_from_pixmap.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'progs') diff --git a/progs/xdemos/texture_from_pixmap.c b/progs/xdemos/texture_from_pixmap.c index 2222956703..50870c4df4 100644 --- a/progs/xdemos/texture_from_pixmap.c +++ b/progs/xdemos/texture_from_pixmap.c @@ -41,6 +41,9 @@ #include +static float top, bottom; + + static Display * OpenDisplay(void) { @@ -71,7 +74,6 @@ ChoosePixmapFBConfig(Display *display) int screen = DefaultScreen(display); GLXFBConfig *fbconfigs; int i, nfbconfigs, value; - float top, bottom; fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs); for (i = 0; i < nfbconfigs; i++) { @@ -273,13 +275,13 @@ Redraw(Display *dpy, Window win, float rot) glRotatef(2.0 * rot, 1, 0, 0); glBegin(GL_QUADS); - glTexCoord2d(0.0, 0.0); + glTexCoord2d(0.0, bottom); glVertex2f(-1, -1); - glTexCoord2d(1.0, 0.0); + glTexCoord2d(1.0, bottom); glVertex2f( 1, -1); - glTexCoord2d(1.0, 1.0); + glTexCoord2d(1.0, top); glVertex2d(1.0, 1.0); - glTexCoord2d(0.0, 1.0); + glTexCoord2d(0.0, top); glVertex2f(-1.0, 1.0); glEnd(); -- cgit v1.2.3 From 0c5662acc7ac3bdd5712a7dabfc970d801117149 Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 29 May 2007 08:05:10 -0600 Subject: use glXGetProcAddress to get extension funcs --- progs/xdemos/texture_from_pixmap.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'progs') diff --git a/progs/xdemos/texture_from_pixmap.c b/progs/xdemos/texture_from_pixmap.c index 50870c4df4..ab215b0ac3 100644 --- a/progs/xdemos/texture_from_pixmap.c +++ b/progs/xdemos/texture_from_pixmap.c @@ -43,6 +43,9 @@ static float top, bottom; +static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL; +static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL; + static Display * OpenDisplay(void) @@ -60,10 +63,20 @@ OpenDisplay(void) screen = DefaultScreen(dpy); ext = glXQueryExtensionsString(dpy, screen); if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) { - printf("GLX_EXT_texture_from_pixmap not supported by GLX\n"); + fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n"); exit(1); } + glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC) + glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); + glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC) + glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT"); + + if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) { + fprintf(stderr, "glXGetProcAddress failed!\n"); + exit(1); + } + return dpy; } @@ -241,14 +254,14 @@ BindPixmapTexture(Display *dpy, GLXPixmap gp) glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - glXBindTexImageEXT(dpy, gp, GLX_FRONT_LEFT_EXT, NULL); + glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_TEXTURE_2D); /* - glXReleaseTexImageEXT (display, glxpixmap, GLX_FRONT_LEFT_EXT); + glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT); */ } -- cgit v1.2.3 From f575d4fa7f69a5de87c52002ffaf3e745634aff5 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 7 Jun 2007 11:59:42 -0700 Subject: Remove '#if defined' tests for ARB extensions. --- progs/demos/shadowtex.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'progs') diff --git a/progs/demos/shadowtex.c b/progs/demos/shadowtex.c index b11c6f5363..634d0b6572 100644 --- a/progs/demos/shadowtex.c +++ b/progs/demos/shadowtex.c @@ -389,10 +389,8 @@ ShowShadowMap(void) DisableTexgen(); /* interpret texture's depth values as luminance values */ -#if defined(GL_ARB_shadow) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); -#endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_POLYGON); @@ -457,9 +455,7 @@ Display(void) } if (DisplayMode == SHOW_DEPTH_MAPPING) { -#if defined(GL_ARB_shadow) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); -#endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); @@ -476,10 +472,8 @@ Display(void) } else { assert(DisplayMode == SHOW_SHADOWS); -#if defined(GL_ARB_shadow) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); -#endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_TEXTURE_2D); MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); @@ -572,10 +566,8 @@ Key(unsigned char key, int x, int y) if (Operator >= 8) Operator = 0; printf("Operator: %s\n", OperatorName[Operator]); -#if defined(GL_ARB_shadow) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, OperatorFunc[Operator]); -#endif } break; case 'p': @@ -651,23 +643,17 @@ Init(void) { static const GLfloat borderColor[4] = {1.0, 0.0, 0.0, 0.0}; -#if defined(GL_ARB_depth_texture) && defined(GL_ARB_shadow) if (!glutExtensionSupported("GL_ARB_depth_texture") || !glutExtensionSupported("GL_ARB_shadow")) { -#else - if (1) { -#endif printf("Sorry, this demo requires the GL_ARB_depth_texture and GL_ARB_shadow extensions\n"); exit(1); } printf("Using GL_ARB_depth_texture and GL_ARB_shadow\n"); -#if defined(GL_ARB_shadow_ambient) HaveShadowAmbient = glutExtensionSupported("GL_ARB_shadow_ambient"); if (HaveShadowAmbient) { printf("and GL_ARB_shadow_ambient\n"); } -#endif HaveEXTshadowFuncs = glutExtensionSupported("GL_EXT_shadow_funcs"); @@ -690,15 +676,12 @@ Init(void) glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); -#if defined(GL_ARB_shadow) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); -#endif + if (HaveShadowAmbient) { -#if defined(GL_ARB_shadow_ambient) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.3); -#endif } #if defined(GL_EXT_framebuffer_object) -- cgit v1.2.3 From 2260c245fd5798a6b3661c3a529654d9f577821d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 7 Jun 2007 12:09:44 -0700 Subject: Refactor shadow map modelview and projection code Explicitly store the modelview matrix and projection matrix used when the shadow map is created. These matrices only need be updated when RenderShadowMap is called. Previously, slightly different code was used to draw and project the shadow map. --- progs/demos/shadowtex.c | 72 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 22 deletions(-) (limited to 'progs') diff --git a/progs/demos/shadowtex.c b/progs/demos/shadowtex.c index 634d0b6572..e87edcf071 100644 --- a/progs/demos/shadowtex.c +++ b/progs/demos/shadowtex.c @@ -67,6 +67,9 @@ static GLboolean NeedNewShadowMap = GL_FALSE; static GLuint ShadowTexture, GrayTexture; static GLuint ShadowFBO; +static GLfloat lightModelview[16]; +static GLfloat lightProjection[16]; + static GLboolean HaveFBO = GL_FALSE; static GLboolean UseFBO = GL_FALSE; static GLboolean HavePackedDepthStencil = GL_FALSE; @@ -134,27 +137,56 @@ DrawScene(void) } -/* - * Load the GL_TEXTURE matrix with the projection from the light - * source's point of view. +/** + * Calculate modelview and project matrices for the light + * + * Stores the results in \c lightProjection (projection matrix) and + * \c lightModelview (modelview matrix). */ static void MakeShadowMatrix(const GLfloat lightPos[4], const GLfloat spotDir[3], GLfloat spotAngle, GLfloat shadowNear, GLfloat shadowFar) { - GLfloat d; - - glMatrixMode(GL_TEXTURE); + /* compute frustum to enclose spot light cone */ + const GLfloat d = shadowNear * tan(spotAngle); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); glLoadIdentity(); - glTranslatef(0.5, 0.5, 0.5 + Bias); - glScalef(0.5, 0.5, 0.5); - d = shadowNear * tan(spotAngle); glFrustum(-d, d, -d, d, shadowNear, shadowFar); + glGetFloatv(GL_PROJECTION_MATRIX, lightProjection); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); gluLookAt(lightPos[0], lightPos[1], lightPos[2], lightPos[0] + spotDir[0], lightPos[1] + spotDir[1], lightPos[2] + spotDir[2], - 0, 1, 0); + 0.0, 1.0, 0.0); + glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview); + glPopMatrix(); +} + + +/** + * Load \c GL_TEXTURE matrix with light's MVP matrix. + */ +static void SetShadowTextureMatrix(void) +{ + static const GLfloat biasMatrix[16] = { + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0, + }; + + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(biasMatrix); + glTranslatef(0.0, 0.0, Bias); + glMultMatrixf(lightProjection); + glMultMatrixf(lightModelview); glMatrixMode(GL_MODELVIEW); } @@ -258,7 +290,6 @@ RenderShadowMap(void) { GLenum depthFormat; /* GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT */ GLenum depthType; /* GL_UNSIGNED_INT_24_8_EXT or GL_UNSIGNED_INT */ - float d; if (WindowWidth >= 1024 && WindowHeight >= 1024) { ShadowTexWidth = ShadowTexHeight = 1024; @@ -283,17 +314,11 @@ RenderShadowMap(void) depthType = GL_UNSIGNED_INT; } - /* compute frustum to enclose spot light cone */ - d = ShadowNear * tan(SpotAngle); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-d, d, -d, d, ShadowNear, ShadowFar); + glLoadMatrixf(lightProjection); + glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(LightPos[0], LightPos[1], LightPos[2], /* from */ - 0, 0, 0, /* target */ - 0, 1, 0); /* up */ + glLoadMatrixf(lightModelview); if (UseFBO) { GLenum fbo_status; @@ -418,6 +443,7 @@ Display(void) LightPos, SpotDir); if (NeedNewShadowMap) { + MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); RenderShadowMap(); NeedNewShadowMap = GL_FALSE; } @@ -458,7 +484,8 @@ Display(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); - MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); + + SetShadowTextureMatrix(); EnableIdentityTexgen(); } else if (DisplayMode == SHOW_DISTANCE) { @@ -476,7 +503,8 @@ Display(void) GL_COMPARE_R_TO_TEXTURE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_TEXTURE_2D); - MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar); + + SetShadowTextureMatrix(); EnableIdentityTexgen(); } -- cgit v1.2.3 From 359c6eada7172d61ed52091dcc8f406ad0598b8a Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Thu, 7 Jun 2007 12:12:14 -0700 Subject: Add support for shadow mapping with vertex and fragment programs --- progs/demos/shadowtex.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 4 deletions(-) (limited to 'progs') diff --git a/progs/demos/shadowtex.c b/progs/demos/shadowtex.c index e87edcf071..59253e8c1e 100644 --- a/progs/demos/shadowtex.c +++ b/progs/demos/shadowtex.c @@ -9,6 +9,7 @@ * Added GL_EXT_packed_depth_stencil support on 15 March 2006. * Added GL_EXT_framebuffer_object support on 27 March 2006. * Removed old SGIX extension support on 5 April 2006. + * Added vertex / fragment program support on 7 June 2007 (Ian Romanick). * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include "showbuffer.h" @@ -70,8 +72,24 @@ static GLuint ShadowFBO; static GLfloat lightModelview[16]; static GLfloat lightProjection[16]; +static GLuint vert_prog; +static GLuint frag_progs[3]; +static GLuint curr_frag = 0; +static GLuint max_frag = 1; + +#define NUM_FRAG_MODES 3 +static const char *FragProgNames[] = { + "fixed-function", + "program without \"OPTION ARB_fragment_program_shadow\"", + "program with \"OPTION ARB_fragment_program_shadow\"", +}; + static GLboolean HaveFBO = GL_FALSE; static GLboolean UseFBO = GL_FALSE; +static GLboolean HaveVP = GL_FALSE; +static GLboolean HaveFP = GL_FALSE; +static GLboolean HaveFP_Shadow = GL_FALSE; +static GLboolean UseVP = GL_FALSE; static GLboolean HavePackedDepthStencil = GL_FALSE; static GLboolean UsePackedDepthStencil = GL_FALSE; static GLboolean HaveEXTshadowFuncs = GL_FALSE; @@ -94,6 +112,103 @@ static GLuint DisplayMode; +#define MAT4_MUL(dest_vec, src_mat, src_vec) \ + "DP4 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \ + "DP4 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \ + "DP4 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" \ + "DP4 " dest_vec ".w, " src_mat "[3], " src_vec ";\n" + +#define MAT3_MUL(dest_vec, src_mat, src_vec) \ + "DP3 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \ + "DP3 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \ + "DP3 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" + +#define NORMALIZE(dest, src) \ + "DP3 " dest ".w, " src ", " src ";\n" \ + "RSQ " dest ".w, " dest ".w;\n" \ + "MUL " dest ", " src ", " dest ".w;\n" + +/** + * Vertex program for shadow mapping. + */ +static const char vert_code[] = + "!!ARBvp1.0\n" + "ATTRIB iPos = vertex.position;\n" + "ATTRIB iNorm = vertex.normal;\n" + + "PARAM mvinv[4] = { state.matrix.modelview.invtrans };\n" + "PARAM mvp[4] = { state.matrix.mvp };\n" + "PARAM mv[4] = { state.matrix.modelview };\n" + "PARAM texmat[4] = { state.matrix.texture[0] };\n" + "PARAM lightPos = state.light[0].position;\n" + "PARAM ambientCol = state.lightprod[0].ambient;\n" + "PARAM diffuseCol = state.lightprod[0].diffuse;\n" + + "TEMP n, lightVec;\n" + "ALIAS V = lightVec;\n" + "ALIAS NdotL = n;\n" + + "OUTPUT oPos = result.position;\n" + "OUTPUT oColor = result.color;\n" + "OUTPUT oTex = result.texcoord[0];\n" + + /* Transform the vertex to clip coordinates. */ + MAT4_MUL("oPos", "mvp", "iPos") + + /* Transform the vertex to eye coordinates. */ + MAT4_MUL("V", "mv", "iPos") + + /* Transform the vertex to projected light coordinates. */ + MAT4_MUL("oTex", "texmat", "iPos") + + /* Transform the normal to eye coordinates. */ + MAT3_MUL("n", "mvinv", "iNorm") + + /* Calculate the vector from the vertex to the light in eye + * coordinates. + */ + "SUB lightVec, lightPos, V;\n" + NORMALIZE("lightVec", "lightVec") + + /* Compute diffuse lighting coefficient. + */ + "DP3 NdotL.x, n, lightVec;\n" + "MAX NdotL.x, NdotL.x, {0.0};\n" + "MIN NdotL.x, NdotL.x, {1.0};\n" + + /* Accumulate color contributions. + */ + "MOV oColor, diffuseCol;\n" + "MAD oColor.xyz, NdotL.x, diffuseCol, ambientCol;\n" + "END\n" + ; + +static const char frag_code[] = + "!!ARBfp1.0\n" + + "TEMP shadow, temp;\n" + + "TXP shadow, fragment.texcoord[0], texture[0], 2D;\n" + "RCP temp.x, fragment.texcoord[0].w;\n" + "MUL temp.x, temp.x, fragment.texcoord[0].z;\n" + "SGE shadow, shadow.x, temp.x;\n" + "MUL result.color.rgb, fragment.color, shadow.x;\n" + "MOV result.color.a, fragment.color;\n" + "END\n" + ; + +static const char frag_shadow_code[] = + "!!ARBfp1.0\n" + "OPTION ARB_fragment_program_shadow;\n" + + "TEMP shadow;\n" + + "TXP shadow, fragment.texcoord[0], texture[0], SHADOW2D;\n" + "MUL result.color.rgb, fragment.color, shadow.x;\n" + "MOV result.color.a, fragment.color.a;\n" + "END\n" + ; + static void DrawScene(void) { @@ -501,17 +616,40 @@ Display(void) assert(DisplayMode == SHOW_SHADOWS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (curr_frag > 0) { + glEnable(GL_FRAGMENT_PROGRAM_ARB); + } + else { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } glEnable(GL_TEXTURE_2D); SetShadowTextureMatrix(); - EnableIdentityTexgen(); + + if (UseVP) { + glEnable(GL_VERTEX_PROGRAM_ARB); + } + else { + glEnable(GL_LIGHTING); + EnableIdentityTexgen(); + } } DrawScene(); - DisableTexgen(); - glDisable(GL_TEXTURE_1D); + if (UseVP) { + glDisable(GL_VERTEX_PROGRAM_ARB); + } + else { + DisableTexgen(); + glDisable(GL_LIGHTING); + } + + if (curr_frag > 0) { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + } + glDisable(GL_TEXTURE_2D); } @@ -583,6 +721,14 @@ Key(unsigned char key, int x, int y) case 'm': DisplayMode = SHOW_DEPTH_MAPPING; break; + case 'M': + curr_frag = (1 + curr_frag) % max_frag; + printf("Using fragment %s\n", FragProgNames[curr_frag]); + + if (HaveFP) { + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, frag_progs[curr_frag]); + } + break; case 'n': case 's': case ' ': @@ -612,6 +758,11 @@ Key(unsigned char key, int x, int y) NeedNewShadowMap = GL_TRUE; } break; + case 'v': + UseVP = !UseVP && HaveVP; + printf("Using vertex %s mode.\n", + UseVP ? "program" : "fixed-function"); + break; case 'z': Zrot -= step; break; @@ -666,6 +817,42 @@ SpecialKey(int key, int x, int y) } +/* A helper for finding errors in program strings */ +static int FindLine( const char *program, int position ) +{ + int i, line = 1; + for (i = 0; i < position; i++) { + if (program[i] == '\n') + line++; + } + return line; +} + + +static GLuint +compile_program(GLenum target, const char *code) +{ + GLuint p; + GLint errorPos; + + + glGenProgramsARB(1, & p); + + glBindProgramARB(target, p); + glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(code), code); + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos); + if (glGetError() != GL_NO_ERROR || errorPos != -1) { + int l = FindLine(code, errorPos); + printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l, + (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + exit(0); + } + + glBindProgramARB(target, 0); + return p; +} + static void Init(void) { @@ -678,6 +865,10 @@ Init(void) } printf("Using GL_ARB_depth_texture and GL_ARB_shadow\n"); + HaveVP = glutExtensionSupported("GL_ARB_vertex_program"); + HaveFP = glutExtensionSupported("GL_ARB_fragment_program"); + HaveFP_Shadow = glutExtensionSupported("GL_ARB_fragment_program_shadow"); + HaveShadowAmbient = glutExtensionSupported("GL_ARB_shadow_ambient"); if (HaveShadowAmbient) { printf("and GL_ARB_shadow_ambient\n"); @@ -744,6 +935,25 @@ Init(void) 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image); } + if (HaveVP) { + vert_prog = compile_program(GL_VERTEX_PROGRAM_ARB, vert_code); + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vert_prog); + } + + max_frag = 1; + frag_progs[0] = 0; + + if (HaveFP) { + frag_progs[1] = compile_program(GL_FRAGMENT_PROGRAM_ARB, frag_code); + max_frag = 2; + } + + if (HaveFP && HaveFP_Shadow) { + frag_progs[2] = compile_program(GL_FRAGMENT_PROGRAM_ARB, + frag_shadow_code); + max_frag = 3; + } + glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); @@ -762,6 +972,8 @@ PrintHelp(void) printf(" f = toggle nearest/bilinear texture filtering\n"); printf(" b/B = decrease/increase shadow map Z bias\n"); printf(" p = toggle use of packed depth/stencil\n"); + printf(" M = cycle through fragment program modes\n"); + printf(" v = toggle vertex program modes\n"); printf(" cursor keys = rotate scene\n"); printf(" + cursor keys = rotate light source\n"); if (HaveEXTshadowFuncs) -- cgit v1.2.3 From 5e9cff0b97b1301c2b13dbfe2570ddb4551f814f Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 8 Jun 2007 13:02:14 -0600 Subject: disable shader program before glDrawPixels --- progs/tests/drawbuffers.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'progs') diff --git a/progs/tests/drawbuffers.c b/progs/tests/drawbuffers.c index 8583bac0dd..d2e826fadf 100644 --- a/progs/tests/drawbuffers.c +++ b/progs/tests/drawbuffers.c @@ -19,6 +19,7 @@ static int Win; static int Width = 400, Height = 400; static GLuint FBobject, RBobjects[3]; static GLfloat Xrot = 0.0, Yrot = 0.0; +static GLuint Program; static void @@ -40,6 +41,8 @@ Display(void) GL_COLOR_ATTACHMENT1_EXT }; + glUseProgram_func(Program); + /* draw to user framebuffer */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject); @@ -75,6 +78,7 @@ Display(void) buffer + Width * Height / 2 * 4); /* draw to window */ + glUseProgram_func(0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glWindowPos2iARB(0, 0); glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); @@ -243,15 +247,15 @@ SetupShaders(void) " gl_FragData[1] = vec4(1.0) - gl_Color; \n" "}\n"; - GLuint fragShader, program; + GLuint fragShader; fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); - program = glCreateProgram_func(); + Program = glCreateProgram_func(); - glAttachShader_func(program, fragShader); - glLinkProgram_func(program); - CheckLink(program); - glUseProgram_func(program); + glAttachShader_func(Program, fragShader); + glLinkProgram_func(Program); + CheckLink(Program); + glUseProgram_func(Program); } -- cgit v1.2.3 From 39d221ef142d24441e5d741d0902624020deebb8 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 8 Jun 2007 13:10:01 -0600 Subject: fix glReadPixels parameters to handle odd-width windows correctly --- progs/tests/drawbuffers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'progs') diff --git a/progs/tests/drawbuffers.c b/progs/tests/drawbuffers.c index d2e826fadf..5e89569380 100644 --- a/progs/tests/drawbuffers.c +++ b/progs/tests/drawbuffers.c @@ -74,8 +74,9 @@ Display(void) buffer); /* top half = colorbuffer 1 */ glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); - glReadPixels(0, Height/2, Width, Height / 2, GL_RGBA, GL_UNSIGNED_BYTE, - buffer + Width * Height / 2 * 4); + glReadPixels(0, Height/2, Width, Height - Height / 2, + GL_RGBA, GL_UNSIGNED_BYTE, + buffer + Width * (Height / 2) * 4); /* draw to window */ glUseProgram_func(0); -- cgit v1.2.3 From 6a3ed5eb9655ef7e9f188077375f882a7d74a7ce Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 21 Jun 2007 18:11:29 -0600 Subject: Random state-change / primitive rendering. Good for hammering on a driver... --- progs/tests/Makefile | 1 + progs/tests/random.c | 457 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 458 insertions(+) create mode 100644 progs/tests/random.c (limited to 'progs') diff --git a/progs/tests/Makefile b/progs/tests/Makefile index b506db3e7b..9016efe9e7 100644 --- a/progs/tests/Makefile +++ b/progs/tests/Makefile @@ -55,6 +55,7 @@ SOURCES = \ pbo.c \ prog_parameter.c \ projtex.c \ + random.c \ readrate.c \ seccolor.c \ sharedtex.c \ diff --git a/progs/tests/random.c b/progs/tests/random.c new file mode 100644 index 0000000000..d52c338e0e --- /dev/null +++ b/progs/tests/random.c @@ -0,0 +1,457 @@ +/** + * Random rendering, to check for crashes, hangs, etc. + * + * Brian Paul + * 21 June 2007 + */ + +#define GL_GLEXT_PROTOTYPES + +#include +#include +#include +#include +#include +#include + +static int Win; +static GLboolean Anim = GL_TRUE; +static int Width = 200, Height = 200; +static int DB = 0; +static int MinVertexCount = 0, MaxVertexCount = 1000; +static int Count = 0; + +struct vertex +{ + int type; + float v[4]; +}; + +static int BufferSize = 10000; +static struct vertex *Vbuffer = NULL; +static int Vcount, Vprim; + +enum { + BEGIN, + END, + VERTEX2, + VERTEX3, + VERTEX4, + COLOR3, + COLOR4, + TEX2, + TEX3, + TEX4, + SECCOLOR3, + NORMAL3 +}; + + + +/** + * This can be called from within gdb after a crash: + * (gdb) call ReportState() + */ +static void +ReportState(void) +{ + static const struct { + GLenum token; + char *str; + GLenum type; + } state [] = { + { GL_ALPHA_TEST, "GL_ALPHA_TEST", GL_INT }, + { GL_BLEND, "GL_BLEND", GL_INT }, + { GL_CLIP_PLANE0, "GL_CLIP_PLANE0", GL_INT }, + { GL_DEPTH_TEST, "GL_DEPTH_TEST", GL_INT }, + { GL_LIGHTING, "GL_LIGHTING", GL_INT }, + { GL_LINE_WIDTH, "GL_LINE_WIDTH", GL_FLOAT }, + { GL_POINT_SIZE, "GL_POINT_SIZE", GL_FLOAT }, + { GL_SHADE_MODEL, "GL_SHADE_MODEL", GL_INT }, + { GL_SCISSOR_TEST, "GL_SCISSOR_TEST", GL_INT }, + { 0, NULL, 0 } + }; + + GLint i; + + for (i = 0; state[i].token; i++) { + if (state[i].type == GL_INT) { + GLint v; + glGetIntegerv(state[i].token, &v); + printf("%s = %d\n", state[i].str, v); + } + else { + GLfloat v; + glGetFloatv(state[i].token, &v); + printf("%s = %f\n", state[i].str, v); + } + } +} + +static void +PrintVertex(const char *f, const struct vertex *v, int sz) +{ + int i; + printf("%s(", f); + for (i = 0; i < sz; i++) { + printf("%g%s", v->v[i], (i == sz-1) ? "" : ", "); + } + printf(");\n"); +} + +/** + * This can be called from within gdb after a crash: + * (gdb) call ReportState() + */ +static void +LastPrim(void) +{ + int i; + for (i = 0; i < Vcount; i++) { + switch (Vbuffer[i].type) { + case BEGIN: + printf("glBegin(%d);\n", (int) Vbuffer[i].v[0]); + break; + case END: + printf("glEnd();\n"); + break; + case VERTEX2: + PrintVertex("glVertex2f", Vbuffer + i, 2); + break; + case VERTEX3: + PrintVertex("glVertex3f", Vbuffer + i, 3); + break; + case VERTEX4: + PrintVertex("glVertex4f", Vbuffer + i, 4); + break; + case COLOR3: + PrintVertex("glColor3f", Vbuffer + i, 3); + break; + case COLOR4: + PrintVertex("glColor4f", Vbuffer + i, 4); + break; + case TEX2: + PrintVertex("glTexCoord2f", Vbuffer + i, 2); + break; + case TEX3: + PrintVertex("glTexCoord3f", Vbuffer + i, 3); + break; + case TEX4: + PrintVertex("glTexCoord4f", Vbuffer + i, 4); + break; + case SECCOLOR3: + PrintVertex("glSecondaryColor3f", Vbuffer + i, 3); + break; + case NORMAL3: + PrintVertex("glNormal3f", Vbuffer + i, 3); + break; + default: + abort(); + } + } +} + + +static int +RandomInt(int max) +{ + if (max == 0) + return 0; + return rand() % max; +} + +static float +RandomFloat(float min, float max) +{ + int k = rand() % 10000; + float x = min + (max - min) * k / 10000.0; + return x; +} + +/* + * Return true if random number in [0,1] is <= percentile. + */ +static GLboolean +RandomChoice(float percentile) +{ + return RandomFloat(0.0, 1.0) <= percentile; +} + +static void +RandomStateChange(void) +{ + int k = RandomInt(19); + switch (k) { + case 0: + glEnable(GL_BLEND); + break; + case 1: + glDisable(GL_BLEND); + break; + case 2: + glEnable(GL_ALPHA_TEST); + break; + case 3: + glEnable(GL_ALPHA_TEST); + break; + case 4: + glEnable(GL_DEPTH_TEST); + break; + case 5: + glEnable(GL_DEPTH_TEST); + break; + case 6: + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + break; + case 7: + glPointSize(10.0); + break; + case 8: + glPointSize(1.0); + break; + case 9: + glLineWidth(10.0); + break; + case 10: + glLineWidth(1.0); + break; + case 11: + glEnable(GL_LIGHTING); + break; + case 12: + glDisable(GL_LIGHTING); + break; + case 13: + glEnable(GL_SCISSOR_TEST); + break; + case 14: + glDisable(GL_SCISSOR_TEST); + break; + case 15: + glEnable(GL_CLIP_PLANE0); + break; + case 16: + glDisable(GL_CLIP_PLANE0); + break; + case 17: + glShadeModel(GL_FLAT); + break; + case 18: + glShadeModel(GL_SMOOTH); + break; + } +} + + +static void +RandomPrimitive(void) +{ + int i; + int len = MinVertexCount + RandomInt(MaxVertexCount - MinVertexCount); + + Vprim = RandomInt(10); + + glBegin(Vprim); + Vbuffer[Vcount].type = BEGIN; + Vbuffer[Vcount].v[0] = Vprim; + Vcount++; + + for (i = 0; i < len; i++) { + Vbuffer[Vcount].v[0] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[1] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[2] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[3] = RandomFloat(-3, 3); + int k = RandomInt(9); + switch (k) { + case 0: + glVertex2fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX2; + break; + case 1: + glVertex3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX3; + break; + case 2: + glVertex4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX4; + break; + case 3: + glColor3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = COLOR3; + break; + case 4: + glColor4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = COLOR4; + break; + case 5: + glTexCoord2fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX2; + break; + case 6: + glTexCoord3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX3; + break; + case 7: + glTexCoord4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX4; + break; + case 8: + glSecondaryColor3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = SECCOLOR3; + break; + case 9: + glNormal3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = NORMAL3; + break; + default: + abort(); + } + Vcount++; + + if (Vcount >= BufferSize - 2) { + /* reset */ + Vcount = 0; + } + } + + Vbuffer[Vcount++].type = END; + + glEnd(); +} + + +static void +RandomDraw(void) +{ + int i; + GLboolean dlist = RandomChoice(0.1); + if (dlist) + glNewList(1, GL_COMPILE); + for (i = 0; i < 3; i++) { + RandomStateChange(); + } + RandomPrimitive(); + + if (dlist) { + glEndList(); + glCallList(1); + } +} + + +static void +Idle(void) +{ + glutPostRedisplay(); +} + + +static void +Draw(void) +{ +#if 1 + RandomDraw(); + Count++; +#else + /* cut & paste temp code here */ +#endif + + assert(glGetError() == 0); + + if (DB) + glutSwapBuffers(); + else + glFinish(); +} + + +static void +Reshape(int width, int height) +{ + Width = width; + Height = height; + glViewport(0, 0, width, height); + glScissor(20, 20, Width-40, Height-40); + 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); +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case 27: + glutDestroyWindow(Win); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +Init(void) +{ + static const GLdouble plane[4] = {1, 1, 0, 0}; + glDrawBuffer(GL_FRONT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_LIGHT0); + glClipPlane(GL_CLIP_PLANE0, plane); + + Vbuffer = (struct vertex *) + malloc(BufferSize * sizeof(struct vertex)); + + /* silence warnings */ + (void) ReportState; + (void) LastPrim; +} + + +static void +ParseArgs(int argc, char *argv[]) +{ + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-s") == 0) { + int j = atoi(argv[i + 1]); + printf("Random seed value: %d\n", j); + srand(j); + i++; + } + else if (strcmp(argv[i], "-a") == 0) { + i++; + MinVertexCount = atoi(argv[i]); + } + else if (strcmp(argv[i], "-b") == 0) { + i++; + MaxVertexCount = atoi(argv[i]); + } + } +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + Win = glutCreateWindow(argv[0]); + ParseArgs(argc, argv); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + if (Anim) + glutIdleFunc(Idle); + Init(); + glutMainLoop(); + return 0; +} -- cgit v1.2.3 From 3b10f50efb0eaad546e8d1aa9316e43914cd6c25 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 28 Jun 2007 07:15:11 -0600 Subject: use larger point/sprite size --- progs/demos/spriteblast.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'progs') diff --git a/progs/demos/spriteblast.c b/progs/demos/spriteblast.c index f0d3d0dfd4..5ad8e4d9a9 100644 --- a/progs/demos/spriteblast.c +++ b/progs/demos/spriteblast.c @@ -333,13 +333,13 @@ menu(int option) smooth = 0; break; case 10: - glPointSize(4.0); + glPointSize(16.0); break; case 11: - glPointSize(8.0); + glPointSize(32.0); break; case 12: - glPointSize(16.0); + glPointSize(64.0); break; case 13: spin = 1 - spin; @@ -411,19 +411,19 @@ key(unsigned char c, int x, int y) glutPostRedisplay(); break; case '1': - glPointSize(2.0); + glPointSize(16.0); glutPostRedisplay(); break; case '2': - glPointSize(4.0); + glPointSize(32.0); glutPostRedisplay(); break; case '3': - glPointSize(8.0); + glPointSize(64.0); glutPostRedisplay(); break; case '4': - glPointSize(16.0); + glPointSize(128.0); glutPostRedisplay(); break; case 27: @@ -526,9 +526,9 @@ main(int argc, char **argv) glutAddMenuEntry("Threshold 10", 7); glutAddMenuEntry("Point smooth on", 8); glutAddMenuEntry("Point smooth off", 9); - glutAddMenuEntry("Point size 4", 10); - glutAddMenuEntry("Point size 8", 11); - glutAddMenuEntry("Point size 16", 12); + glutAddMenuEntry("Point size 16", 10); + glutAddMenuEntry("Point size 32", 11); + glutAddMenuEntry("Point size 64", 12); glutAddMenuEntry("Toggle spin", 13); glutAddMenuEntry("200 points ", 14); glutAddMenuEntry("500 points ", 15); @@ -544,7 +544,7 @@ main(int argc, char **argv) glEnable(GL_DEPTH_TEST); glEnable(GL_POINT_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glPointSize(16.0); + glPointSize(32.0); #ifdef GL_ARB_point_parameters glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, theQuad); #endif -- cgit v1.2.3 From e8e5d9effe879482c0e7b65bfed9eafde0803ae0 Mon Sep 17 00:00:00 2001 From: Brian Date: Wed, 4 Jul 2007 09:23:12 -0600 Subject: support more modes, added -f cmd line option --- progs/fbdev/glfbdevtest.c | 105 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 15 deletions(-) (limited to 'progs') diff --git a/progs/fbdev/glfbdevtest.c b/progs/fbdev/glfbdevtest.c index a461c55e2f..6d9f807030 100644 --- a/progs/fbdev/glfbdevtest.c +++ b/progs/fbdev/glfbdevtest.c @@ -23,11 +23,21 @@ #include #include -#define DEFAULT_DEPTH 8 + +/** + * Choose one of these modes + */ +/*static const int XRes = 1280, YRes = 1024, Hz = 75;*/ +/*static const int XRes = 1280, YRes = 1024, Hz = 70;*/ +/*static const int XRes = 1280, YRes = 1024, Hz = 60;*/ +static const int XRes = 1024, YRes = 768, Hz = 70; + +static int DesiredDepth = 32; + +static int NumFrames = 100; static struct fb_fix_screeninfo FixedInfo; static struct fb_var_screeninfo VarInfo, OrigVarInfo; -static int DesiredDepth = 0; static int OriginalVT = -1; static int ConsoleFD = -1; static int FrameBufferFD = -1; @@ -227,7 +237,6 @@ initialize_fbdev( void ) VarInfo = OrigVarInfo; /* set the depth, resolution, etc */ - DesiredDepth = 32; if (DesiredDepth) VarInfo.bits_per_pixel = DesiredDepth; @@ -251,16 +260,60 @@ initialize_fbdev( void ) VarInfo.blue.length = 8; VarInfo.transp.length = 8; } - /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */ - VarInfo.xres_virtual = VarInfo.xres = 1280; - VarInfo.yres_virtual = VarInfo.yres = 1024; - VarInfo.pixclock = 7408; - VarInfo.left_margin = 248; - VarInfo.right_margin = 16; - VarInfo.upper_margin = 38; - VarInfo.lower_margin = 1; - VarInfo.hsync_len = 144; - VarInfo.vsync_len = 3; + + /* timing values taken from /etc/fb.modes */ + if (XRes == 1280 && YRes == 1024) { + VarInfo.xres_virtual = VarInfo.xres = XRes; + VarInfo.yres_virtual = VarInfo.yres = YRes; + if (Hz == 75) { + VarInfo.pixclock = 7408; + VarInfo.left_margin = 248; + VarInfo.right_margin = 16; + VarInfo.upper_margin = 38; + VarInfo.lower_margin = 1; + VarInfo.hsync_len = 144; + VarInfo.vsync_len = 3; + } + else if (Hz == 70) { + VarInfo.pixclock = 7937; + VarInfo.left_margin = 216; + VarInfo.right_margin = 80; + VarInfo.upper_margin = 36; + VarInfo.lower_margin = 1; + VarInfo.hsync_len = 112; + VarInfo.vsync_len = 5; + } + else if (Hz == 60) { + VarInfo.pixclock = 9260; + VarInfo.left_margin = 248; + VarInfo.right_margin = 48; + VarInfo.upper_margin = 38; + VarInfo.lower_margin = 1; + VarInfo.hsync_len = 112; + VarInfo.vsync_len = 3; + } + else { + fprintf(stderr, "invalid rate for 1280x1024\n"); + exit(1); + } + } + else if (XRes == 1024 && YRes == 768 && Hz == 70) { + VarInfo.xres_virtual = VarInfo.xres = XRes; + VarInfo.yres_virtual = VarInfo.yres = YRes; + if (Hz == 70) { + VarInfo.pixclock = 13334; + VarInfo.left_margin = 144; + VarInfo.right_margin = 24; + VarInfo.upper_margin = 29; + VarInfo.lower_margin = 3; + VarInfo.hsync_len = 136; + VarInfo.vsync_len = 6; + } + else { + fprintf(stderr, "invalid rate for 1024x768\n"); + exit(1); + } + } VarInfo.xoffset = 0; VarInfo.yoffset = 0; @@ -338,7 +391,7 @@ initialize_fbdev( void ) printf("MMIOAddress = %p\n", MMIOAddress); /* try out some simple MMIO register reads */ - if (1) + if (0) { typedef unsigned int CARD32; typedef unsigned char CARD8; @@ -452,6 +505,7 @@ gltest( void ) GLFBDevVisualPtr vis; int bytes, r, g, b, a; float ang; + int i; printf("GLFBDEV_VENDOR = %s\n", glFBDevGetString(GLFBDEV_VENDOR)); printf("GLFBDEV_VERSION = %s\n", glFBDevGetString(GLFBDEV_VERSION)); @@ -491,13 +545,17 @@ gltest( void ) glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); - for (ang = 0; ang <= 180; ang += 15) { + printf("Drawing %d frames...\n", NumFrames); + + ang = 0.0; + for (i = 0; i < NumFrames; i++) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(ang, 1, 0, 0); doughnut(1, 3, 40, 20); glPopMatrix(); glFBDevSwapBuffers(buf); + ang += 15.0; } /* clean up */ @@ -510,12 +568,29 @@ gltest( void ) } +static void +parse_args(int argc, char *argv[]) +{ + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-f") == 0) { + NumFrames = atoi(argv[i+1]); + i++; + } + } +} + + int main( int argc, char *argv[] ) { signal(SIGUSR1, signal_handler); /* exit if someone tries a vt switch */ signal(SIGSEGV, signal_handler); /* catch segfaults */ + parse_args(argc, argv); + + printf("Setting mode to %d x %d @ %d Hz, %d bpp\n", XRes, YRes, Hz, DesiredDepth); initialize_fbdev(); gltest(); shutdown_fbdev(); -- cgit v1.2.3