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) */
54 static double
current_time(void)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
current_time(void)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
gear(GLfloat inner_radius,GLfloat outer_radius,GLfloat width,GLint teeth,GLfloat tooth_depth)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
draw(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
reshape(int width,int height)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
init(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 
run_gears(EGLDisplay dpy,EGLSurface surf,int ttr)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 	fflush(stdout);
361 
362 }
363 
364 
365 int
main(int argc,char * argv[])366 main(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