1/* 2 * Test AUX buffer rendering 3 * Use GLX since GLUT doesn't support AUX buffers 4 */ 5 6 7/* 8 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the "Software"), 12 * to deal in the Software without restriction, including without limitation 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 * and/or sell copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included 18 * in all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 24 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28/* 29 * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) 30 * Port by Brian Paul 23 March 2001 31 * 32 * Command line options: 33 * -info print GL implementation information 34 * 35 */ 36 37 38#include <math.h> 39#include <stdlib.h> 40#include <stdio.h> 41#include <string.h> 42#include <X11/Xlib.h> 43#include <X11/keysym.h> 44#include <GL/glew.h> 45#include <GL/glx.h> 46 47 48static int 49current_time(void) 50{ 51 return 0; 52} 53 54 55 56 57#ifndef M_PI 58#define M_PI 3.14159265 59#endif 60 61static int WinWidth = 300, WinHeight = 300; 62static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; 63static GLint gear1, gear2, gear3; 64static GLfloat angle = 0.0; 65 66 67/* 68 * 69 * Draw a gear wheel. You'll probably want to call this function when 70 * building a display list since we do a lot of trig here. 71 * 72 * Input: inner_radius - radius of hole at center 73 * outer_radius - radius at center of teeth 74 * width - width of gear 75 * teeth - number of teeth 76 * tooth_depth - depth of tooth 77 */ 78static void 79gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 80 GLint teeth, GLfloat tooth_depth) 81{ 82 GLint i; 83 GLfloat r0, r1, r2; 84 GLfloat angle, da; 85 GLfloat u, v, len; 86 87 r0 = inner_radius; 88 r1 = outer_radius - tooth_depth / 2.0; 89 r2 = outer_radius + tooth_depth / 2.0; 90 91 da = 2.0 * M_PI / teeth / 4.0; 92 93 glShadeModel(GL_FLAT); 94 95 glNormal3f(0.0, 0.0, 1.0); 96 97 /* draw front face */ 98 glBegin(GL_QUAD_STRIP); 99 for (i = 0; i <= teeth; i++) { 100 angle = i * 2.0 * M_PI / teeth; 101 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 102 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 103 if (i < teeth) { 104 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 105 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 106 width * 0.5); 107 } 108 } 109 glEnd(); 110 111 /* draw front sides of teeth */ 112 glBegin(GL_QUADS); 113 da = 2.0 * M_PI / teeth / 4.0; 114 for (i = 0; i < teeth; i++) { 115 angle = i * 2.0 * M_PI / teeth; 116 117 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 118 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 119 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 120 width * 0.5); 121 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 122 width * 0.5); 123 } 124 glEnd(); 125 126 glNormal3f(0.0, 0.0, -1.0); 127 128 /* draw back face */ 129 glBegin(GL_QUAD_STRIP); 130 for (i = 0; i <= teeth; i++) { 131 angle = i * 2.0 * M_PI / teeth; 132 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 133 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 134 if (i < teeth) { 135 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 136 -width * 0.5); 137 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 138 } 139 } 140 glEnd(); 141 142 /* draw back sides of teeth */ 143 glBegin(GL_QUADS); 144 da = 2.0 * M_PI / teeth / 4.0; 145 for (i = 0; i < teeth; i++) { 146 angle = i * 2.0 * M_PI / teeth; 147 148 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 149 -width * 0.5); 150 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 151 -width * 0.5); 152 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 153 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 154 } 155 glEnd(); 156 157 /* draw outward faces of teeth */ 158 glBegin(GL_QUAD_STRIP); 159 for (i = 0; i < teeth; i++) { 160 angle = i * 2.0 * M_PI / teeth; 161 162 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 163 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 164 u = r2 * cos(angle + da) - r1 * cos(angle); 165 v = r2 * sin(angle + da) - r1 * sin(angle); 166 len = sqrt(u * u + v * v); 167 u /= len; 168 v /= len; 169 glNormal3f(v, -u, 0.0); 170 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 171 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 172 glNormal3f(cos(angle), sin(angle), 0.0); 173 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 174 width * 0.5); 175 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 176 -width * 0.5); 177 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 178 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 179 glNormal3f(v, -u, 0.0); 180 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 181 width * 0.5); 182 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 183 -width * 0.5); 184 glNormal3f(cos(angle), sin(angle), 0.0); 185 } 186 187 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); 188 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); 189 190 glEnd(); 191 192 glShadeModel(GL_SMOOTH); 193 194 /* draw inside radius cylinder */ 195 glBegin(GL_QUAD_STRIP); 196 for (i = 0; i <= teeth; i++) { 197 angle = i * 2.0 * M_PI / teeth; 198 glNormal3f(-cos(angle), -sin(angle), 0.0); 199 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 200 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 201 } 202 glEnd(); 203} 204 205 206static void 207draw(void) 208{ 209 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 210 211 glPushMatrix(); 212 glRotatef(view_rotx, 1.0, 0.0, 0.0); 213 glRotatef(view_roty, 0.0, 1.0, 0.0); 214 glRotatef(view_rotz, 0.0, 0.0, 1.0); 215 216 glPushMatrix(); 217 glTranslatef(-3.0, -2.0, 0.0); 218 glRotatef(angle, 0.0, 0.0, 1.0); 219 glCallList(gear1); 220 glPopMatrix(); 221 222 glPushMatrix(); 223 glTranslatef(3.1, -2.0, 0.0); 224 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); 225 glCallList(gear2); 226 glPopMatrix(); 227 228 glPushMatrix(); 229 glTranslatef(-3.1, 4.2, 0.0); 230 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); 231 glCallList(gear3); 232 glPopMatrix(); 233 234 glPopMatrix(); 235} 236 237 238/* new window size or exposure */ 239static void 240reshape(int width, int height) 241{ 242 GLfloat h = (GLfloat) height / (GLfloat) width; 243 244 WinWidth = width; 245 WinHeight = height; 246 glViewport(0, 0, (GLint) width, (GLint) height); 247 glMatrixMode(GL_PROJECTION); 248 glLoadIdentity(); 249 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); 250 glMatrixMode(GL_MODELVIEW); 251 glLoadIdentity(); 252 glTranslatef(0.0, 0.0, -40.0); 253} 254 255 256static void 257init(void) 258{ 259 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; 260 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; 261 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; 262 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; 263 int i; 264 265 glGetIntegerv(GL_AUX_BUFFERS, &i); 266 printf("AUX BUFFERS: %d\n", i); 267 268 glLightfv(GL_LIGHT0, GL_POSITION, pos); 269 glEnable(GL_CULL_FACE); 270 glEnable(GL_LIGHTING); 271 glEnable(GL_LIGHT0); 272 glEnable(GL_DEPTH_TEST); 273 274 /* make the gears */ 275 gear1 = glGenLists(1); 276 glNewList(gear1, GL_COMPILE); 277 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); 278 gear(1.0, 4.0, 1.0, 20, 0.7); 279 glEndList(); 280 281 gear2 = glGenLists(1); 282 glNewList(gear2, GL_COMPILE); 283 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); 284 gear(0.5, 2.0, 2.0, 10, 0.7); 285 glEndList(); 286 287 gear3 = glGenLists(1); 288 glNewList(gear3, GL_COMPILE); 289 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); 290 gear(1.3, 2.0, 0.5, 10, 0.7); 291 glEndList(); 292 293 glEnable(GL_NORMALIZE); 294} 295 296 297/* 298 * Create an RGB, double-buffered window. 299 * Return the window and context handles. 300 */ 301static void 302make_window( Display *dpy, const char *name, 303 int x, int y, int width, int height, 304 Window *winRet, GLXContext *ctxRet) 305{ 306 int attrib[] = { GLX_RGBA, 307 GLX_RED_SIZE, 1, 308 GLX_GREEN_SIZE, 1, 309 GLX_BLUE_SIZE, 1, 310 GLX_DOUBLEBUFFER, 311 GLX_DEPTH_SIZE, 1, 312 GLX_AUX_BUFFERS, 1, 313 None }; 314 int scrnum; 315 XSetWindowAttributes attr; 316 unsigned long mask; 317 Window root; 318 Window win; 319 GLXContext ctx; 320 XVisualInfo *visinfo; 321 322 scrnum = DefaultScreen( dpy ); 323 root = RootWindow( dpy, scrnum ); 324 325 visinfo = glXChooseVisual( dpy, scrnum, attrib ); 326 if (!visinfo) { 327 printf("Error: couldn't get an RGB, Double-buffered visual\n"); 328 exit(1); 329 } 330 331 /* window attributes */ 332 attr.background_pixel = 0; 333 attr.border_pixel = 0; 334 attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); 335 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 336 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 337 338 win = XCreateWindow( dpy, root, 0, 0, width, height, 339 0, visinfo->depth, InputOutput, 340 visinfo->visual, mask, &attr ); 341 342 /* set hints and properties */ 343 { 344 XSizeHints sizehints; 345 sizehints.x = x; 346 sizehints.y = y; 347 sizehints.width = width; 348 sizehints.height = height; 349 sizehints.flags = USSize | USPosition; 350 XSetNormalHints(dpy, win, &sizehints); 351 XSetStandardProperties(dpy, win, name, name, 352 None, (char **)NULL, 0, &sizehints); 353 } 354 355 ctx = glXCreateContext( dpy, visinfo, NULL, True ); 356 if (!ctx) { 357 printf("Error: glXCreateContext failed\n"); 358 exit(1); 359 } 360 361 XFree(visinfo); 362 363 *winRet = win; 364 *ctxRet = ctx; 365} 366 367 368static void 369event_loop(Display *dpy, Window win) 370{ 371 while (1) { 372 while (XPending(dpy) > 0) { 373 XEvent event; 374 XNextEvent(dpy, &event); 375 switch (event.type) { 376 case Expose: 377 /* we'll redraw below */ 378 break; 379 case ConfigureNotify: 380 reshape(event.xconfigure.width, event.xconfigure.height); 381 break; 382 case KeyPress: 383 { 384 char buffer[10]; 385 int r, code; 386 code = XLookupKeysym(&event.xkey, 0); 387 if (code == XK_Left) { 388 view_roty += 5.0; 389 } 390 else if (code == XK_Right) { 391 view_roty -= 5.0; 392 } 393 else if (code == XK_Up) { 394 view_rotx += 5.0; 395 } 396 else if (code == XK_Down) { 397 view_rotx -= 5.0; 398 } 399 else { 400 r = XLookupString(&event.xkey, buffer, sizeof(buffer), 401 NULL, NULL); 402 if (buffer[0] == 27) { 403 /* escape */ 404 return; 405 } 406 } 407 } 408 } 409 } 410 411 /* next frame */ 412 angle += 2.0; 413 414 /* draw to aux buffer */ 415 glDrawBuffer(GL_AUX0); 416 417 draw(); 418 419 /* Copy aux buffer image to back color buffer */ 420 glReadBuffer(GL_AUX0); 421 glDrawBuffer(GL_BACK); 422 glWindowPos2iARB(0, 0); 423 glDisable(GL_DEPTH_TEST); 424 glCopyPixels(0, 0, WinWidth, WinHeight, GL_COLOR); 425 glEnable(GL_DEPTH_TEST); 426 427 glXSwapBuffers(dpy, win); 428 429 /* calc framerate */ 430 { 431 static int t0 = -1; 432 static int frames = 0; 433 int t = current_time(); 434 435 if (t0 < 0) 436 t0 = t; 437 438 frames++; 439 440 if (t - t0 >= 5.0) { 441 GLfloat seconds = t - t0; 442 GLfloat fps = frames / seconds; 443 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, 444 fps); 445 t0 = t; 446 frames = 0; 447 } 448 } 449 } 450} 451 452 453int 454main(int argc, char *argv[]) 455{ 456 Display *dpy; 457 Window win; 458 GLXContext ctx; 459 char *dpyName = ":0"; 460 GLboolean printInfo = GL_FALSE; 461 int i; 462 463 for (i = 1; i < argc; i++) { 464 if (strcmp(argv[i], "-display") == 0) { 465 dpyName = argv[i+1]; 466 i++; 467 } 468 else if (strcmp(argv[i], "-info") == 0) { 469 printInfo = GL_TRUE; 470 } 471 } 472 473 dpy = XOpenDisplay(dpyName); 474 if (!dpy) { 475 printf("Error: couldn't open display %s\n", dpyName); 476 return -1; 477 } 478 479 make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win, &ctx); 480 XMapWindow(dpy, win); 481 glXMakeCurrent(dpy, win, ctx); 482 483 glewInit(); 484 485 if (printInfo) { 486 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 487 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 488 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 489 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 490 } 491 492 init(); 493 494 event_loop(dpy, win); 495 496 glXDestroyContext(dpy, ctx); 497 XDestroyWindow(dpy, win); 498 XCloseDisplay(dpy); 499 500 return 0; 501} 502