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];
156 procQueryMatrixx
= (PFNGLQUERYMATRIXXOESPROC
) eglGetProcAddress("glQueryMatrixxOES");
157 assert(procQueryMatrixx
);
158 /* Actually try out this one */
159 rv
= (*procQueryMatrixx
)(mantissa
, exponent
);
160 for (i
= 0; i
< 16; i
++) {
162 printf("matrix[%d] invalid\n", i
);
165 printf("matrix[%d] = %f * 2^(%d)\n", i
, mantissa
[i
]/65536.0, exponent
[i
]);
168 assert(!eglGetProcAddress("glFoo"));
175 glClearColor(0.4, 0.4, 0.4, 0.0);
183 * Create an RGB, double-buffered X window.
184 * Return the window and context handles.
187 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
189 int x
, int y
, int width
, int height
,
194 static const EGLint attribs
[] = {
203 XSetWindowAttributes attr
;
207 XVisualInfo
*visInfo
, visTemplate
;
214 scrnum
= DefaultScreen( x_dpy
);
215 root
= RootWindow( x_dpy
, scrnum
);
217 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
218 printf("Error: couldn't get an EGL visual config\n");
223 assert(num_configs
> 0);
225 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
226 printf("Error: eglGetConfigAttrib() failed\n");
230 /* The X window visual must match the EGL config */
231 visTemplate
.visualid
= vid
;
232 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
234 printf("Error: couldn't get X visual\n");
238 /* window attributes */
239 attr
.background_pixel
= 0;
240 attr
.border_pixel
= 0;
241 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
242 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
243 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
245 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
246 0, visInfo
->depth
, InputOutput
,
247 visInfo
->visual
, mask
, &attr
);
249 /* set hints and properties */
251 XSizeHints sizehints
;
254 sizehints
.width
= width
;
255 sizehints
.height
= height
;
256 sizehints
.flags
= USSize
| USPosition
;
257 XSetNormalHints(x_dpy
, win
, &sizehints
);
258 XSetStandardProperties(x_dpy
, win
, name
, name
,
259 None
, (char **)NULL
, 0, &sizehints
);
263 eglBindAPI(EGL_OPENGL_API
);
265 eglBindAPI(EGL_OPENGL_ES_API
);
268 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
270 printf("Error: eglCreateContext failed\n");
274 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
277 printf("Error: eglCreateWindowSurface failed\n");
289 event_loop(Display
*dpy
, Window win
,
290 EGLDisplay egl_dpy
, EGLSurface egl_surf
)
296 XNextEvent(dpy
, &event
);
298 switch (event
.type
) {
302 case ConfigureNotify
:
303 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
309 code
= XLookupKeysym(&event
.xkey
, 0);
310 if (code
== XK_Left
) {
313 else if (code
== XK_Right
) {
316 else if (code
== XK_Up
) {
319 else if (code
== XK_Down
) {
323 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
325 if (buffer
[0] == 27) {
339 eglSwapBuffers(egl_dpy
, egl_surf
);
349 printf(" -display <displayname> set the display to run on\n");
350 printf(" -info display OpenGL renderer info\n");
355 main(int argc
, char *argv
[])
357 const int winWidth
= 300, winHeight
= 300;
363 char *dpyName
= NULL
;
364 GLboolean printInfo
= GL_FALSE
;
365 EGLint egl_major
, egl_minor
;
372 enum {GetString
, GetInteger
} type
;
374 {"GL_RENDERER", GL_RENDERER
, GetString
},
375 {"GL_VERSION", GL_VERSION
, GetString
},
376 {"GL_VENDOR", GL_VENDOR
, GetString
},
377 {"GL_EXTENSIONS", GL_EXTENSIONS
, GetString
},
378 {"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES
, GetInteger
},
379 {"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES
, GetInteger
},
382 for (i
= 1; i
< argc
; i
++) {
383 if (strcmp(argv
[i
], "-display") == 0) {
387 else if (strcmp(argv
[i
], "-info") == 0) {
396 x_dpy
= XOpenDisplay(dpyName
);
398 printf("Error: couldn't open display %s\n",
399 dpyName
? dpyName
: getenv("DISPLAY"));
403 egl_dpy
= eglGetDisplay(x_dpy
);
405 printf("Error: eglGetDisplay() failed\n");
409 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
410 printf("Error: eglInitialize() failed\n");
414 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
415 printf("EGL_VERSION = %s\n", s
);
417 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
418 printf("EGL_VENDOR = %s\n", s
);
420 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
421 printf("EGL_EXTENSIONS = %s\n", s
);
423 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
424 printf("EGL_CLIENT_APIS = %s\n", s
);
426 make_x_window(x_dpy
, egl_dpy
,
427 "OpenGL ES 1.x tri", 0, 0, winWidth
, winHeight
,
428 &win
, &egl_ctx
, &egl_surf
);
430 XMapWindow(x_dpy
, win
);
431 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
432 printf("Error: eglMakeCurrent() failed\n");
437 for (i
= 0; i
< sizeof(info_items
)/sizeof(info_items
[0]); i
++) {
438 switch (info_items
[i
].type
) {
440 printf("%s = %s\n", info_items
[i
].name
, (char *)glGetString(info_items
[i
].value
));
444 glGetIntegerv(info_items
[i
].value
, &rv
);
445 printf("%s = %d\n", info_items
[i
].name
, rv
);
453 /* Set initial projection/viewing transformation.
454 * We can't be sure we'll get a ConfigureNotify event when the window
457 reshape(winWidth
, winHeight
);
459 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
);
461 eglDestroyContext(egl_dpy
, egl_ctx
);
462 eglDestroySurface(egl_dpy
, egl_surf
);
463 eglTerminate(egl_dpy
);
466 XDestroyWindow(x_dpy
, win
);
467 XCloseDisplay(x_dpy
);