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 /* then draw to pbuffer */
172 if (!eglMakeCurrent(egl_dpy
, egl_pbuf
, egl_pbuf
, egl_ctx
)) {
173 printf("Error: eglMakeCurrent(pbuffer) failed\n");
177 glReadPixels(0, 0, WinWidth
, WinHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, pbuf
);
178 printf("Pbuffer[%d,%d] = 0x%08x\n", x
, y
, pbuf
[y
*WinWidth
+x
]);
180 eglSwapBuffers(egl_dpy
, egl_surf
);
182 /* compare renderings */
183 for (dif
= i
= 0; i
< WinWidth
* WinHeight
; i
++) {
184 if (wbuf
[i
] != pbuf
[i
]) {
191 printf("Difference at %d: 0x%08x vs. 0x%08x\n", i
, wbuf
[i
], pbuf
[i
]);
193 printf("Window rendering matches Pbuffer rendering!\n");
200 /* new window size or exposure */
202 reshape(int width
, int height
)
204 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
209 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
211 glMatrixMode(GL_PROJECTION
);
214 #ifdef GL_VERSION_ES_CM_1_0
215 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
217 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
220 glMatrixMode(GL_MODELVIEW
);
222 glTranslatef(0.0, 0.0, -15.0);
230 GLenum Filter
= GL_LINEAR
;
231 GLubyte image
[SZ
][SZ
][4];
234 for (i
= 0; i
< SZ
; i
++) {
235 for (j
= 0; j
< SZ
; j
++) {
236 GLfloat d
= (i
- SZ
/2) * (i
- SZ
/2) + (j
- SZ
/2) * (j
- SZ
/2);
239 image
[i
][j
][0] = 255;
240 image
[i
][j
][1] = 255;
241 image
[i
][j
][2] = 255;
242 image
[i
][j
][3] = 255;
245 image
[i
][j
][0] = 127;
246 image
[i
][j
][1] = 127;
247 image
[i
][j
][2] = 127;
248 image
[i
][j
][3] = 255;
253 glActiveTexture(GL_TEXTURE0
); /* unit 0 */
254 glBindTexture(GL_TEXTURE_2D
, 42);
255 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, SZ
, SZ
, 0,
256 GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
257 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, Filter
);
258 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, Filter
);
259 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
260 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
269 static const GLfloat red
[4] = {1, 0, 0, 0};
270 static const GLfloat white
[4] = {1.0, 1.0, 1.0, 1.0};
271 static const GLfloat diffuse
[4] = {0.7, 0.7, 0.7, 1.0};
272 static const GLfloat specular
[4] = {0.001, 0.001, 0.001, 1.0};
273 static const GLfloat pos
[4] = {20, 20, 50, 1};
275 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, red
);
276 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, white
);
277 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, 9.0);
279 glEnable(GL_LIGHTING
);
281 glLightfv(GL_LIGHT0
, GL_POSITION
, pos
);
282 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
283 glLightfv(GL_LIGHT0
, GL_SPECULAR
, specular
);
285 glClearColor(0.4, 0.4, 0.4, 0.0);
286 glEnable(GL_DEPTH_TEST
);
289 glEnable(GL_TEXTURE_2D
);
294 * Create an RGB, double-buffered X window.
295 * Return the window and context handles.
298 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
300 int x
, int y
, int width
, int height
,
305 static const EGLint attribs
[] = {
314 XSetWindowAttributes attr
;
318 XVisualInfo
*visInfo
, visTemplate
;
325 scrnum
= DefaultScreen( x_dpy
);
326 root
= RootWindow( x_dpy
, scrnum
);
328 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
329 printf("Error: couldn't get an EGL visual config\n");
334 assert(num_configs
> 0);
336 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
337 printf("Error: eglGetConfigAttrib() failed\n");
341 /* The X window visual must match the EGL config */
342 visTemplate
.visualid
= vid
;
343 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
345 printf("Error: couldn't get X visual\n");
349 /* window attributes */
350 attr
.background_pixel
= 0;
351 attr
.border_pixel
= 0;
352 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
353 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
354 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
356 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
357 0, visInfo
->depth
, InputOutput
,
358 visInfo
->visual
, mask
, &attr
);
360 /* set hints and properties */
362 XSizeHints sizehints
;
365 sizehints
.width
= width
;
366 sizehints
.height
= height
;
367 sizehints
.flags
= USSize
| USPosition
;
368 XSetNormalHints(x_dpy
, win
, &sizehints
);
369 XSetStandardProperties(x_dpy
, win
, name
, name
,
370 None
, (char **)NULL
, 0, &sizehints
);
373 eglBindAPI(EGL_OPENGL_ES_API
);
375 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
377 printf("Error: eglCreateContext failed\n");
381 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
384 printf("Error: eglCreateWindowSurface failed\n");
396 make_pbuffer(Display
*x_dpy
, EGLDisplay egl_dpy
, int width
, int height
)
398 static const EGLint config_attribs
[] = {
408 EGLint pbuf_attribs
[5];
410 pbuf_attribs
[0] = EGL_WIDTH
;
411 pbuf_attribs
[1] = width
;
412 pbuf_attribs
[2] = EGL_HEIGHT
;
413 pbuf_attribs
[3] = height
;
414 pbuf_attribs
[4] = EGL_NONE
;
416 if (!eglChooseConfig( egl_dpy
, config_attribs
, &config
, 1, &num_configs
)) {
417 printf("Error: couldn't get an EGL config for pbuffer\n");
421 pbuf
= eglCreatePbufferSurface(egl_dpy
, config
, pbuf_attribs
);
428 event_loop(Display
*dpy
, Window win
,
429 EGLDisplay egl_dpy
, EGLSurface egl_surf
, EGLSurface egl_pbuf
,
437 if (!anim
|| XPending(dpy
)) {
439 XNextEvent(dpy
, &event
);
441 switch (event
.type
) {
445 case ConfigureNotify
:
446 if (event
.xconfigure
.window
== win
)
447 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
453 code
= XLookupKeysym(&event
.xkey
, 0);
454 if (code
== XK_Left
) {
457 else if (code
== XK_Right
) {
460 else if (code
== XK_Up
) {
463 else if (code
== XK_Down
) {
467 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
469 if (buffer
[0] == ' ') {
472 else if (buffer
[0] == 27) {
492 draw_both(egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
502 printf(" -display <displayname> set the display to run on\n");
503 printf(" -info display OpenGL renderer info\n");
508 main(int argc
, char *argv
[])
512 EGLSurface egl_surf
, egl_pbuf
;
515 char *dpyName
= NULL
;
516 GLboolean printInfo
= GL_FALSE
;
517 EGLint egl_major
, egl_minor
;
521 for (i
= 1; i
< argc
; i
++) {
522 if (strcmp(argv
[i
], "-display") == 0) {
526 else if (strcmp(argv
[i
], "-info") == 0) {
535 x_dpy
= XOpenDisplay(dpyName
);
537 printf("Error: couldn't open display %s\n",
538 dpyName
? dpyName
: getenv("DISPLAY"));
542 egl_dpy
= eglGetDisplay(x_dpy
);
544 printf("Error: eglGetDisplay() failed\n");
548 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
549 printf("Error: eglInitialize() failed\n");
553 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
554 printf("EGL_VERSION = %s\n", s
);
556 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
557 printf("EGL_VENDOR = %s\n", s
);
559 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
560 printf("EGL_EXTENSIONS = %s\n", s
);
562 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
563 printf("EGL_CLIENT_APIS = %s\n", s
);
565 make_x_window(x_dpy
, egl_dpy
,
566 "pbuffer", 0, 0, WinWidth
, WinHeight
,
567 &win
, &egl_ctx
, &egl_surf
);
569 egl_pbuf
= make_pbuffer(x_dpy
, egl_dpy
, WinWidth
, WinHeight
);
571 printf("Error: eglCreatePBufferSurface() failed\n");
575 XMapWindow(x_dpy
, win
);
576 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
577 printf("Error: eglMakeCurrent() failed\n");
582 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
583 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
584 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
585 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
590 /* Set initial projection/viewing transformation.
591 * We can't be sure we'll get a ConfigureNotify event when the window
594 reshape(WinWidth
, WinHeight
);
596 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
, egl_pbuf
, egl_ctx
);
598 eglDestroyContext(egl_dpy
, egl_ctx
);
599 eglDestroySurface(egl_dpy
, egl_surf
);
600 eglTerminate(egl_dpy
);
603 XDestroyWindow(x_dpy
, win
);
604 XCloseDisplay(x_dpy
);