2 * Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
18 #include <X11/Xutil.h>
19 #include <X11/keysym.h>
21 #include <GLES/glext.h>
26 static int WinWidth
= 300, WinHeight
= 300;
28 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
32 Normal(GLfloat
*n
, GLfloat nx
, GLfloat ny
, GLfloat nz
)
40 Vertex(GLfloat
*v
, GLfloat vx
, GLfloat vy
, GLfloat vz
)
48 Texcoord(GLfloat
*v
, GLfloat s
, GLfloat t
)
55 /* Borrowed from glut, adapted */
57 draw_torus(GLfloat r
, GLfloat R
, GLint nsides
, GLint rings
)
60 GLfloat theta
, phi
, theta1
;
61 GLfloat cosTheta
, sinTheta
;
62 GLfloat cosTheta1
, sinTheta1
;
63 GLfloat ringDelta
, sideDelta
;
64 GLfloat varray
[100][3], narray
[100][3], tarray
[100][2];
67 glVertexPointer(3, GL_FLOAT
, 0, varray
);
68 glNormalPointer(GL_FLOAT
, 0, narray
);
69 glTexCoordPointer(2, GL_FLOAT
, 0, tarray
);
70 glEnableClientState(GL_VERTEX_ARRAY
);
71 glEnableClientState(GL_NORMAL_ARRAY
);
72 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
74 ringDelta
= 2.0 * M_PI
/ rings
;
75 sideDelta
= 2.0 * M_PI
/ nsides
;
80 for (i
= rings
- 1; i
>= 0; i
--) {
81 theta1
= theta
+ ringDelta
;
82 cosTheta1
= cos(theta1
);
83 sinTheta1
= sin(theta1
);
85 vcount
= 0; /* glBegin(GL_QUAD_STRIP); */
88 for (j
= nsides
; j
>= 0; j
--) {
90 GLfloat cosPhi
, sinPhi
, dist
;
95 dist
= R
+ r
* cosPhi
;
97 s0
= 20.0 * theta
/ (2.0 * M_PI
);
98 s1
= 20.0 * theta1
/ (2.0 * M_PI
);
99 t
= 8.0 * phi
/ (2.0 * M_PI
);
101 Normal(narray
[vcount
], cosTheta1
* cosPhi
, -sinTheta1
* cosPhi
, sinPhi
);
102 Texcoord(tarray
[vcount
], s1
, t
);
103 Vertex(varray
[vcount
], cosTheta1
* dist
, -sinTheta1
* dist
, r
* sinPhi
);
106 Normal(narray
[vcount
], cosTheta
* cosPhi
, -sinTheta
* cosPhi
, sinPhi
);
107 Texcoord(tarray
[vcount
], s0
, t
);
108 Vertex(varray
[vcount
], cosTheta
* dist
, -sinTheta
* dist
, r
* sinPhi
);
113 assert(vcount
<= 100);
114 glDrawArrays(GL_TRIANGLE_STRIP
, 0, vcount
);
117 cosTheta
= cosTheta1
;
118 sinTheta
= sinTheta1
;
121 glDisableClientState(GL_VERTEX_ARRAY
);
122 glDisableClientState(GL_NORMAL_ARRAY
);
123 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
130 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
133 glRotatef(view_rotx
, 1, 0, 0);
134 glRotatef(view_roty
, 0, 1, 0);
135 glRotatef(view_rotz
, 0, 0, 1);
136 glScalef(0.5, 0.5, 0.5);
138 draw_torus(1.0, 3.0, 30, 60);
147 * Draw to both the window and pbuffer and compare results.
150 draw_both(EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
153 unsigned *wbuf
, *pbuf
;
154 int x
= 100, y
= 110;
157 wbuf
= (unsigned *) malloc(WinWidth
* WinHeight
* 4);
158 pbuf
= (unsigned *) malloc(WinWidth
* WinHeight
* 4);
160 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
162 /* first draw to window */
163 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
164 printf("Error: eglMakeCurrent(window) failed\n");
168 glReadPixels(0, 0, WinWidth
, WinHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, wbuf
);
169 printf("Window[%d,%d] = 0x%08x\n", x
, y
, wbuf
[y
*WinWidth
+x
]);
171 eglSwapBuffers(egl_dpy
, egl_surf
);
173 /* then draw to pbuffer */
174 if (!eglMakeCurrent(egl_dpy
, egl_pbuf
, egl_pbuf
, egl_ctx
)) {
175 printf("Error: eglMakeCurrent(pbuffer) failed\n");
179 glReadPixels(0, 0, WinWidth
, WinHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, pbuf
);
180 printf("Pbuffer[%d,%d] = 0x%08x\n", x
, y
, pbuf
[y
*WinWidth
+x
]);
183 /* compare renderings */
184 for (dif
= i
= 0; i
< WinWidth
* WinHeight
; i
++) {
185 if (wbuf
[i
] != pbuf
[i
]) {
192 printf("Difference at %d: 0x%08x vs. 0x%08x\n", i
, wbuf
[i
], pbuf
[i
]);
194 printf("Window rendering matches Pbuffer rendering!\n");
201 /* new window size or exposure */
203 reshape(int width
, int height
)
205 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
210 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
212 glMatrixMode(GL_PROJECTION
);
215 #ifdef GL_VERSION_ES_CM_1_0
216 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
218 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
221 glMatrixMode(GL_MODELVIEW
);
223 glTranslatef(0.0, 0.0, -15.0);
231 GLenum Filter
= GL_LINEAR
;
232 GLubyte image
[SZ
][SZ
][4];
235 for (i
= 0; i
< SZ
; i
++) {
236 for (j
= 0; j
< SZ
; j
++) {
237 GLfloat d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
240 image
[i
][j
][0] = 255;
241 image
[i
][j
][1] = 255;
242 image
[i
][j
][2] = 255;
243 image
[i
][j
][3] = 255;
246 image
[i
][j
][0] = 127;
247 image
[i
][j
][1] = 127;
248 image
[i
][j
][2] = 127;
249 image
[i
][j
][3] = 255;
254 glActiveTexture(GL_TEXTURE0
); /* unit 0 */
255 glBindTexture(GL_TEXTURE_2D
, 42);
256 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ
, SZ
, 0,
257 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
258 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
259 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
260 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
261 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
270 static const GLfloat red
[4] = {1, 0, 0, 0};
271 static const GLfloat white
[4] = {1.0, 1.0, 1.0, 1.0};
272 static const GLfloat diffuse
[4] = {0.7, 0.7, 0.7, 1.0};
273 static const GLfloat specular
[4] = {0.001, 0.001, 0.001, 1.0};
274 static const GLfloat pos
[4] = {20, 20, 50, 1};
276 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red
);
277 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, white
);
278 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 9.0);
280 glEnable(GL_LIGHTING
);
282 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
283 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
284 glLightfv(GL_LIGHT0
, GL_SPECULAR
, specular
);
286 glClearColor(0.4, 0.4, 0.4, 0.0);
287 glEnable(GL_DEPTH_TEST
);
290 glEnable(GL_TEXTURE_2D
);
295 * Create an RGB, double-buffered X window.
296 * Return the window and context handles.
299 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
301 int x
, int y
, int width
, int height
,
306 static const EGLint attribs
[] = {
315 XSetWindowAttributes attr
;
319 XVisualInfo
*visInfo
, visTemplate
;
326 scrnum
= DefaultScreen( x_dpy
);
327 root
= RootWindow( x_dpy
, scrnum
);
329 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
330 printf("Error: couldn't get an EGL visual config\n");
335 assert(num_configs
> 0);
337 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
338 printf("Error: eglGetConfigAttrib() failed\n");
342 /* The X window visual must match the EGL config */
343 visTemplate
.visualid
= vid
;
344 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
346 printf("Error: couldn't get X visual\n");
350 /* window attributes */
351 attr
.background_pixel
= 0;
352 attr
.border_pixel
= 0;
353 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
354 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
355 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
357 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
358 0, visInfo
->depth
, InputOutput
,
359 visInfo
->visual
, mask
, &attr
);
361 /* set hints and properties */
363 XSizeHints sizehints
;
366 sizehints
.width
= width
;
367 sizehints
.height
= height
;
368 sizehints
.flags
= USSize
| USPosition
;
369 XSetNormalHints(x_dpy
, win
, &sizehints
);
370 XSetStandardProperties(x_dpy
, win
, name
, name
,
371 None
, (char **)NULL
, 0, &sizehints
);
374 eglBindAPI(EGL_OPENGL_ES_API
);
376 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
378 printf("Error: eglCreateContext failed\n");
382 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
385 printf("Error: eglCreateWindowSurface failed\n");
397 make_pbuffer(Display
*x_dpy
, EGLDisplay egl_dpy
, int width
, int height
)
399 static const EGLint config_attribs
[] = {
409 EGLint pbuf_attribs
[5];
411 pbuf_attribs
[0] = EGL_WIDTH
;
412 pbuf_attribs
[1] = width
;
413 pbuf_attribs
[2] = EGL_HEIGHT
;
414 pbuf_attribs
[3] = height
;
415 pbuf_attribs
[4] = EGL_NONE
;
417 if (!eglChooseConfig( egl_dpy
, config_attribs
, &config
, 1, &num_configs
)) {
418 printf("Error: couldn't get an EGL config for pbuffer\n");
422 pbuf
= eglCreatePbufferSurface(egl_dpy
, config
, pbuf_attribs
);
429 event_loop(Display
*dpy
, Window win
,
430 EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
438 if (!anim
|| XPending(dpy
)) {
440 XNextEvent(dpy
, &event
);
442 switch (event
.type
) {
446 case ConfigureNotify
:
447 if (event
.xconfigure
.window
== win
)
448 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
454 code
= XLookupKeysym(&event
.xkey
, 0);
455 if (code
== XK_Left
) {
458 else if (code
== XK_Right
) {
461 else if (code
== XK_Up
) {
464 else if (code
== XK_Down
) {
468 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
470 if (buffer
[0] == ' ') {
473 else if (buffer
[0] == 27) {
493 draw_both(egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
503 printf(" -display <displayname> set the display to run on\n");
504 printf(" -info display OpenGL renderer info\n");
509 main(int argc
, char *argv
[])
513 EGLSurface egl_surf
, egl_pbuf
;
516 char *dpyName
= NULL
;
517 GLboolean printInfo
= GL_FALSE
;
518 EGLint egl_major
, egl_minor
;
522 for (i
= 1; i
< argc
; i
++) {
523 if (strcmp(argv
[i
], "-display") == 0) {
527 else if (strcmp(argv
[i
], "-info") == 0) {
536 x_dpy
= XOpenDisplay(dpyName
);
538 printf("Error: couldn't open display %s\n",
539 dpyName
? dpyName
: getenv("DISPLAY"));
543 egl_dpy
= eglGetDisplay(x_dpy
);
545 printf("Error: eglGetDisplay() failed\n");
549 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
550 printf("Error: eglInitialize() failed\n");
554 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
555 printf("EGL_VERSION = %s\n", s
);
557 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
558 printf("EGL_VENDOR = %s\n", s
);
560 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
561 printf("EGL_EXTENSIONS = %s\n", s
);
563 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
564 printf("EGL_CLIENT_APIS = %s\n", s
);
566 make_x_window(x_dpy
, egl_dpy
,
567 "pbuffer", 0, 0, WinWidth
, WinHeight
,
568 &win
, &egl_ctx
, &egl_surf
);
570 egl_pbuf
= make_pbuffer(x_dpy
, egl_dpy
, WinWidth
, WinHeight
);
572 printf("Error: eglCreatePBufferSurface() failed\n");
576 XMapWindow(x_dpy
, win
);
577 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
578 printf("Error: eglMakeCurrent() failed\n");
583 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
584 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
585 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
586 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
591 /* Set initial projection/viewing transformation.
592 * We can't be sure we'll get a ConfigureNotify event when the window
595 reshape(WinWidth
, WinHeight
);
597 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
599 eglDestroyContext(egl_dpy
, egl_ctx
);
600 eglDestroySurface(egl_dpy
, egl_surf
);
601 eglTerminate(egl_dpy
);
604 XDestroyWindow(x_dpy
, win
);
605 XCloseDisplay(x_dpy
);