132001f49Smrg/*
232001f49Smrg * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
332001f49Smrg *
432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
532001f49Smrg * copy of this software and associated documentation files (the "Software"),
632001f49Smrg * to deal in the Software without restriction, including without limitation
732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
932001f49Smrg * Software is furnished to do so, subject to the following conditions:
1032001f49Smrg *
1132001f49Smrg * The above copyright notice and this permission notice shall be included
1232001f49Smrg * in all copies or substantial portions of the Software.
1332001f49Smrg *
1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1532001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1732001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1832001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1932001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2032001f49Smrg */
2132001f49Smrg
2232001f49Smrg/*
2332001f49Smrg * Version of glxgears that creates/destroys the rendering context for each
2432001f49Smrg * frame.  Also periodically destroy/recreate the window.
2532001f49Smrg * Good for finding memory leaks, etc.
2632001f49Smrg *
2732001f49Smrg * Command line options:
2832001f49Smrg *    -info      print GL implementation information
2932001f49Smrg *
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg
3332001f49Smrg#include <assert.h>
3432001f49Smrg#include <math.h>
3532001f49Smrg#include <stdlib.h>
3632001f49Smrg#include <stdio.h>
3732001f49Smrg#include <string.h>
3832001f49Smrg#include <X11/Xlib.h>
3932001f49Smrg#include <X11/keysym.h>
4032001f49Smrg#include <GL/gl.h>
4132001f49Smrg#include <GL/glx.h>
4232001f49Smrg
4332001f49Smrg
4432001f49Smrg#define BENCHMARK
4532001f49Smrg
4632001f49Smrg#ifdef BENCHMARK
4732001f49Smrg
4832001f49Smrg/* XXX this probably isn't very portable */
4932001f49Smrg
5032001f49Smrg#include <sys/time.h>
5132001f49Smrg#include <unistd.h>
5232001f49Smrg
5332001f49Smrg/* return current time (in seconds) */
5432001f49Smrgstatic double
5532001f49Smrgcurrent_time(void)
5632001f49Smrg{
5732001f49Smrg   struct timeval tv;
5832001f49Smrg#ifdef __VMS
5932001f49Smrg   (void) gettimeofday(&tv, NULL );
6032001f49Smrg#else
6132001f49Smrg   struct timezone tz;
6232001f49Smrg   (void) gettimeofday(&tv, &tz);
6332001f49Smrg#endif
6432001f49Smrg   return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
6532001f49Smrg}
6632001f49Smrg
6732001f49Smrg#else /*BENCHMARK*/
6832001f49Smrg
6932001f49Smrg/* dummy */
7032001f49Smrgstatic double
7132001f49Smrgcurrent_time(void)
7232001f49Smrg{
7332001f49Smrg   /* update this function for other platforms! */
7432001f49Smrg   static double t = 0.0;
7532001f49Smrg   static int warn = 1;
7632001f49Smrg   if (warn) {
7732001f49Smrg      fprintf(stderr, "Warning: current_time() not implemented!!\n");
7832001f49Smrg      warn = 0;
7932001f49Smrg   }
8032001f49Smrg   return t += 1.0;
8132001f49Smrg}
8232001f49Smrg
8332001f49Smrg#endif /*BENCHMARK*/
8432001f49Smrg
8532001f49Smrg
8632001f49Smrg
8732001f49Smrg#ifndef M_PI
8832001f49Smrg#define M_PI 3.14159265
8932001f49Smrg#endif
9032001f49Smrg
9132001f49Smrg
9232001f49Smrgstatic GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
9332001f49Smrgstatic GLint gear1, gear2, gear3;
9432001f49Smrgstatic GLfloat angle = 0.0;
9532001f49Smrg
9632001f49Smrgstatic XVisualInfo *visinfo = NULL;
9732001f49Smrgstatic int WinWidth = 300, WinHeight = 300;
9832001f49Smrg
9932001f49Smrg
10032001f49Smrg/*
10132001f49Smrg *
10232001f49Smrg *  Draw a gear wheel.  You'll probably want to call this function when
10332001f49Smrg *  building a display list since we do a lot of trig here.
10432001f49Smrg *
10532001f49Smrg *  Input:  inner_radius - radius of hole at center
10632001f49Smrg *          outer_radius - radius at center of teeth
10732001f49Smrg *          width - width of gear
10832001f49Smrg *          teeth - number of teeth
10932001f49Smrg *          tooth_depth - depth of tooth
11032001f49Smrg */
11132001f49Smrgstatic void
11232001f49Smrggear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
11332001f49Smrg     GLint teeth, GLfloat tooth_depth)
11432001f49Smrg{
11532001f49Smrg   GLint i;
11632001f49Smrg   GLfloat r0, r1, r2;
11732001f49Smrg   GLfloat angle, da;
11832001f49Smrg   GLfloat u, v, len;
11932001f49Smrg
12032001f49Smrg   r0 = inner_radius;
12132001f49Smrg   r1 = outer_radius - tooth_depth / 2.0;
12232001f49Smrg   r2 = outer_radius + tooth_depth / 2.0;
12332001f49Smrg
12432001f49Smrg   da = 2.0 * M_PI / teeth / 4.0;
12532001f49Smrg
12632001f49Smrg   glShadeModel(GL_FLAT);
12732001f49Smrg
12832001f49Smrg   glNormal3f(0.0, 0.0, 1.0);
12932001f49Smrg
13032001f49Smrg   /* draw front face */
13132001f49Smrg   glBegin(GL_QUAD_STRIP);
13232001f49Smrg   for (i = 0; i <= teeth; i++) {
13332001f49Smrg      angle = i * 2.0 * M_PI / teeth;
13432001f49Smrg      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
13532001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
13632001f49Smrg      if (i < teeth) {
13732001f49Smrg	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
13832001f49Smrg	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
13932001f49Smrg		    width * 0.5);
14032001f49Smrg      }
14132001f49Smrg   }
14232001f49Smrg   glEnd();
14332001f49Smrg
14432001f49Smrg   /* draw front sides of teeth */
14532001f49Smrg   glBegin(GL_QUADS);
14632001f49Smrg   da = 2.0 * M_PI / teeth / 4.0;
14732001f49Smrg   for (i = 0; i < teeth; i++) {
14832001f49Smrg      angle = i * 2.0 * M_PI / teeth;
14932001f49Smrg
15032001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
15132001f49Smrg      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
15232001f49Smrg      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
15332001f49Smrg		 width * 0.5);
15432001f49Smrg      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
15532001f49Smrg		 width * 0.5);
15632001f49Smrg   }
15732001f49Smrg   glEnd();
15832001f49Smrg
15932001f49Smrg   glNormal3f(0.0, 0.0, -1.0);
16032001f49Smrg
16132001f49Smrg   /* draw back face */
16232001f49Smrg   glBegin(GL_QUAD_STRIP);
16332001f49Smrg   for (i = 0; i <= teeth; i++) {
16432001f49Smrg      angle = i * 2.0 * M_PI / teeth;
16532001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
16632001f49Smrg      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
16732001f49Smrg      if (i < teeth) {
16832001f49Smrg	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
16932001f49Smrg		    -width * 0.5);
17032001f49Smrg	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
17132001f49Smrg      }
17232001f49Smrg   }
17332001f49Smrg   glEnd();
17432001f49Smrg
17532001f49Smrg   /* draw back sides of teeth */
17632001f49Smrg   glBegin(GL_QUADS);
17732001f49Smrg   da = 2.0 * M_PI / teeth / 4.0;
17832001f49Smrg   for (i = 0; i < teeth; i++) {
17932001f49Smrg      angle = i * 2.0 * M_PI / teeth;
18032001f49Smrg
18132001f49Smrg      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
18232001f49Smrg		 -width * 0.5);
18332001f49Smrg      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
18432001f49Smrg		 -width * 0.5);
18532001f49Smrg      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
18632001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
18732001f49Smrg   }
18832001f49Smrg   glEnd();
18932001f49Smrg
19032001f49Smrg   /* draw outward faces of teeth */
19132001f49Smrg   glBegin(GL_QUAD_STRIP);
19232001f49Smrg   for (i = 0; i < teeth; i++) {
19332001f49Smrg      angle = i * 2.0 * M_PI / teeth;
19432001f49Smrg
19532001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
19632001f49Smrg      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
19732001f49Smrg      u = r2 * cos(angle + da) - r1 * cos(angle);
19832001f49Smrg      v = r2 * sin(angle + da) - r1 * sin(angle);
19932001f49Smrg      len = sqrt(u * u + v * v);
20032001f49Smrg      u /= len;
20132001f49Smrg      v /= len;
20232001f49Smrg      glNormal3f(v, -u, 0.0);
20332001f49Smrg      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
20432001f49Smrg      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
20532001f49Smrg      glNormal3f(cos(angle), sin(angle), 0.0);
20632001f49Smrg      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
20732001f49Smrg		 width * 0.5);
20832001f49Smrg      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
20932001f49Smrg		 -width * 0.5);
21032001f49Smrg      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
21132001f49Smrg      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
21232001f49Smrg      glNormal3f(v, -u, 0.0);
21332001f49Smrg      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
21432001f49Smrg		 width * 0.5);
21532001f49Smrg      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
21632001f49Smrg		 -width * 0.5);
21732001f49Smrg      glNormal3f(cos(angle), sin(angle), 0.0);
21832001f49Smrg   }
21932001f49Smrg
22032001f49Smrg   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
22132001f49Smrg   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
22232001f49Smrg
22332001f49Smrg   glEnd();
22432001f49Smrg
22532001f49Smrg   glShadeModel(GL_SMOOTH);
22632001f49Smrg
22732001f49Smrg   /* draw inside radius cylinder */
22832001f49Smrg   glBegin(GL_QUAD_STRIP);
22932001f49Smrg   for (i = 0; i <= teeth; i++) {
23032001f49Smrg      angle = i * 2.0 * M_PI / teeth;
23132001f49Smrg      glNormal3f(-cos(angle), -sin(angle), 0.0);
23232001f49Smrg      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
23332001f49Smrg      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
23432001f49Smrg   }
23532001f49Smrg   glEnd();
23632001f49Smrg}
23732001f49Smrg
23832001f49Smrg
23932001f49Smrgstatic void
24032001f49Smrgdo_draw(void)
24132001f49Smrg{
24232001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
24332001f49Smrg
24432001f49Smrg   glPushMatrix();
24532001f49Smrg   glRotatef(view_rotx, 1.0, 0.0, 0.0);
24632001f49Smrg   glRotatef(view_roty, 0.0, 1.0, 0.0);
24732001f49Smrg   glRotatef(view_rotz, 0.0, 0.0, 1.0);
24832001f49Smrg
24932001f49Smrg   glPushMatrix();
25032001f49Smrg   glTranslatef(-3.0, -2.0, 0.0);
25132001f49Smrg   glRotatef(angle, 0.0, 0.0, 1.0);
25232001f49Smrg   glCallList(gear1);
25332001f49Smrg   glPopMatrix();
25432001f49Smrg
25532001f49Smrg   glPushMatrix();
25632001f49Smrg   glTranslatef(3.1, -2.0, 0.0);
25732001f49Smrg   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
25832001f49Smrg   glCallList(gear2);
25932001f49Smrg   glPopMatrix();
26032001f49Smrg
26132001f49Smrg   glPushMatrix();
26232001f49Smrg   glTranslatef(-3.1, 4.2, 0.0);
26332001f49Smrg   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
26432001f49Smrg   glCallList(gear3);
26532001f49Smrg   glPopMatrix();
26632001f49Smrg
26732001f49Smrg   glPopMatrix();
26832001f49Smrg}
26932001f49Smrg
27032001f49Smrg
27132001f49Smrg/* new window size or exposure */
27232001f49Smrgstatic void
27332001f49Smrgreshape(int width, int height)
27432001f49Smrg{
27532001f49Smrg   glViewport(0, 0, (GLint) width, (GLint) height);
27632001f49Smrg
27732001f49Smrg   {
27832001f49Smrg      GLfloat h = (GLfloat) height / (GLfloat) width;
27932001f49Smrg
28032001f49Smrg      glMatrixMode(GL_PROJECTION);
28132001f49Smrg      glLoadIdentity();
28232001f49Smrg      glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
28332001f49Smrg   }
28432001f49Smrg
28532001f49Smrg   glMatrixMode(GL_MODELVIEW);
28632001f49Smrg   glLoadIdentity();
28732001f49Smrg   glTranslatef(0.0, 0.0, -40.0);
28832001f49Smrg}
28932001f49Smrg
29032001f49Smrg
29132001f49Smrgstatic void
29232001f49Smrginit(void)
29332001f49Smrg{
29432001f49Smrg   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
29532001f49Smrg   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
29632001f49Smrg   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
29732001f49Smrg   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
29832001f49Smrg
29932001f49Smrg   glLightfv(GL_LIGHT0, GL_POSITION, pos);
30032001f49Smrg   glEnable(GL_CULL_FACE);
30132001f49Smrg   glEnable(GL_LIGHTING);
30232001f49Smrg   glEnable(GL_LIGHT0);
30332001f49Smrg   glEnable(GL_DEPTH_TEST);
30432001f49Smrg
30532001f49Smrg   /* make the gears */
30632001f49Smrg   gear1 = glGenLists(1);
30732001f49Smrg   glNewList(gear1, GL_COMPILE);
30832001f49Smrg   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
30932001f49Smrg   gear(1.0, 4.0, 1.0, 20, 0.7);
31032001f49Smrg   glEndList();
31132001f49Smrg
31232001f49Smrg   gear2 = glGenLists(1);
31332001f49Smrg   glNewList(gear2, GL_COMPILE);
31432001f49Smrg   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
31532001f49Smrg   gear(0.5, 2.0, 2.0, 10, 0.7);
31632001f49Smrg   glEndList();
31732001f49Smrg
31832001f49Smrg   gear3 = glGenLists(1);
31932001f49Smrg   glNewList(gear3, GL_COMPILE);
32032001f49Smrg   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
32132001f49Smrg   gear(1.3, 2.0, 0.5, 10, 0.7);
32232001f49Smrg   glEndList();
32332001f49Smrg
32432001f49Smrg   glEnable(GL_NORMALIZE);
32532001f49Smrg}
32632001f49Smrg
32732001f49Smrg
32832001f49Smrgstatic void
32932001f49Smrgdraw( Display *dpy, Window win )
33032001f49Smrg{
33132001f49Smrg   GLXContext ctx;
33232001f49Smrg
33332001f49Smrg   ctx = glXCreateContext( dpy, visinfo, NULL, True );
33432001f49Smrg   if (!ctx) {
33532001f49Smrg      printf("Error: glXCreateContext failed\n");
33632001f49Smrg      exit(1);
33732001f49Smrg   }
33832001f49Smrg
33932001f49Smrg   glXMakeCurrent(dpy, win, ctx);
34032001f49Smrg
34132001f49Smrg   init();
34232001f49Smrg
34332001f49Smrg   reshape(WinWidth, WinHeight);
34432001f49Smrg
34532001f49Smrg   do_draw();
34632001f49Smrg
34732001f49Smrg   glDeleteLists(gear1, 1);
34832001f49Smrg   glDeleteLists(gear2, 1);
34932001f49Smrg   glDeleteLists(gear3, 1);
35032001f49Smrg
35132001f49Smrg   glXSwapBuffers(dpy, win);
35232001f49Smrg   glXDestroyContext(dpy, ctx);
35332001f49Smrg}
35432001f49Smrg
35532001f49Smrg
35632001f49Smrg/*
35732001f49Smrg * Create an RGB, double-buffered window.
35832001f49Smrg * Return the window and context handles.
35932001f49Smrg */
36032001f49Smrgstatic void
36132001f49Smrgmake_window( Display *dpy, const char *name,
36232001f49Smrg             int x, int y, int width, int height,
36332001f49Smrg             Window *winRet)
36432001f49Smrg{
36532001f49Smrg   int attribs[] = { GLX_RGBA,
36632001f49Smrg                     GLX_RED_SIZE, 1,
36732001f49Smrg                     GLX_GREEN_SIZE, 1,
36832001f49Smrg                     GLX_BLUE_SIZE, 1,
36932001f49Smrg                     GLX_DOUBLEBUFFER,
37032001f49Smrg                     GLX_DEPTH_SIZE, 1,
37132001f49Smrg                     None };
37232001f49Smrg   int scrnum;
37332001f49Smrg   XSetWindowAttributes attr;
37432001f49Smrg   unsigned long mask;
37532001f49Smrg   Window root;
37632001f49Smrg   Window win;
37732001f49Smrg
37832001f49Smrg   scrnum = DefaultScreen( dpy );
37932001f49Smrg   root = RootWindow( dpy, scrnum );
38032001f49Smrg
38132001f49Smrg   if (visinfo)
38232001f49Smrg	   XFree(visinfo);
38332001f49Smrg
38432001f49Smrg   visinfo = glXChooseVisual( dpy, scrnum, attribs );
38532001f49Smrg   if (!visinfo) {
38632001f49Smrg      printf("Error: couldn't get an RGB, Double-buffered visual\n");
38732001f49Smrg      exit(1);
38832001f49Smrg   }
38932001f49Smrg
39032001f49Smrg   /* window attributes */
39132001f49Smrg   attr.background_pixel = 0;
39232001f49Smrg   attr.border_pixel = 0;
39332001f49Smrg   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
39432001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
39532001f49Smrg   attr.override_redirect = 0;
39632001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
39732001f49Smrg
39832001f49Smrg   win = XCreateWindow( dpy, root, x, y, width, height,
39932001f49Smrg		        0, visinfo->depth, InputOutput,
40032001f49Smrg		        visinfo->visual, mask, &attr );
40132001f49Smrg
40232001f49Smrg   /* set hints and properties */
40332001f49Smrg   {
40432001f49Smrg      XSizeHints sizehints;
40532001f49Smrg      sizehints.x = x;
40632001f49Smrg      sizehints.y = y;
40732001f49Smrg      sizehints.width  = width;
40832001f49Smrg      sizehints.height = height;
40932001f49Smrg      sizehints.flags = USSize | USPosition;
41032001f49Smrg      XSetNormalHints(dpy, win, &sizehints);
41132001f49Smrg      XSetStandardProperties(dpy, win, name, name,
41232001f49Smrg                              None, (char **)NULL, 0, &sizehints);
41332001f49Smrg   }
41432001f49Smrg
41532001f49Smrg   *winRet = win;
41632001f49Smrg}
41732001f49Smrg
41832001f49Smrg
41932001f49Smrgstatic void
42032001f49Smrgevent_loop(Display *dpy)
42132001f49Smrg{
42232001f49Smrg   Window win;
42332001f49Smrg   make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win);
42432001f49Smrg   XMapWindow(dpy, win);
42532001f49Smrg
42632001f49Smrg   while (1) {
42732001f49Smrg      while (XPending(dpy) > 0) {
42832001f49Smrg         XEvent event;
42932001f49Smrg         XNextEvent(dpy, &event);
43032001f49Smrg         switch (event.type) {
43132001f49Smrg	 case Expose:
43232001f49Smrg            /* we'll redraw below */
43332001f49Smrg	    break;
43432001f49Smrg	 case ConfigureNotify:
43532001f49Smrg            WinWidth = event.xconfigure.width;
43632001f49Smrg            WinHeight = event.xconfigure.height;
43732001f49Smrg	    break;
43832001f49Smrg         case KeyPress:
43932001f49Smrg            {
44032001f49Smrg               char buffer[10];
44132001f49Smrg               int code;
44232001f49Smrg               code = XLookupKeysym(&event.xkey, 0);
44332001f49Smrg               if (code == XK_Left) {
44432001f49Smrg                  view_roty += 5.0;
44532001f49Smrg               }
44632001f49Smrg               else if (code == XK_Right) {
44732001f49Smrg                  view_roty -= 5.0;
44832001f49Smrg               }
44932001f49Smrg               else if (code == XK_Up) {
45032001f49Smrg                  view_rotx += 5.0;
45132001f49Smrg               }
45232001f49Smrg               else if (code == XK_Down) {
45332001f49Smrg                  view_rotx -= 5.0;
45432001f49Smrg               }
45532001f49Smrg               else {
45632001f49Smrg                  XLookupString(&event.xkey, buffer, sizeof(buffer),
45732001f49Smrg                                NULL, NULL);
45832001f49Smrg                  if (buffer[0] == 27) {
45932001f49Smrg                     /* escape */
46032001f49Smrg                     return;
46132001f49Smrg                  }
46232001f49Smrg               }
46332001f49Smrg            }
46432001f49Smrg         }
46532001f49Smrg      }
46632001f49Smrg
46732001f49Smrg      {
46832001f49Smrg         static int frames = 0;
46932001f49Smrg         static double tRot0 = -1.0, tRate0 = -1.0;
47032001f49Smrg         double dt, t = current_time();
47132001f49Smrg         if (tRot0 < 0.0)
47232001f49Smrg            tRot0 = t;
47332001f49Smrg         dt = t - tRot0;
47432001f49Smrg         tRot0 = t;
47532001f49Smrg
47632001f49Smrg         /* advance rotation for next frame */
47732001f49Smrg         angle += 70.0 * dt;  /* 70 degrees per second */
47832001f49Smrg         if (angle > 3600.0)
47932001f49Smrg	    angle -= 3600.0;
48032001f49Smrg
48132001f49Smrg         draw( dpy, win );
48232001f49Smrg
48332001f49Smrg         frames++;
48432001f49Smrg
48532001f49Smrg         if (tRate0 < 0.0)
48632001f49Smrg            tRate0 = t;
48732001f49Smrg
48832001f49Smrg         if (t - tRate0 >= 1.0) {
48932001f49Smrg            GLfloat seconds = t - tRate0;
49032001f49Smrg            GLfloat fps = frames / seconds;
49132001f49Smrg            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
49232001f49Smrg                   fps);
49332001f49Smrg	    fflush(stdout);
49432001f49Smrg            tRate0 = t;
49532001f49Smrg
49632001f49Smrg            /* Destroy window and create new one */
49732001f49Smrg	    XDestroyWindow(dpy, win);
49832001f49Smrg	    make_window(dpy, "glxgears",
49932001f49Smrg                        (int)(fps * 100) % 100, (int)(fps * 100) % 100, /* x,y */
50032001f49Smrg                        WinWidth, WinHeight, &win);
50132001f49Smrg	    XMapWindow(dpy, win);
50232001f49Smrg
50332001f49Smrg            frames = 0;
50432001f49Smrg         }
50532001f49Smrg      }
50632001f49Smrg   }
50732001f49Smrg}
50832001f49Smrg
50932001f49Smrg
51032001f49Smrgint
51132001f49Smrgmain(int argc, char *argv[])
51232001f49Smrg{
51332001f49Smrg   Display *dpy;
51432001f49Smrg   char *dpyName = NULL;
51532001f49Smrg   GLboolean printInfo = GL_FALSE;
51632001f49Smrg   int i;
51732001f49Smrg
51832001f49Smrg   for (i = 1; i < argc; i++) {
51932001f49Smrg      if (strcmp(argv[i], "-display") == 0) {
52032001f49Smrg         dpyName = argv[i+1];
52132001f49Smrg         i++;
52232001f49Smrg      }
52332001f49Smrg      else if (strcmp(argv[i], "-info") == 0) {
52432001f49Smrg         printInfo = GL_TRUE;
52532001f49Smrg      }
52632001f49Smrg      else
52732001f49Smrg	 printf("Warrning: unknown parameter: %s\n", argv[i]);
52832001f49Smrg   }
52932001f49Smrg
53032001f49Smrg   dpy = XOpenDisplay(dpyName);
53132001f49Smrg   if (!dpy) {
53232001f49Smrg      fprintf(stderr, "Error: couldn't open display %s\n",
53332001f49Smrg	      XDisplayName(dpyName));
53432001f49Smrg      return -1;
53532001f49Smrg   }
53632001f49Smrg
53732001f49Smrg   if (printInfo) {
53832001f49Smrg      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
53932001f49Smrg      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
54032001f49Smrg      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
54132001f49Smrg      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
54232001f49Smrg   }
54332001f49Smrg
54432001f49Smrg   event_loop(dpy);
54532001f49Smrg
54632001f49Smrg   XCloseDisplay(dpy);
54732001f49Smrg
54832001f49Smrg   return 0;
54932001f49Smrg}
550