2 * Copyright (C) 2008 Brian Paul All Rights Reserved.
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
23 * Draw a triangle with X/EGL and OpenGL ES 1.x
30 #define USE_FIXED_POINT 0
39 #include <X11/Xutil.h>
40 #include <X11/keysym.h>
42 #include <GL/gl.h> /* use full OpenGL */
44 #include <GLES/gl.h> /* use OpenGL ES 1.x */
45 #include <GLES/glext.h>
50 #define FLOAT_TO_FIXED(X) ((X) * 65535.0)
54 static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
61 static const GLfixed verts[3][2] = {
66 static const GLfixed colors[3][4] = {
67 { 65536, 0, 0, 65536 },
68 { 0, 65536, 0 , 65536},
69 { 0, 0, 65536 , 65536}
72 static const GLfloat verts[3][2] = {
77 static const GLfloat colors[3][4] = {
84 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
87 glRotatef(view_rotx, 1, 0, 0);
88 glRotatef(view_roty, 0, 1, 0);
89 glRotatef(view_rotz, 0, 0, 1);
93 glVertexPointer(2, GL_FIXED, 0, verts);
94 glColorPointer(4, GL_FIXED, 0, colors);
96 glVertexPointer(2, GL_FLOAT, 0, verts);
97 glColorPointer(4, GL_FLOAT, 0, colors);
99 glEnableClientState(GL_VERTEX_ARRAY);
100 glEnableClientState(GL_COLOR_ARRAY);
103 glDrawArrays(GL_TRIANGLES, 0, 3);
105 /* draw some points */
106 glPointSizex(FLOAT_TO_FIXED(15.5));
107 glDrawArrays(GL_POINTS, 0, 3);
109 glDisableClientState(GL_VERTEX_ARRAY);
110 glDisableClientState(GL_COLOR_ARRAY);
116 glGetFixedv(GL_POINT_SIZE, &size);
117 printf("GL_POINT_SIZE = 0x%x %f\n", size, size / 65536.0);
124 /* new window size or exposure */
126 reshape(int width, int height)
128 GLfloat ar = (GLfloat) width / (GLfloat) height;
130 glViewport(0, 0, (GLint) width, (GLint) height);
132 glMatrixMode(GL_PROJECTION);
134 #ifdef GL_VERSION_ES_CM_1_0
135 glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
137 glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
140 glMatrixMode(GL_MODELVIEW);
142 glTranslatef(0.0, 0.0, -10.0);
147 test_query_matrix(void)
149 PFNGLQUERYMATRIXXOESPROC procQueryMatrixx;
150 typedef void (*voidproc)();
151 GLfixed mantissa[16];
155 voidproc p = eglGetProcAddress("eglCreateContext");
158 procQueryMatrixx = (PFNGLQUERYMATRIXXOESPROC) eglGetProcAddress("glQueryMatrixxOES");
159 assert(procQueryMatrixx);
160 /* Actually try out this one */
161 rv = (*procQueryMatrixx)(mantissa, exponent);
162 for (i = 0; i < 16; i++) {
164 printf("matrix[%d] invalid\n", i);
167 printf("matrix[%d] = %f * 2^(%d)\n", i, mantissa[i]/65536.0, exponent[i]);
170 p = eglGetProcAddress("glFoo");
178 glClearColor(0.4, 0.4, 0.4, 0.0);
186 * Create an RGB, double-buffered X window.
187 * Return the window and context handles.
190 make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
192 int x, int y, int width, int height,
197 static const EGLint attribs[] = {
206 XSetWindowAttributes attr;
210 XVisualInfo *visInfo, visTemplate;
217 scrnum = DefaultScreen( x_dpy );
218 root = RootWindow( x_dpy, scrnum );
220 if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
221 printf("Error: couldn't get an EGL visual config\n");
226 assert(num_configs > 0);
228 if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
229 printf("Error: eglGetConfigAttrib() failed\n");
233 /* The X window visual must match the EGL config */
234 visTemplate.visualid = vid;
235 visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
237 printf("Error: couldn't get X visual\n");
241 /* window attributes */
242 attr.background_pixel = 0;
243 attr.border_pixel = 0;
244 attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
245 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
246 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
248 win = XCreateWindow( x_dpy, root, 0, 0, width, height,
249 0, visInfo->depth, InputOutput,
250 visInfo->visual, mask, &attr );
252 /* set hints and properties */
254 XSizeHints sizehints;
257 sizehints.width = width;
258 sizehints.height = height;
259 sizehints.flags = USSize | USPosition;
260 XSetNormalHints(x_dpy, win, &sizehints);
261 XSetStandardProperties(x_dpy, win, name, name,
262 None, (char **)NULL, 0, &sizehints);
266 eglBindAPI(EGL_OPENGL_API);
268 eglBindAPI(EGL_OPENGL_ES_API);
271 ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
273 printf("Error: eglCreateContext failed\n");
277 *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
280 printf("Error: eglCreateWindowSurface failed\n");
292 event_loop(Display *dpy, Window win,
293 EGLDisplay egl_dpy, EGLSurface egl_surf)
299 XNextEvent(dpy, &event);
301 switch (event.type) {
305 case ConfigureNotify:
306 reshape(event.xconfigure.width, event.xconfigure.height);
312 code = XLookupKeysym(&event.xkey, 0);
313 if (code == XK_Left) {
316 else if (code == XK_Right) {
319 else if (code == XK_Up) {
322 else if (code == XK_Down) {
326 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
328 if (buffer[0] == 27) {
342 eglSwapBuffers(egl_dpy, egl_surf);
352 printf(" -display <displayname> set the display to run on\n");
353 printf(" -info display OpenGL renderer info\n");
358 main(int argc, char *argv[])
360 const int winWidth = 300, winHeight = 300;
366 char *dpyName = NULL;
367 GLboolean printInfo = GL_FALSE;
368 EGLint egl_major, egl_minor;
375 enum {GetString, GetInteger} type;
377 {"GL_RENDERER", GL_RENDERER, GetString},
378 {"GL_VERSION", GL_VERSION, GetString},
379 {"GL_VENDOR", GL_VENDOR, GetString},
380 {"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
381 {"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
382 {"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
385 for (i = 1; i < argc; i++) {
386 if (strcmp(argv[i], "-display") == 0) {
390 else if (strcmp(argv[i], "-info") == 0) {
399 x_dpy = XOpenDisplay(dpyName);
401 printf("Error: couldn't open display %s\n",
402 dpyName ? dpyName : getenv("DISPLAY"));
406 egl_dpy = eglGetDisplay(x_dpy);
408 printf("Error: eglGetDisplay() failed\n");
412 if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
413 printf("Error: eglInitialize() failed\n");
417 s = eglQueryString(egl_dpy, EGL_VERSION);
418 printf("EGL_VERSION = %s\n", s);
420 s = eglQueryString(egl_dpy, EGL_VENDOR);
421 printf("EGL_VENDOR = %s\n", s);
423 s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
424 printf("EGL_EXTENSIONS = %s\n", s);
426 s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
427 printf("EGL_CLIENT_APIS = %s\n", s);
429 make_x_window(x_dpy, egl_dpy,
430 "OpenGL ES 1.x tri", 0, 0, winWidth, winHeight,
431 &win, &egl_ctx, &egl_surf);
433 XMapWindow(x_dpy, win);
434 if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
435 printf("Error: eglMakeCurrent() failed\n");
440 for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
441 switch (info_items[i].type) {
443 printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
447 glGetIntegerv(info_items[i].value, &rv);
448 printf("%s = %d\n", info_items[i].name, rv);
456 /* Set initial projection/viewing transformation.
457 * We can't be sure we'll get a ConfigureNotify event when the window
460 reshape(winWidth, winHeight);
462 event_loop(x_dpy, win, egl_dpy, egl_surf);
464 eglDestroyContext(egl_dpy, egl_ctx);
465 eglDestroySurface(egl_dpy, egl_surf);
466 eglTerminate(egl_dpy);
469 XDestroyWindow(x_dpy, win);
470 XCloseDisplay(x_dpy);