Merge branch '7.8'
[mesa.git] / progs / egl / opengl / peglgears.c
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/gl.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) */
54 static double
55 current_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 */
70 static double
71 current_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
91 static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
92 static GLint gear1, gear2, gear3;
93 static GLfloat angle = 0.0;
94
95 #if 0
96 static GLfloat eyesep = 5.0; /* Eye separation. */
97 static GLfloat fix_point = 40.0; /* Fixation point distance. */
98 static 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 */
113 static void
114 gear(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
241 static void
242 draw(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 */
274 static void
275 reshape(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
292 static void
293 init(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
331 static 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
361 }
362
363
364 int
365 main(int argc, char *argv[])
366 {
367 int major, minor;
368 EGLContext ctx;
369 EGLSurface surface;
370 EGLConfig configs[MAX_CONFIGS];
371 EGLint numConfigs, i;
372 EGLBoolean b;
373 EGLDisplay d;
374 EGLint screenAttribs[10];
375 GLboolean printInfo = GL_FALSE;
376 EGLint width = 300, height = 300;
377
378 /* parse cmd line args */
379 for (i = 1; i < argc; i++)
380 {
381 if (strcmp(argv[i], "-info") == 0)
382 {
383 printInfo = GL_TRUE;
384 }
385 else
386 printf("Warning: unknown parameter: %s\n", argv[i]);
387 }
388
389 /* DBR : Create EGL context/surface etc */
390 d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
391 assert(d);
392
393 if (!eglInitialize(d, &major, &minor)) {
394 printf("peglgears: eglInitialize failed\n");
395 return 0;
396 }
397
398 printf("peglgears: EGL version = %d.%d\n", major, minor);
399 printf("peglgears: EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR));
400
401 eglGetConfigs(d, configs, MAX_CONFIGS, &numConfigs);
402
403 eglBindAPI(EGL_OPENGL_API);
404
405 ctx = eglCreateContext(d, configs[0], EGL_NO_CONTEXT, NULL);
406 if (ctx == EGL_NO_CONTEXT) {
407 printf("peglgears: failed to create context\n");
408 return 0;
409 }
410
411 /* build up screenAttribs array */
412 i = 0;
413 screenAttribs[i++] = EGL_WIDTH;
414 screenAttribs[i++] = width;
415 screenAttribs[i++] = EGL_HEIGHT;
416 screenAttribs[i++] = height;
417 screenAttribs[i++] = EGL_NONE;
418
419 surface = eglCreatePbufferSurface(d, configs[0], screenAttribs);
420 if (surface == EGL_NO_SURFACE) {
421 printf("peglgears: failed to create pbuffer surface\n");
422 return 0;
423 }
424
425 b = eglMakeCurrent(d, surface, surface, ctx);
426 if (!b) {
427 printf("peglgears: make current failed\n");
428 return 0;
429 }
430
431 if (printInfo)
432 {
433 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
434 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
435 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
436 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
437 }
438
439 init();
440 reshape(width, height);
441
442 glDrawBuffer( GL_BACK );
443
444 run_gears(d, surface, 5.0);
445
446 eglDestroySurface(d, surface);
447 eglDestroyContext(d, ctx);
448 eglTerminate(d);
449
450 return 0;
451 }