1/* 2 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 */ 21 22/* 23 * This is a port of the infamous "glxgears" demo to straight EGL 24 * Port by Dane Rushton 10 July 2005 25 * 26 * No command line options. 27 * Program runs for 5 seconds then exits, outputing framerate to console 28 */ 29 30#define EGL_EGLEXT_PROTOTYPES 31 32#include <assert.h> 33#include <math.h> 34#include <stdlib.h> 35#include <stdio.h> 36#include <string.h> 37#include "gl_wrap.h" 38#include <EGL/egl.h> 39#include <EGL/eglext.h> 40 41#define MAX_CONFIGS 10 42#define MAX_MODES 100 43 44#define BENCHMARK 45 46#ifdef BENCHMARK 47 48/* XXX this probably isn't very portable */ 49 50#include <sys/time.h> 51#include <unistd.h> 52 53/* return current time (in seconds) */ 54static double 55current_time(void) 56{ 57 struct timeval tv; 58#ifdef __VMS 59 (void) gettimeofday(&tv, NULL ); 60#else 61 struct timezone tz; 62 (void) gettimeofday(&tv, &tz); 63#endif 64 return (double) tv.tv_sec + tv.tv_usec / 1000000.0; 65} 66 67#else /*BENCHMARK*/ 68 69/* dummy */ 70static double 71current_time(void) 72{ 73 /* update this function for other platforms! */ 74 static double t = 0.0; 75 static int warn = 1; 76 if (warn) { 77 fprintf(stderr, "Warning: current_time() not implemented!!\n"); 78 warn = 0; 79 } 80 return t += 1.0; 81} 82 83#endif /*BENCHMARK*/ 84 85 86#ifndef M_PI 87#define M_PI 3.14159265 88#endif 89 90 91static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; 92static GLint gear1, gear2, gear3; 93static GLfloat angle = 0.0; 94 95#if 0 96static GLfloat eyesep = 5.0; /* Eye separation. */ 97static GLfloat fix_point = 40.0; /* Fixation point distance. */ 98static GLfloat left, right, asp; /* Stereo frustum params. */ 99#endif 100 101 102/* 103 * 104 * Draw a gear wheel. You'll probably want to call this function when 105 * building a display list since we do a lot of trig here. 106 * 107 * Input: inner_radius - radius of hole at center 108 * outer_radius - radius at center of teeth 109 * width - width of gear 110 * teeth - number of teeth 111 * tooth_depth - depth of tooth 112 */ 113static void 114gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 115 GLint teeth, GLfloat tooth_depth) 116{ 117 GLint i; 118 GLfloat r0, r1, r2; 119 GLfloat angle, da; 120 GLfloat u, v, len; 121 122 r0 = inner_radius; 123 r1 = outer_radius - tooth_depth / 2.0; 124 r2 = outer_radius + tooth_depth / 2.0; 125 126 da = 2.0 * M_PI / teeth / 4.0; 127 128 glShadeModel(GL_FLAT); 129 130 glNormal3f(0.0, 0.0, 1.0); 131 132 /* draw front face */ 133 glBegin(GL_QUAD_STRIP); 134 for (i = 0; i <= teeth; i++) { 135 angle = i * 2.0 * M_PI / teeth; 136 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 137 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 138 if (i < teeth) { 139 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 140 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 141 width * 0.5); 142 } 143 } 144 glEnd(); 145 146 /* draw front sides of teeth */ 147 glBegin(GL_QUADS); 148 da = 2.0 * M_PI / teeth / 4.0; 149 for (i = 0; i < teeth; i++) { 150 angle = i * 2.0 * M_PI / teeth; 151 152 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 153 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 154 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 155 width * 0.5); 156 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 157 width * 0.5); 158 } 159 glEnd(); 160 161 glNormal3f(0.0, 0.0, -1.0); 162 163 /* draw back face */ 164 glBegin(GL_QUAD_STRIP); 165 for (i = 0; i <= teeth; i++) { 166 angle = i * 2.0 * M_PI / teeth; 167 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 168 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 169 if (i < teeth) { 170 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 171 -width * 0.5); 172 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 173 } 174 } 175 glEnd(); 176 177 /* draw back sides of teeth */ 178 glBegin(GL_QUADS); 179 da = 2.0 * M_PI / teeth / 4.0; 180 for (i = 0; i < teeth; i++) { 181 angle = i * 2.0 * M_PI / teeth; 182 183 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 184 -width * 0.5); 185 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 186 -width * 0.5); 187 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 188 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 189 } 190 glEnd(); 191 192 /* draw outward faces of teeth */ 193 glBegin(GL_QUAD_STRIP); 194 for (i = 0; i < teeth; i++) { 195 angle = i * 2.0 * M_PI / teeth; 196 197 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 198 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 199 u = r2 * cos(angle + da) - r1 * cos(angle); 200 v = r2 * sin(angle + da) - r1 * sin(angle); 201 len = sqrt(u * u + v * v); 202 u /= len; 203 v /= len; 204 glNormal3f(v, -u, 0.0); 205 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 206 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 207 glNormal3f(cos(angle), sin(angle), 0.0); 208 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 209 width * 0.5); 210 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 211 -width * 0.5); 212 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 213 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 214 glNormal3f(v, -u, 0.0); 215 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 216 width * 0.5); 217 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 218 -width * 0.5); 219 glNormal3f(cos(angle), sin(angle), 0.0); 220 } 221 222 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); 223 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); 224 225 glEnd(); 226 227 glShadeModel(GL_SMOOTH); 228 229 /* draw inside radius cylinder */ 230 glBegin(GL_QUAD_STRIP); 231 for (i = 0; i <= teeth; i++) { 232 angle = i * 2.0 * M_PI / teeth; 233 glNormal3f(-cos(angle), -sin(angle), 0.0); 234 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 235 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 236 } 237 glEnd(); 238} 239 240 241static void 242draw(void) 243{ 244 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 245 246 glPushMatrix(); 247 glRotatef(view_rotx, 1.0, 0.0, 0.0); 248 glRotatef(view_roty, 0.0, 1.0, 0.0); 249 glRotatef(view_rotz, 0.0, 0.0, 1.0); 250 251 glPushMatrix(); 252 glTranslatef(-3.0, -2.0, 0.0); 253 glRotatef(angle, 0.0, 0.0, 1.0); 254 glCallList(gear1); 255 glPopMatrix(); 256 257 glPushMatrix(); 258 glTranslatef(3.1, -2.0, 0.0); 259 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); 260 glCallList(gear2); 261 glPopMatrix(); 262 263 glPushMatrix(); 264 glTranslatef(-3.1, 4.2, 0.0); 265 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); 266 glCallList(gear3); 267 glPopMatrix(); 268 269 glPopMatrix(); 270} 271 272 273/* new window size or exposure */ 274static void 275reshape(int width, int height) 276{ 277 GLfloat h = (GLfloat) height / (GLfloat) width; 278 279 glViewport(0, 0, (GLint) width, (GLint) height); 280 281 glMatrixMode(GL_PROJECTION); 282 glLoadIdentity(); 283 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); 284 285 glMatrixMode(GL_MODELVIEW); 286 glLoadIdentity(); 287 glTranslatef(0.0, 0.0, -40.0); 288} 289 290 291 292static void 293init(void) 294{ 295 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; 296 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; 297 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; 298 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; 299 300 glLightfv(GL_LIGHT0, GL_POSITION, pos); 301 glEnable(GL_CULL_FACE); 302 glEnable(GL_LIGHTING); 303 glEnable(GL_LIGHT0); 304 glEnable(GL_DEPTH_TEST); 305 306 /* make the gears */ 307 gear1 = glGenLists(1); 308 glNewList(gear1, GL_COMPILE); 309 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); 310 gear(1.0, 4.0, 1.0, 20, 0.7); 311 glEndList(); 312 313 gear2 = glGenLists(1); 314 glNewList(gear2, GL_COMPILE); 315 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); 316 gear(0.5, 2.0, 2.0, 10, 0.7); 317 glEndList(); 318 319 gear3 = glGenLists(1); 320 glNewList(gear3, GL_COMPILE); 321 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); 322 gear(1.3, 2.0, 0.5, 10, 0.7); 323 glEndList(); 324 325 glEnable(GL_NORMALIZE); 326} 327 328 329 330 331static void run_gears(EGLDisplay dpy, EGLSurface surf, int ttr) 332{ 333 double st = current_time(); 334 double ct = st; 335 int frames = 0; 336 GLfloat seconds, fps; 337 338 while (ct - st < ttr) 339 { 340 double tt = current_time(); 341 double dt = tt - ct; 342 ct = tt; 343 344 /* advance rotation for next frame */ 345 angle += 70.0 * dt; /* 70 degrees per second */ 346 if (angle > 3600.0) 347 angle -= 3600.0; 348 349 draw(); 350 351 eglSwapBuffers(dpy, surf); 352 353 354 frames++; 355 } 356 357 seconds = ct - st; 358 fps = frames / seconds; 359 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, fps); 360 fflush(stdout); 361 362} 363 364 365int 366main(int argc, char *argv[]) 367{ 368 int major, minor; 369 EGLContext ctx; 370 EGLSurface surface; 371 EGLConfig configs[MAX_CONFIGS]; 372 EGLint numConfigs, i; 373 EGLBoolean b; 374 EGLDisplay d; 375 EGLint configAttribs[10]; 376 EGLint screenAttribs[10]; 377 GLboolean printInfo = GL_FALSE; 378 EGLint width = 300, height = 300; 379 380 /* parse cmd line args */ 381 for (i = 1; i < argc; i++) 382 { 383 if (strcmp(argv[i], "-info") == 0) 384 { 385 printInfo = GL_TRUE; 386 } 387 else 388 printf("Warning: unknown parameter: %s\n", argv[i]); 389 } 390 391 /* DBR : Create EGL context/surface etc */ 392 d = eglGetDisplay(EGL_DEFAULT_DISPLAY); 393 assert(d); 394 395 if (!eglInitialize(d, &major, &minor)) { 396 printf("peglgears: eglInitialize failed\n"); 397 return 0; 398 } 399 400 printf("peglgears: EGL version = %d.%d\n", major, minor); 401 printf("peglgears: EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR)); 402 403 i = 0; 404 configAttribs[i++] = EGL_RENDERABLE_TYPE; 405 configAttribs[i++] = EGL_OPENGL_BIT; 406 configAttribs[i++] = EGL_SURFACE_TYPE; 407 configAttribs[i++] = EGL_PBUFFER_BIT; 408 configAttribs[i++] = EGL_NONE; 409 410 numConfigs = 0; 411 if (!eglChooseConfig(d, configAttribs, configs, MAX_CONFIGS, &numConfigs) || 412 !numConfigs) { 413 printf("peglgears: failed to choose a config\n"); 414 return 0; 415 } 416 417 eglBindAPI(EGL_OPENGL_API); 418 419 ctx = eglCreateContext(d, configs[0], EGL_NO_CONTEXT, NULL); 420 if (ctx == EGL_NO_CONTEXT) { 421 printf("peglgears: failed to create context\n"); 422 return 0; 423 } 424 425 /* build up screenAttribs array */ 426 i = 0; 427 screenAttribs[i++] = EGL_WIDTH; 428 screenAttribs[i++] = width; 429 screenAttribs[i++] = EGL_HEIGHT; 430 screenAttribs[i++] = height; 431 screenAttribs[i++] = EGL_NONE; 432 433 surface = eglCreatePbufferSurface(d, configs[0], screenAttribs); 434 if (surface == EGL_NO_SURFACE) { 435 printf("peglgears: failed to create pbuffer surface\n"); 436 return 0; 437 } 438 439 b = eglMakeCurrent(d, surface, surface, ctx); 440 if (!b) { 441 printf("peglgears: make current failed\n"); 442 return 0; 443 } 444 445 if (printInfo) 446 { 447 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 448 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 449 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 450 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 451 } 452 453 init(); 454 reshape(width, height); 455 456 glDrawBuffer( GL_BACK ); 457 458 run_gears(d, surface, 5.0); 459 460 eglDestroySurface(d, surface); 461 eglDestroyContext(d, ctx); 462 eglTerminate(d); 463 464 return 0; 465} 466