/* * Test the mini GLX interface. */ #include #include #include #include #include #define USE_MINI_GLX 1 #if USE_MINI_GLX #include #else #include #endif #include "../util/writebuf.c" static GLXContext ctx; static GLuint NumFrames = 100; static GLuint NumDisplays = 1; static GLboolean Texture = GL_FALSE; static GLboolean SingleBuffer = GL_FALSE; static GLboolean Sleeps = GL_TRUE; static void rect(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { glBegin(GL_QUADS); glTexCoord2f(0, 0); glColor3f(0, 0, 1); glVertex2f(x1, y1); glTexCoord2f(1, 0); glColor3f(1, 0, 0); glVertex2f(x2, y1); glTexCoord2f(1, 1); glColor3f(0, 1, 0); glVertex2f(x2, y2); glTexCoord2f(0, 1); glColor3f(0, 0, 0); glVertex2f(x1, y2); glEnd(); } static void redraw(Display *dpy, Window w, int rot) { GLfloat a; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(rot, 0, 0, 1); glScalef(.5, .5, .5); for (a = 0.0; a < 360.0; a += 30.0) { glPushMatrix(); glRotatef(a, 0, 0, 1); glRotatef(40, 1, 0, 0); glColor3f(a / 360.0, 1-a/360.0, 0); rect(0.3, -0.25, 1.5, 0.25); glPopMatrix(); } glPopMatrix(); if (SingleBuffer) glFlush(); else glXSwapBuffers(dpy, w); } static Window make_window(Display *dpy, unsigned int width, unsigned int height) { int attrib_single[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, None }; int attrib_double[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None }; int *attrib = SingleBuffer ? attrib_single : attrib_double; int scrnum = 0; XSetWindowAttributes attr; unsigned long mask; Window root; Window win; XVisualInfo *visinfo; root = RootWindow(dpy, scrnum); if (!(visinfo = glXChooseVisual(dpy, scrnum, attrib))) { printf("Error: couldn't get an RGB, Double-buffered visual\n"); exit(1); } if (!(ctx = glXCreateContext(dpy, visinfo, NULL, True))) { printf("Error: glXCreateContext failed\n"); exit(1); } /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); if (!win) { printf("Error: XCreateWindow failed\n"); exit(1); } glXMakeCurrent(dpy, win, ctx); glViewport(0, 0, width, height); return win; } static void event_loop(Display *dpy, Window win) { int i; printf("Drawing %d frames\n", NumFrames); for (i = 0; i < NumFrames; i++) { redraw(dpy, win, -i*2); if (i == 1) { glReadBuffer(GL_BACK); WritePPMFile("frame1.ppm", 800,600); } if (Sleeps) { usleep(20000); } } } static int runtest(void) { Display *dpy; Window win; dpy = XOpenDisplay(NULL); if (!dpy) { printf("Error: XOpenDisplay failed\n"); return 1; } win = make_window(dpy, 800, 600); srand(getpid()); /* init GL state */ glClearColor(0.5, 0.5, 0.5, 1.0); glEnable(GL_DEPTH_TEST); if (Texture) { GLubyte image[16][16][4]; GLint i, j; for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { if (((i / 2) ^ (j / 2)) & 1) { image[i][j][0] = 255; image[i][j][1] = 255; image[i][j][2] = 255; image[i][j][3] = 255; } else { image[i][j][0] = 128; image[i][j][1] = 128; image[i][j][2] = 128; image[i][j][3] = 128; } } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_TEXTURE_2D); } if (SingleBuffer) { glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); } else { glDrawBuffer(GL_BACK); } XMapWindow(dpy, win); /* wait for window to get mapped */ { XEvent e; while (1) { XNextEvent(dpy, &e); if (e.type == MapNotify && e.xmap.window == win) { break; } } } event_loop(dpy, win); glXDestroyContext(dpy, ctx); XDestroyWindow(dpy, win); XCloseDisplay(dpy); return 0; } static void usage(void) { printf("Usage:\n"); printf(" -f N render N frames (default %d)\n", NumFrames); printf(" -d N do N display cycles\n"); printf(" -t texturing\n"); printf(" -s single buffering\n"); printf(" -n no usleep() delay\n"); } 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++; } else if (strcmp(argv[i], "-d") == 0) { NumDisplays = atoi(argv[i + 1]); i++; } else if (strcmp(argv[i], "-n") == 0) { Sleeps = GL_FALSE; } else if (strcmp(argv[i], "-s") == 0) { SingleBuffer = GL_TRUE; } else if (strcmp(argv[i], "-t") == 0) { Texture = GL_TRUE; } else { usage(); exit(1); } } } int main(int argc, char *argv[]) { int i; parse_args(argc, argv); for (i = 0; i < NumDisplays; i++) { if (runtest() != 0) break; } return 0; }