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 #define M_PI 3.14159265
29 static int WinWidth
= 300, WinHeight
= 300;
31 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
35 Normal(GLfloat
*n
, GLfloat nx
, GLfloat ny
, GLfloat nz
)
43 Vertex(GLfloat
*v
, GLfloat vx
, GLfloat vy
, GLfloat vz
)
51 Texcoord(GLfloat
*v
, GLfloat s
, GLfloat t
)
58 /* Borrowed from glut, adapted */
60 draw_torus(GLfloat r
, GLfloat R
, GLint nsides
, GLint rings
)
63 GLfloat theta
, phi
, theta1
;
64 GLfloat cosTheta
, sinTheta
;
65 GLfloat cosTheta1
, sinTheta1
;
66 GLfloat ringDelta
, sideDelta
;
67 GLfloat varray
[100][3], narray
[100][3], tarray
[100][2];
70 glVertexPointer(3, GL_FLOAT
, 0, varray
);
71 glNormalPointer(GL_FLOAT
, 0, narray
);
72 glTexCoordPointer(2, GL_FLOAT
, 0, tarray
);
73 glEnableClientState(GL_VERTEX_ARRAY
);
74 glEnableClientState(GL_NORMAL_ARRAY
);
75 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
77 ringDelta
= 2.0 * M_PI
/ rings
;
78 sideDelta
= 2.0 * M_PI
/ nsides
;
83 for (i
= rings
- 1; i
>= 0; i
--) {
84 theta1
= theta
+ ringDelta
;
85 cosTheta1
= cos(theta1
);
86 sinTheta1
= sin(theta1
);
88 vcount
= 0; /* glBegin(GL_QUAD_STRIP); */
91 for (j
= nsides
; j
>= 0; j
--) {
93 GLfloat cosPhi
, sinPhi
, dist
;
98 dist
= R
+ r
* cosPhi
;
100 s0
= 20.0 * theta
/ (2.0 * M_PI
);
101 s1
= 20.0 * theta1
/ (2.0 * M_PI
);
102 t
= 8.0 * phi
/ (2.0 * M_PI
);
104 Normal(narray
[vcount
], cosTheta1
* cosPhi
, -sinTheta1
* cosPhi
, sinPhi
);
105 Texcoord(tarray
[vcount
], s1
, t
);
106 Vertex(varray
[vcount
], cosTheta1
* dist
, -sinTheta1
* dist
, r
* sinPhi
);
109 Normal(narray
[vcount
], cosTheta
* cosPhi
, -sinTheta
* cosPhi
, sinPhi
);
110 Texcoord(tarray
[vcount
], s0
, t
);
111 Vertex(varray
[vcount
], cosTheta
* dist
, -sinTheta
* dist
, r
* sinPhi
);
116 assert(vcount
<= 100);
117 glDrawArrays(GL_TRIANGLE_STRIP
, 0, vcount
);
120 cosTheta
= cosTheta1
;
121 sinTheta
= sinTheta1
;
124 glDisableClientState(GL_VERTEX_ARRAY
);
125 glDisableClientState(GL_NORMAL_ARRAY
);
126 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
133 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
136 glRotatef(view_rotx
, 1, 0, 0);
137 glRotatef(view_roty
, 0, 1, 0);
138 glRotatef(view_rotz
, 0, 0, 1);
139 glScalef(0.5, 0.5, 0.5);
141 draw_torus(1.0, 3.0, 30, 60);
150 * Draw to both the window and pbuffer and compare results.
153 draw_both(EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
156 unsigned *wbuf
, *pbuf
;
157 int x
= 100, y
= 110;
160 wbuf
= (unsigned *) malloc(WinWidth
* WinHeight
* 4);
161 pbuf
= (unsigned *) malloc(WinWidth
* WinHeight
* 4);
163 glPixelStorei(GL_PACK_ALIGNMENT
, 1);
165 /* first draw to window */
166 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
167 printf("Error: eglMakeCurrent(window) failed\n");
171 glReadPixels(0, 0, WinWidth
, WinHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, wbuf
);
172 printf("Window[%d,%d] = 0x%08x\n", x
, y
, wbuf
[y
*WinWidth
+x
]);
174 eglSwapBuffers(egl_dpy
, egl_surf
);
176 /* then draw to pbuffer */
177 if (!eglMakeCurrent(egl_dpy
, egl_pbuf
, egl_pbuf
, egl_ctx
)) {
178 printf("Error: eglMakeCurrent(pbuffer) failed\n");
182 glReadPixels(0, 0, WinWidth
, WinHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, pbuf
);
183 printf("Pbuffer[%d,%d] = 0x%08x\n", x
, y
, pbuf
[y
*WinWidth
+x
]);
186 /* compare renderings */
187 for (dif
= i
= 0; i
< WinWidth
* WinHeight
; i
++) {
188 if (wbuf
[i
] != pbuf
[i
]) {
195 printf("Difference at %d: 0x%08x vs. 0x%08x\n", i
, wbuf
[i
], pbuf
[i
]);
197 printf("Window rendering matches Pbuffer rendering!\n");
204 /* new window size or exposure */
206 reshape(int width
, int height
)
208 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
213 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
215 glMatrixMode(GL_PROJECTION
);
218 #ifdef GL_VERSION_ES_CM_1_0
219 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
221 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
224 glMatrixMode(GL_MODELVIEW
);
226 glTranslatef(0.0, 0.0, -15.0);
234 GLenum Filter
= GL_LINEAR
;
235 GLubyte image
[SZ
][SZ
][4];
238 for (i
= 0; i
< SZ
; i
++) {
239 for (j
= 0; j
< SZ
; j
++) {
240 GLfloat d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
243 image
[i
][j
][0] = 255;
244 image
[i
][j
][1] = 255;
245 image
[i
][j
][2] = 255;
246 image
[i
][j
][3] = 255;
249 image
[i
][j
][0] = 127;
250 image
[i
][j
][1] = 127;
251 image
[i
][j
][2] = 127;
252 image
[i
][j
][3] = 255;
257 glActiveTexture(GL_TEXTURE0
); /* unit 0 */
258 glBindTexture(GL_TEXTURE_2D
, 42);
259 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ
, SZ
, 0,
260 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
261 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
262 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
263 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
264 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
273 static const GLfloat red
[4] = {1, 0, 0, 0};
274 static const GLfloat white
[4] = {1.0, 1.0, 1.0, 1.0};
275 static const GLfloat diffuse
[4] = {0.7, 0.7, 0.7, 1.0};
276 static const GLfloat specular
[4] = {0.001, 0.001, 0.001, 1.0};
277 static const GLfloat pos
[4] = {20, 20, 50, 1};
279 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red
);
280 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, white
);
281 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 9.0);
283 glEnable(GL_LIGHTING
);
285 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
286 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
287 glLightfv(GL_LIGHT0
, GL_SPECULAR
, specular
);
289 glClearColor(0.4, 0.4, 0.4, 0.0);
290 glEnable(GL_DEPTH_TEST
);
293 glEnable(GL_TEXTURE_2D
);
298 * Create an RGB, double-buffered X window.
299 * Return the window and context handles.
302 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
304 int x
, int y
, int width
, int height
,
309 static const EGLint attribs
[] = {
318 XSetWindowAttributes attr
;
322 XVisualInfo
*visInfo
, visTemplate
;
329 scrnum
= DefaultScreen( x_dpy
);
330 root
= RootWindow( x_dpy
, scrnum
);
332 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
333 printf("Error: couldn't get an EGL visual config\n");
338 assert(num_configs
> 0);
340 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
341 printf("Error: eglGetConfigAttrib() failed\n");
345 /* The X window visual must match the EGL config */
346 visTemplate
.visualid
= vid
;
347 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
349 printf("Error: couldn't get X visual\n");
353 /* window attributes */
354 attr
.background_pixel
= 0;
355 attr
.border_pixel
= 0;
356 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
357 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
358 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
360 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
361 0, visInfo
->depth
, InputOutput
,
362 visInfo
->visual
, mask
, &attr
);
364 /* set hints and properties */
366 XSizeHints sizehints
;
369 sizehints
.width
= width
;
370 sizehints
.height
= height
;
371 sizehints
.flags
= USSize
| USPosition
;
372 XSetNormalHints(x_dpy
, win
, &sizehints
);
373 XSetStandardProperties(x_dpy
, win
, name
, name
,
374 None
, (char **)NULL
, 0, &sizehints
);
377 eglBindAPI(EGL_OPENGL_ES_API
);
379 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
381 printf("Error: eglCreateContext failed\n");
385 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
388 printf("Error: eglCreateWindowSurface failed\n");
400 make_pbuffer(Display
*x_dpy
, EGLDisplay egl_dpy
, int width
, int height
)
402 static const EGLint config_attribs
[] = {
412 EGLint pbuf_attribs
[5];
414 pbuf_attribs
[0] = EGL_WIDTH
;
415 pbuf_attribs
[1] = width
;
416 pbuf_attribs
[2] = EGL_HEIGHT
;
417 pbuf_attribs
[3] = height
;
418 pbuf_attribs
[4] = EGL_NONE
;
420 if (!eglChooseConfig( egl_dpy
, config_attribs
, &config
, 1, &num_configs
)) {
421 printf("Error: couldn't get an EGL config for pbuffer\n");
425 pbuf
= eglCreatePbufferSurface(egl_dpy
, config
, pbuf_attribs
);
432 event_loop(Display
*dpy
, Window win
,
433 EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
441 if (!anim
|| XPending(dpy
)) {
443 XNextEvent(dpy
, &event
);
445 switch (event
.type
) {
449 case ConfigureNotify
:
450 if (event
.xconfigure
.window
== win
)
451 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
457 code
= XLookupKeysym(&event
.xkey
, 0);
458 if (code
== XK_Left
) {
461 else if (code
== XK_Right
) {
464 else if (code
== XK_Up
) {
467 else if (code
== XK_Down
) {
471 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
473 if (buffer
[0] == ' ') {
476 else if (buffer
[0] == 27) {
496 draw_both(egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
506 printf(" -display <displayname> set the display to run on\n");
507 printf(" -info display OpenGL renderer info\n");
512 main(int argc
, char *argv
[])
516 EGLSurface egl_surf
, egl_pbuf
;
519 char *dpyName
= NULL
;
520 GLboolean printInfo
= GL_FALSE
;
521 EGLint egl_major
, egl_minor
;
525 for (i
= 1; i
< argc
; i
++) {
526 if (strcmp(argv
[i
], "-display") == 0) {
530 else if (strcmp(argv
[i
], "-info") == 0) {
539 x_dpy
= XOpenDisplay(dpyName
);
541 printf("Error: couldn't open display %s\n",
542 dpyName
? dpyName
: getenv("DISPLAY"));
546 egl_dpy
= eglGetDisplay(x_dpy
);
548 printf("Error: eglGetDisplay() failed\n");
552 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
553 printf("Error: eglInitialize() failed\n");
557 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
558 printf("EGL_VERSION = %s\n", s
);
560 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
561 printf("EGL_VENDOR = %s\n", s
);
563 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
564 printf("EGL_EXTENSIONS = %s\n", s
);
566 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
567 printf("EGL_CLIENT_APIS = %s\n", s
);
569 make_x_window(x_dpy
, egl_dpy
,
570 "pbuffer", 0, 0, WinWidth
, WinHeight
,
571 &win
, &egl_ctx
, &egl_surf
);
573 egl_pbuf
= make_pbuffer(x_dpy
, egl_dpy
, WinWidth
, WinHeight
);
575 printf("Error: eglCreatePBufferSurface() failed\n");
579 XMapWindow(x_dpy
, win
);
580 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
581 printf("Error: eglMakeCurrent() failed\n");
586 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
587 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
588 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
589 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
594 /* Set initial projection/viewing transformation.
595 * We can't be sure we'll get a ConfigureNotify event when the window
598 reshape(WinWidth
, WinHeight
);
600 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
602 eglDestroyContext(egl_dpy
, egl_ctx
);
603 eglDestroySurface(egl_dpy
, egl_surf
);
604 eglTerminate(egl_dpy
);
607 XDestroyWindow(x_dpy
, win
);
608 XCloseDisplay(x_dpy
);