1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 **************************************************************************/
9 * Draw a triangle with X/EGL and OpenGL ES 2.x
22 #include <X11/Xutil.h>
23 #include <X11/keysym.h>
25 #include <GL/gl.h> /* use full OpenGL */
27 #include <GLES2/gl2.h> /* use OpenGL ES 2.x */
32 #define FLOAT_TO_FIXED(X) ((X) * 65535.0)
36 static GLfloat view_rotx
= 0.0, view_roty
= 0.0;
38 static GLint u_matrix
= -1;
39 static GLint attr_pos
= 0, attr_color
= 1;
43 make_z_rot_matrix(GLfloat angle
, GLfloat
*m
)
45 float c
= cos(angle
* M_PI
/ 180.0);
46 float s
= sin(angle
* M_PI
/ 180.0);
48 for (i
= 0; i
< 16; i
++)
50 m
[0] = m
[5] = m
[10] = m
[15] = 1.0;
59 make_scale_matrix(GLfloat xs
, GLfloat ys
, GLfloat zs
, GLfloat
*m
)
62 for (i
= 0; i
< 16; i
++)
72 mul_matrix(GLfloat
*prod
, const GLfloat
*a
, const GLfloat
*b
)
74 #define A(row,col) a[(col<<2)+row]
75 #define B(row,col) b[(col<<2)+row]
76 #define P(row,col) p[(col<<2)+row]
79 for (i
= 0; i
< 4; i
++) {
80 const GLfloat ai0
=A(i
,0), ai1
=A(i
,1), ai2
=A(i
,2), ai3
=A(i
,3);
81 P(i
,0) = ai0
* B(0,0) + ai1
* B(1,0) + ai2
* B(2,0) + ai3
* B(3,0);
82 P(i
,1) = ai0
* B(0,1) + ai1
* B(1,1) + ai2
* B(2,1) + ai3
* B(3,1);
83 P(i
,2) = ai0
* B(0,2) + ai1
* B(1,2) + ai2
* B(2,2) + ai3
* B(3,2);
84 P(i
,3) = ai0
* B(0,3) + ai1
* B(1,3) + ai2
* B(2,3) + ai3
* B(3,3);
86 memcpy(prod
, p
, sizeof(p
));
96 static const GLfloat verts
[3][2] = {
101 static const GLfloat colors
[3][3] = {
106 GLfloat mat
[16], rot
[16], scale
[16];
108 /* Set modelview/projection matrix */
109 make_z_rot_matrix(view_rotx
, rot
);
110 make_scale_matrix(0.5, 0.5, 0.5, scale
);
111 mul_matrix(mat
, rot
, scale
);
112 glUniformMatrix4fv(u_matrix
, 1, GL_FALSE
, mat
);
114 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
117 glVertexAttribPointer(attr_pos
, 2, GL_FLOAT
, GL_FALSE
, 0, verts
);
118 glVertexAttribPointer(attr_color
, 3, GL_FLOAT
, GL_FALSE
, 0, colors
);
119 glEnableVertexAttribArray(attr_pos
);
120 glEnableVertexAttribArray(attr_color
);
122 glDrawArrays(GL_TRIANGLES
, 0, 3);
124 glDisableVertexAttribArray(attr_pos
);
125 glDisableVertexAttribArray(attr_color
);
130 /* new window size or exposure */
132 reshape(int width
, int height
)
134 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
141 static const char *fragShaderText
=
142 "varying vec4 v_color;\n"
144 " gl_FragColor = v_color;\n"
146 static const char *vertShaderText
=
147 "uniform mat4 modelviewProjection;\n"
148 "attribute vec4 pos;\n"
149 "attribute vec4 color;\n"
150 "varying vec4 v_color;\n"
152 " gl_Position = modelviewProjection * pos;\n"
153 " v_color = color;\n"
156 GLuint fragShader
, vertShader
, program
;
159 fragShader
= glCreateShader(GL_FRAGMENT_SHADER
);
160 glShaderSource(fragShader
, 1, (const char **) &fragShaderText
, NULL
);
161 glCompileShader(fragShader
);
162 glGetShaderiv(fragShader
, GL_COMPILE_STATUS
, &stat
);
164 printf("Error: fragment shader did not compile!\n");
168 vertShader
= glCreateShader(GL_VERTEX_SHADER
);
169 glShaderSource(vertShader
, 1, (const char **) &vertShaderText
, NULL
);
170 glCompileShader(vertShader
);
171 glGetShaderiv(vertShader
, GL_COMPILE_STATUS
, &stat
);
173 printf("Error: vertex shader did not compile!\n");
177 program
= glCreateProgram();
178 glAttachShader(program
, fragShader
);
179 glAttachShader(program
, vertShader
);
180 glLinkProgram(program
);
182 glGetProgramiv(program
, GL_LINK_STATUS
, &stat
);
186 glGetProgramInfoLog(program
, 1000, &len
, log
);
187 printf("Error: linking:\n%s\n", log
);
191 glUseProgram(program
);
194 /* test setting attrib locations */
195 glBindAttribLocation(program
, attr_pos
, "pos");
196 glBindAttribLocation(program
, attr_color
, "color");
197 glLinkProgram(program
); /* needed to put attribs into effect */
200 /* test automatic attrib locations */
201 attr_pos
= glGetAttribLocation(program
, "pos");
202 attr_color
= glGetAttribLocation(program
, "color");
205 u_matrix
= glGetUniformLocation(program
, "modelviewProjection");
206 printf("Uniform modelviewProjection at %d\n", u_matrix
);
207 printf("Attrib pos at %d\n", attr_pos
);
208 printf("Attrib color at %d\n", attr_color
);
215 typedef void (*proc
)();
217 #if 1 /* test code */
218 proc p
= eglGetProcAddress("glMapBufferOES");
222 glClearColor(0.4, 0.4, 0.4, 0.0);
229 * Create an RGB, double-buffered X window.
230 * Return the window and context handles.
233 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
235 int x
, int y
, int width
, int height
,
240 static const EGLint attribs
[] = {
245 EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES2_BIT
,
248 static const EGLint ctx_attribs
[] = {
249 EGL_CONTEXT_CLIENT_VERSION
, 2,
253 XSetWindowAttributes attr
;
257 XVisualInfo
*visInfo
, visTemplate
;
264 scrnum
= DefaultScreen( x_dpy
);
265 root
= RootWindow( x_dpy
, scrnum
);
267 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
268 printf("Error: couldn't get an EGL visual config\n");
273 assert(num_configs
> 0);
275 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
276 printf("Error: eglGetConfigAttrib() failed\n");
280 /* The X window visual must match the EGL config */
281 visTemplate
.visualid
= vid
;
282 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
284 printf("Error: couldn't get X visual\n");
288 /* window attributes */
289 attr
.background_pixel
= 0;
290 attr
.border_pixel
= 0;
291 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
292 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
293 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
295 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
296 0, visInfo
->depth
, InputOutput
,
297 visInfo
->visual
, mask
, &attr
);
299 /* set hints and properties */
301 XSizeHints sizehints
;
304 sizehints
.width
= width
;
305 sizehints
.height
= height
;
306 sizehints
.flags
= USSize
| USPosition
;
307 XSetNormalHints(x_dpy
, win
, &sizehints
);
308 XSetStandardProperties(x_dpy
, win
, name
, name
,
309 None
, (char **)NULL
, 0, &sizehints
);
312 #if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
313 eglBindAPI(EGL_OPENGL_API
);
315 eglBindAPI(EGL_OPENGL_ES_API
);
318 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, ctx_attribs
);
320 printf("Error: eglCreateContext failed\n");
324 /* test eglQueryContext() */
327 eglQueryContext(egl_dpy
, ctx
, EGL_CONTEXT_CLIENT_VERSION
, &val
);
331 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
333 printf("Error: eglCreateWindowSurface failed\n");
340 eglQuerySurface(egl_dpy
, *surfRet
, EGL_WIDTH
, &val
);
341 assert(val
== width
);
342 eglQuerySurface(egl_dpy
, *surfRet
, EGL_HEIGHT
, &val
);
343 assert(val
== height
);
344 assert(eglGetConfigAttrib(egl_dpy
, config
, EGL_SURFACE_TYPE
, &val
));
345 assert(val
& EGL_WINDOW_BIT
);
356 event_loop(Display
*dpy
, Window win
,
357 EGLDisplay egl_dpy
, EGLSurface egl_surf
)
363 XNextEvent(dpy
, &event
);
365 switch (event
.type
) {
369 case ConfigureNotify
:
370 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
376 code
= XLookupKeysym(&event
.xkey
, 0);
377 if (code
== XK_Left
) {
380 else if (code
== XK_Right
) {
383 else if (code
== XK_Up
) {
386 else if (code
== XK_Down
) {
390 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
392 if (buffer
[0] == 27) {
406 eglSwapBuffers(egl_dpy
, egl_surf
);
416 printf(" -display <displayname> set the display to run on\n");
417 printf(" -info display OpenGL renderer info\n");
422 main(int argc
, char *argv
[])
424 const int winWidth
= 300, winHeight
= 300;
430 char *dpyName
= NULL
;
431 GLboolean printInfo
= GL_FALSE
;
432 EGLint egl_major
, egl_minor
;
436 for (i
= 1; i
< argc
; i
++) {
437 if (strcmp(argv
[i
], "-display") == 0) {
441 else if (strcmp(argv
[i
], "-info") == 0) {
450 x_dpy
= XOpenDisplay(dpyName
);
452 printf("Error: couldn't open display %s\n",
453 dpyName
? dpyName
: getenv("DISPLAY"));
457 egl_dpy
= eglGetDisplay(x_dpy
);
459 printf("Error: eglGetDisplay() failed\n");
463 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
464 printf("Error: eglInitialize() failed\n");
468 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
469 printf("EGL_VERSION = %s\n", s
);
471 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
472 printf("EGL_VENDOR = %s\n", s
);
474 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
475 printf("EGL_EXTENSIONS = %s\n", s
);
477 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
478 printf("EGL_CLIENT_APIS = %s\n", s
);
480 make_x_window(x_dpy
, egl_dpy
,
481 "OpenGL ES 2.x tri", 0, 0, winWidth
, winHeight
,
482 &win
, &egl_ctx
, &egl_surf
);
484 XMapWindow(x_dpy
, win
);
485 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
486 printf("Error: eglMakeCurrent() failed\n");
491 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
492 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
493 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
494 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS
));
499 /* Set initial projection/viewing transformation.
500 * We can't be sure we'll get a ConfigureNotify event when the window
503 reshape(winWidth
, winHeight
);
505 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
);
507 eglDestroyContext(egl_dpy
, egl_ctx
);
508 eglDestroySurface(egl_dpy
, egl_surf
);
509 eglTerminate(egl_dpy
);
512 XDestroyWindow(x_dpy
, win
);
513 XCloseDisplay(x_dpy
);