Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / progs / egl / eglgears.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 #include <math.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <GL/gl.h>
35 #include <GLES/egl.h>
36 #include <assert.h>
37
38 #define MAX_CONFIGS 10
39 #define MAX_MODES 100
40
41 #define BENCHMARK
42
43 #ifdef BENCHMARK
44
45 /* XXX this probably isn't very portable */
46
47 #include <sys/time.h>
48 #include <unistd.h>
49
50 /* return current time (in seconds) */
51 static double
52 current_time(void)
53 {
54 struct timeval tv;
55 #ifdef __VMS
56 (void) gettimeofday(&tv, NULL );
57 #else
58 struct timezone tz;
59 (void) gettimeofday(&tv, &tz);
60 #endif
61 return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
62 }
63
64 #else /*BENCHMARK*/
65
66 /* dummy */
67 static double
68 current_time(void)
69 {
70 /* update this function for other platforms! */
71 static double t = 0.0;
72 static int warn = 1;
73 if (warn) {
74 fprintf(stderr, "Warning: current_time() not implemented!!\n");
75 warn = 0;
76 }
77 return t += 1.0;
78 }
79
80 #endif /*BENCHMARK*/
81
82
83 #ifndef M_PI
84 #define M_PI 3.14159265
85 #endif
86
87
88 static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
89 static GLint gear1, gear2, gear3;
90 static GLfloat angle = 0.0;
91
92 #if 0
93 static GLfloat eyesep = 5.0; /* Eye separation. */
94 static GLfloat fix_point = 40.0; /* Fixation point distance. */
95 static GLfloat left, right, asp; /* Stereo frustum params. */
96 #endif
97
98
99 /*
100 *
101 * Draw a gear wheel. You'll probably want to call this function when
102 * building a display list since we do a lot of trig here.
103 *
104 * Input: inner_radius - radius of hole at center
105 * outer_radius - radius at center of teeth
106 * width - width of gear
107 * teeth - number of teeth
108 * tooth_depth - depth of tooth
109 */
110 static void
111 gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
112 GLint teeth, GLfloat tooth_depth)
113 {
114 GLint i;
115 GLfloat r0, r1, r2;
116 GLfloat angle, da;
117 GLfloat u, v, len;
118
119 r0 = inner_radius;
120 r1 = outer_radius - tooth_depth / 2.0;
121 r2 = outer_radius + tooth_depth / 2.0;
122
123 da = 2.0 * M_PI / teeth / 4.0;
124
125 glShadeModel(GL_FLAT);
126
127 glNormal3f(0.0, 0.0, 1.0);
128
129 /* draw front face */
130 glBegin(GL_QUAD_STRIP);
131 for (i = 0; i <= teeth; i++) {
132 angle = i * 2.0 * M_PI / teeth;
133 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
134 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
135 if (i < teeth) {
136 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
137 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
138 width * 0.5);
139 }
140 }
141 glEnd();
142
143 /* draw front sides of teeth */
144 glBegin(GL_QUADS);
145 da = 2.0 * M_PI / teeth / 4.0;
146 for (i = 0; i < teeth; i++) {
147 angle = i * 2.0 * M_PI / teeth;
148
149 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
150 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
151 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
152 width * 0.5);
153 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
154 width * 0.5);
155 }
156 glEnd();
157
158 glNormal3f(0.0, 0.0, -1.0);
159
160 /* draw back face */
161 glBegin(GL_QUAD_STRIP);
162 for (i = 0; i <= teeth; i++) {
163 angle = i * 2.0 * M_PI / teeth;
164 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
165 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
166 if (i < teeth) {
167 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
168 -width * 0.5);
169 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
170 }
171 }
172 glEnd();
173
174 /* draw back sides of teeth */
175 glBegin(GL_QUADS);
176 da = 2.0 * M_PI / teeth / 4.0;
177 for (i = 0; i < teeth; i++) {
178 angle = i * 2.0 * M_PI / teeth;
179
180 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
181 -width * 0.5);
182 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
183 -width * 0.5);
184 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
185 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
186 }
187 glEnd();
188
189 /* draw outward faces of teeth */
190 glBegin(GL_QUAD_STRIP);
191 for (i = 0; i < teeth; i++) {
192 angle = i * 2.0 * M_PI / teeth;
193
194 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
195 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
196 u = r2 * cos(angle + da) - r1 * cos(angle);
197 v = r2 * sin(angle + da) - r1 * sin(angle);
198 len = sqrt(u * u + v * v);
199 u /= len;
200 v /= len;
201 glNormal3f(v, -u, 0.0);
202 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
203 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
204 glNormal3f(cos(angle), sin(angle), 0.0);
205 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
206 width * 0.5);
207 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
208 -width * 0.5);
209 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
210 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
211 glNormal3f(v, -u, 0.0);
212 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
213 width * 0.5);
214 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
215 -width * 0.5);
216 glNormal3f(cos(angle), sin(angle), 0.0);
217 }
218
219 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
220 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
221
222 glEnd();
223
224 glShadeModel(GL_SMOOTH);
225
226 /* draw inside radius cylinder */
227 glBegin(GL_QUAD_STRIP);
228 for (i = 0; i <= teeth; i++) {
229 angle = i * 2.0 * M_PI / teeth;
230 glNormal3f(-cos(angle), -sin(angle), 0.0);
231 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
232 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
233 }
234 glEnd();
235 }
236
237
238 static void
239 draw(void)
240 {
241 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
242
243 glPushMatrix();
244 glRotatef(view_rotx, 1.0, 0.0, 0.0);
245 glRotatef(view_roty, 0.0, 1.0, 0.0);
246 glRotatef(view_rotz, 0.0, 0.0, 1.0);
247
248 glPushMatrix();
249 glTranslatef(-3.0, -2.0, 0.0);
250 glRotatef(angle, 0.0, 0.0, 1.0);
251 glCallList(gear1);
252 glPopMatrix();
253
254 glPushMatrix();
255 glTranslatef(3.1, -2.0, 0.0);
256 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
257 glCallList(gear2);
258 glPopMatrix();
259
260 glPushMatrix();
261 glTranslatef(-3.1, 4.2, 0.0);
262 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
263 glCallList(gear3);
264 glPopMatrix();
265
266 glPopMatrix();
267 }
268
269
270 /* new window size or exposure */
271 static void
272 reshape(int width, int height)
273 {
274 glViewport(0, 0, (GLint) width, (GLint) height);
275
276 GLfloat h = (GLfloat) height / (GLfloat) width;
277
278 glMatrixMode(GL_PROJECTION);
279 glLoadIdentity();
280 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
281
282 glMatrixMode(GL_MODELVIEW);
283 glLoadIdentity();
284 glTranslatef(0.0, 0.0, -40.0);
285 }
286
287
288
289 static void
290 init(void)
291 {
292 static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
293 static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
294 static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
295 static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
296
297 glLightfv(GL_LIGHT0, GL_POSITION, pos);
298 glEnable(GL_CULL_FACE);
299 glEnable(GL_LIGHTING);
300 glEnable(GL_LIGHT0);
301 glEnable(GL_DEPTH_TEST);
302
303 /* make the gears */
304 gear1 = glGenLists(1);
305 glNewList(gear1, GL_COMPILE);
306 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
307 gear(1.0, 4.0, 1.0, 20, 0.7);
308 glEndList();
309
310 gear2 = glGenLists(1);
311 glNewList(gear2, GL_COMPILE);
312 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
313 gear(0.5, 2.0, 2.0, 10, 0.7);
314 glEndList();
315
316 gear3 = glGenLists(1);
317 glNewList(gear3, GL_COMPILE);
318 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
319 gear(1.3, 2.0, 0.5, 10, 0.7);
320 glEndList();
321
322 glEnable(GL_NORMALIZE);
323 }
324
325
326
327
328 static void run_gears(EGLDisplay dpy, EGLSurface surf, int ttr)
329 {
330 double st = current_time();
331 double ct = st;
332 int frames = 0;
333 while (ct - st < ttr)
334 {
335 double tt = current_time();
336 double dt = tt - ct;
337 ct = tt;
338
339 /* advance rotation for next frame */
340 angle += 70.0 * dt; /* 70 degrees per second */
341 if (angle > 3600.0)
342 angle -= 3600.0;
343
344 draw();
345
346 eglSwapBuffers(dpy, surf);
347
348
349 frames++;
350 }
351
352 GLfloat seconds = ct - st;
353 GLfloat fps = frames / seconds;
354 printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, fps);
355
356 }
357
358
359 int
360 main(int argc, char *argv[])
361 {
362 int maj, min;
363 EGLContext ctx;
364 EGLSurface screen_surf;
365 EGLConfig configs[MAX_CONFIGS];
366 EGLint numConfigs, i;
367 EGLBoolean b;
368 EGLDisplay d;
369 EGLint screenAttribs[10];
370 EGLModeMESA mode[MAX_MODES];
371 EGLScreenMESA screen;
372 EGLint count, chosenMode;
373 GLboolean printInfo = GL_FALSE;
374 EGLint width = 0, height = 0;
375
376 /* parse cmd line args */
377 for (i = 1; i < argc; i++)
378 {
379 if (strcmp(argv[i], "-info") == 0)
380 {
381 printInfo = GL_TRUE;
382 }
383 else
384 printf("Warning: unknown parameter: %s\n", argv[i]);
385 }
386
387 /* DBR : Create EGL context/surface etc */
388 d = eglGetDisplay("!EGL_i915");
389 assert(d);
390
391 if (!eglInitialize(d, &maj, &min)) {
392 printf("eglgears: eglInitialize failed\n");
393 exit(1);
394 }
395
396 printf("eglgears: EGL version = %d.%d\n", maj, min);
397 printf("eglgears: EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR));
398
399 /* XXX use ChooseConfig */
400 eglGetConfigs(d, configs, MAX_CONFIGS, &numConfigs);
401 eglGetScreensMESA(d, &screen, 1, &count);
402
403 if (!eglGetModesMESA(d, screen, mode, MAX_MODES, &count) || count == 0) {
404 printf("eglgears: eglGetModesMESA failed!\n");
405 return 0;
406 }
407
408 /* Print list of modes, and find the one to use */
409 printf("eglgears: Found %d modes:\n", count);
410 for (i = 0; i < count; i++) {
411 EGLint w, h;
412 eglGetModeAttribMESA(d, mode[i], EGL_WIDTH, &w);
413 eglGetModeAttribMESA(d, mode[i], EGL_HEIGHT, &h);
414 printf("%3d: %d x %d\n", i, w, h);
415 if (w > width && h > height && w <= 1280 && h <= 1024) {
416 width = w;
417 height = h;
418 chosenMode = i;
419 }
420 }
421 printf("eglgears: Using screen mode/size %d: %d x %d\n", chosenMode, width, height);
422
423 ctx = eglCreateContext(d, configs[0], EGL_NO_CONTEXT, NULL);
424 if (ctx == EGL_NO_CONTEXT) {
425 printf("eglgears: failed to create context\n");
426 return 0;
427 }
428
429 /* build up screenAttribs array */
430 i = 0;
431 screenAttribs[i++] = EGL_WIDTH;
432 screenAttribs[i++] = width;
433 screenAttribs[i++] = EGL_HEIGHT;
434 screenAttribs[i++] = height;
435 screenAttribs[i++] = EGL_NONE;
436
437 screen_surf = eglCreateScreenSurfaceMESA(d, configs[0], screenAttribs);
438 if (screen_surf == EGL_NO_SURFACE) {
439 printf("eglgears: failed to create screen surface\n");
440 return 0;
441 }
442
443 b = eglShowScreenSurfaceMESA(d, screen, screen_surf, mode[chosenMode]);
444 if (!b) {
445 printf("eglgears: show surface failed\n");
446 return 0;
447 }
448
449 b = eglMakeCurrent(d, screen_surf, screen_surf, ctx);
450 if (!b) {
451 printf("eglgears: make current failed\n");
452 return 0;
453 }
454
455 if (printInfo)
456 {
457 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
458 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
459 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
460 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
461 }
462
463 init();
464 reshape(width, height);
465
466 glDrawBuffer( GL_BACK );
467
468 run_gears(d, screen_surf, 5.0);
469
470 eglDestroySurface(d, screen_surf);
471 eglDestroyContext(d, ctx);
472 eglTerminate(d);
473
474 return 0;
475 }