2 * Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
6 * Draw a lit, textured torus with X/EGL and OpenGL ES 1.x
18 #include <X11/Xutil.h>
19 #include <X11/keysym.h>
21 #include <GLES/glext.h>
26 GLenum internalFormat
;
31 { GL_PALETTE4_RGB8_OES
, "GL_PALETTE4_RGB8_OES", 16, 3 },
32 { GL_PALETTE4_RGBA8_OES
, "GL_PALETTE4_RGBA8_OES", 16, 4 },
33 { GL_PALETTE4_R5_G6_B5_OES
, "GL_PALETTE4_R5_G6_B5_OES", 16, 2 },
34 { GL_PALETTE4_RGBA4_OES
, "GL_PALETTE4_RGBA4_OES", 16, 2 },
35 { GL_PALETTE4_RGB5_A1_OES
, "GL_PALETTE4_RGB5_A1_OES", 16, 2 },
36 { GL_PALETTE8_RGB8_OES
, "GL_PALETTE8_RGB8_OES", 256, 3 },
37 { GL_PALETTE8_RGBA8_OES
, "GL_PALETTE8_RGBA8_OES", 256, 4 },
38 { GL_PALETTE8_R5_G6_B5_OES
, "GL_PALETTE8_R5_G6_B5_OES", 256, 2 },
39 { GL_PALETTE8_RGBA4_OES
, "GL_PALETTE8_RGBA4_OES", 256, 2 },
40 { GL_PALETTE8_RGB5_A1_OES
, "GL_PALETTE8_RGB5_A1_OES", 256, 2 }
42 #define NUM_CPAL_FORMATS (sizeof(cpal_formats) / sizeof(cpal_formats[0]))
44 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
45 static GLint tex_format
= NUM_CPAL_FORMATS
;
49 Normal(GLfloat
*n
, GLfloat nx
, GLfloat ny
, GLfloat nz
)
57 Vertex(GLfloat
*v
, GLfloat vx
, GLfloat vy
, GLfloat vz
)
65 Texcoord(GLfloat
*v
, GLfloat s
, GLfloat t
)
72 /* Borrowed from glut, adapted */
74 draw_torus(GLfloat r
, GLfloat R
, GLint nsides
, GLint rings
)
77 GLfloat theta
, phi
, theta1
;
78 GLfloat cosTheta
, sinTheta
;
79 GLfloat cosTheta1
, sinTheta1
;
80 GLfloat ringDelta
, sideDelta
;
81 GLfloat varray
[100][3], narray
[100][3], tarray
[100][2];
84 glVertexPointer(3, GL_FLOAT
, 0, varray
);
85 glNormalPointer(GL_FLOAT
, 0, narray
);
86 glTexCoordPointer(2, GL_FLOAT
, 0, tarray
);
87 glEnableClientState(GL_VERTEX_ARRAY
);
88 glEnableClientState(GL_NORMAL_ARRAY
);
89 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
91 ringDelta
= 2.0 * M_PI
/ rings
;
92 sideDelta
= 2.0 * M_PI
/ nsides
;
97 for (i
= rings
- 1; i
>= 0; i
--) {
98 theta1
= theta
+ ringDelta
;
99 cosTheta1
= cos(theta1
);
100 sinTheta1
= sin(theta1
);
102 vcount
= 0; /* glBegin(GL_QUAD_STRIP); */
105 for (j
= nsides
; j
>= 0; j
--) {
107 GLfloat cosPhi
, sinPhi
, dist
;
112 dist
= R
+ r
* cosPhi
;
114 s0
= 20.0 * theta
/ (2.0 * M_PI
);
115 s1
= 20.0 * theta1
/ (2.0 * M_PI
);
116 t
= 8.0 * phi
/ (2.0 * M_PI
);
118 Normal(narray
[vcount
], cosTheta1
* cosPhi
, -sinTheta1
* cosPhi
, sinPhi
);
119 Texcoord(tarray
[vcount
], s1
, t
);
120 Vertex(varray
[vcount
], cosTheta1
* dist
, -sinTheta1
* dist
, r
* sinPhi
);
123 Normal(narray
[vcount
], cosTheta
* cosPhi
, -sinTheta
* cosPhi
, sinPhi
);
124 Texcoord(tarray
[vcount
], s0
, t
);
125 Vertex(varray
[vcount
], cosTheta
* dist
, -sinTheta
* dist
, r
* sinPhi
);
130 assert(vcount
<= 100);
131 glDrawArrays(GL_TRIANGLE_STRIP
, 0, vcount
);
134 cosTheta
= cosTheta1
;
135 sinTheta
= sinTheta1
;
138 glDisableClientState(GL_VERTEX_ARRAY
);
139 glDisableClientState(GL_NORMAL_ARRAY
);
140 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
147 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
150 glRotatef(view_rotx
, 1, 0, 0);
151 glRotatef(view_roty
, 0, 1, 0);
152 glRotatef(view_rotz
, 0, 0, 1);
153 glScalef(0.5, 0.5, 0.5);
155 draw_torus(1.0, 3.0, 30, 60);
161 /* new window size or exposure */
163 reshape(int width
, int height
)
165 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
167 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
169 glMatrixMode(GL_PROJECTION
);
172 #ifdef GL_VERSION_ES_CM_1_0
173 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
175 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
178 glMatrixMode(GL_MODELVIEW
);
180 glTranslatef(0.0, 0.0, -15.0);
185 make_cpal_texture(GLint idx
)
188 GLenum internalFormat
= GL_PALETTE4_RGB8_OES
+ idx
;
189 GLenum Filter
= GL_LINEAR
;
190 GLubyte palette
[256 * 4 + SZ
* SZ
];
194 GLuint packed_indices
= 0;
196 assert(cpal_formats
[idx
].internalFormat
== internalFormat
);
199 switch (internalFormat
) {
200 case GL_PALETTE4_RGB8_OES
:
201 case GL_PALETTE8_RGB8_OES
:
211 case GL_PALETTE4_RGBA8_OES
:
212 case GL_PALETTE8_RGBA8_OES
:
224 case GL_PALETTE4_R5_G6_B5_OES
:
225 case GL_PALETTE8_R5_G6_B5_OES
:
227 GLushort
*pal
= (GLushort
*) palette
;
229 pal
[0] = (31 << 11 | 63 << 5 | 31);
231 pal
[1] = (15 << 11 | 31 << 5 | 15);
234 case GL_PALETTE4_RGBA4_OES
:
235 case GL_PALETTE8_RGBA4_OES
:
237 GLushort
*pal
= (GLushort
*) palette
;
239 pal
[0] = (15 << 12 | 15 << 8 | 15 << 4 | 15);
241 pal
[1] = (7 << 12 | 7 << 8 | 7 << 4 | 15);
244 case GL_PALETTE4_RGB5_A1_OES
:
245 case GL_PALETTE8_RGB5_A1_OES
:
247 GLushort
*pal
= (GLushort
*) palette
;
249 pal
[0] = (31 << 11 | 31 << 6 | 31 << 1 | 1);
251 pal
[1] = (15 << 11 | 15 << 6 | 15 << 1 | 1);
256 image_size
= cpal_formats
[idx
].size
* cpal_formats
[idx
].num_entries
;
257 indices
= palette
+ image_size
;
258 for (i
= 0; i
< SZ
; i
++) {
259 for (j
= 0; j
< SZ
; j
++) {
262 d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
264 index
= (d
< SZ
/ 3) ? 0 : 1;
266 if (cpal_formats
[idx
].num_entries
== 16) {
267 /* 4-bit indices packed in GLubyte */
268 packed_indices
|= index
<< (4 * (1 - (j
% 2)));
270 *(indices
+ (i
* SZ
+ j
- 1) / 2) = packed_indices
& 0xff;
277 *(indices
+ i
* SZ
+ j
) = index
;
283 glActiveTexture(GL_TEXTURE0
); /* unit 0 */
284 glBindTexture(GL_TEXTURE_2D
, 42);
285 glCompressedTexImage2D(GL_TEXTURE_2D
, 0, internalFormat
, SZ
, SZ
, 0,
286 image_size
, palette
);
288 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
289 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
290 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
291 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
302 GLenum Filter
= GL_LINEAR
;
303 GLubyte image
[SZ
][SZ
][4];
306 for (i
= 0; i
< SZ
; i
++) {
307 for (j
= 0; j
< SZ
; j
++) {
308 GLfloat d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
311 image
[i
][j
][0] = 255;
312 image
[i
][j
][1] = 255;
313 image
[i
][j
][2] = 255;
314 image
[i
][j
][3] = 255;
317 image
[i
][j
][0] = 127;
318 image
[i
][j
][1] = 127;
319 image
[i
][j
][2] = 127;
320 image
[i
][j
][3] = 255;
325 glActiveTexture(GL_TEXTURE0
); /* unit 0 */
326 glBindTexture(GL_TEXTURE_2D
, 42);
327 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ
, SZ
, 0,
328 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
329 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
330 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
331 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
332 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
335 return sizeof(image
);
343 static const GLfloat red
[4] = {1, 0, 0, 0};
344 static const GLfloat white
[4] = {1.0, 1.0, 1.0, 1.0};
345 static const GLfloat diffuse
[4] = {0.7, 0.7, 0.7, 1.0};
346 static const GLfloat specular
[4] = {0.001, 0.001, 0.001, 1.0};
347 static const GLfloat pos
[4] = {20, 20, 50, 1};
349 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red
);
350 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, white
);
351 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 9.0);
353 glEnable(GL_LIGHTING
);
355 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
356 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
357 glLightfv(GL_LIGHT0
, GL_SPECULAR
, specular
);
359 glClearColor(0.4, 0.4, 0.4, 0.0);
360 glEnable(GL_DEPTH_TEST
);
363 glEnable(GL_TEXTURE_2D
);
368 * Create an RGB, double-buffered X window.
369 * Return the window and context handles.
372 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
374 int x
, int y
, int width
, int height
,
379 static const EGLint attribs
[] = {
388 XSetWindowAttributes attr
;
392 XVisualInfo
*visInfo
, visTemplate
;
399 scrnum
= DefaultScreen( x_dpy
);
400 root
= RootWindow( x_dpy
, scrnum
);
402 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
403 printf("Error: couldn't get an EGL visual config\n");
408 assert(num_configs
> 0);
410 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
411 printf("Error: eglGetConfigAttrib() failed\n");
415 /* The X window visual must match the EGL config */
416 visTemplate
.visualid
= vid
;
417 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
419 printf("Error: couldn't get X visual\n");
423 /* window attributes */
424 attr
.background_pixel
= 0;
425 attr
.border_pixel
= 0;
426 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
427 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
428 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
430 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
431 0, visInfo
->depth
, InputOutput
,
432 visInfo
->visual
, mask
, &attr
);
434 /* set hints and properties */
436 XSizeHints sizehints
;
439 sizehints
.width
= width
;
440 sizehints
.height
= height
;
441 sizehints
.flags
= USSize
| USPosition
;
442 XSetNormalHints(x_dpy
, win
, &sizehints
);
443 XSetStandardProperties(x_dpy
, win
, name
, name
,
444 None
, (char **)NULL
, 0, &sizehints
);
447 eglBindAPI(EGL_OPENGL_ES_API
);
449 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
451 printf("Error: eglCreateContext failed\n");
455 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
458 printf("Error: eglCreateWindowSurface failed\n");
470 event_loop(Display
*dpy
, Window win
,
471 EGLDisplay egl_dpy
, EGLSurface egl_surf
)
478 if (!anim
|| XPending(dpy
)) {
480 XNextEvent(dpy
, &event
);
482 switch (event
.type
) {
486 case ConfigureNotify
:
487 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
493 code
= XLookupKeysym(&event
.xkey
, 0);
494 if (code
== XK_Left
) {
497 else if (code
== XK_Right
) {
500 else if (code
== XK_Up
) {
503 else if (code
== XK_Down
) {
506 else if (code
== XK_t
) {
508 tex_format
= (tex_format
+ 1) % (NUM_CPAL_FORMATS
+ 1);
509 if (tex_format
< NUM_CPAL_FORMATS
) {
510 size
= make_cpal_texture(tex_format
);
511 printf("Using %s (%d bytes)\n",
512 cpal_formats
[tex_format
].name
, size
);
515 size
= make_texture();
516 printf("Using uncompressed texture (%d bytes)\n", size
);
520 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
522 if (buffer
[0] == ' ') {
525 else if (buffer
[0] == 27) {
546 eglSwapBuffers(egl_dpy
, egl_surf
);
556 printf(" -display <displayname> set the display to run on\n");
557 printf(" -info display OpenGL renderer info\n");
562 main(int argc
, char *argv
[])
564 const int winWidth
= 300, winHeight
= 300;
570 char *dpyName
= NULL
;
571 GLboolean printInfo
= GL_FALSE
;
572 EGLint egl_major
, egl_minor
;
576 for (i
= 1; i
< argc
; i
++) {
577 if (strcmp(argv
[i
], "-display") == 0) {
581 else if (strcmp(argv
[i
], "-info") == 0) {
590 x_dpy
= XOpenDisplay(dpyName
);
592 printf("Error: couldn't open display %s\n",
593 dpyName
? dpyName
: getenv("DISPLAY"));
597 egl_dpy
= eglGetDisplay(x_dpy
);
599 printf("Error: eglGetDisplay() failed\n");
603 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
604 printf("Error: eglInitialize() failed\n");
608 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
609 printf("EGL_VERSION = %s\n", s
);
611 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
612 printf("EGL_VENDOR = %s\n", s
);
614 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
615 printf("EGL_EXTENSIONS = %s\n", s
);
617 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
618 printf("EGL_CLIENT_APIS = %s\n", s
);
620 make_x_window(x_dpy
, egl_dpy
,
621 "torus", 0, 0, winWidth
, winHeight
,
622 &win
, &egl_ctx
, &egl_surf
);
624 XMapWindow(x_dpy
, win
);
625 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
626 printf("Error: eglMakeCurrent() failed\n");
631 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
632 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
633 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
634 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
639 /* Set initial projection/viewing transformation.
640 * We can't be sure we'll get a ConfigureNotify event when the window
643 reshape(winWidth
, winHeight
);
645 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
);
647 eglDestroyContext(egl_dpy
, egl_ctx
);
648 eglDestroySurface(egl_dpy
, egl_surf
);
649 eglTerminate(egl_dpy
);
652 XDestroyWindow(x_dpy
, win
);
653 XCloseDisplay(x_dpy
);