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.
35 #include <X11/Xutil.h>
36 #include <X11/keysym.h>
37 #include <GL/gl.h> /* using full OpenGL for now */
41 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
47 static const GLfloat verts
[3][2] = {
52 static const GLfloat colors
[3][3] = {
58 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
61 glRotatef(view_rotx
, 1, 0, 0);
62 glRotatef(view_roty
, 0, 1, 0);
63 glRotatef(view_rotz
, 0, 0, 1);
66 glVertexPointer(2, GL_FLOAT
, 0, verts
);
67 glColorPointer(3, GL_FLOAT
, 0, colors
);
68 glEnableClientState(GL_VERTEX_ARRAY
);
69 glEnableClientState(GL_COLOR_ARRAY
);
71 glDrawArrays(GL_TRIANGLES
, 0, 3);
73 glDisableClientState(GL_VERTEX_ARRAY
);
74 glDisableClientState(GL_COLOR_ARRAY
);
81 /* new window size or exposure */
83 reshape(int width
, int height
)
85 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
87 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
89 glMatrixMode(GL_PROJECTION
);
91 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
93 glMatrixMode(GL_MODELVIEW
);
95 glTranslatef(0.0, 0.0, -10.0);
102 glClearColor(0.4, 0.4, 0.4, 0.0);
107 * Create an RGB, double-buffered X window.
108 * Return the window and context handles.
111 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
113 int x
, int y
, int width
, int height
,
118 static const EGLint attribs
[] = {
123 EGL_RENDERABLE_TYPE
, EGL_OPENGL_BIT
,
128 XSetWindowAttributes attr
;
132 XVisualInfo
*visInfo
, visTemplate
;
139 scrnum
= DefaultScreen( x_dpy
);
140 root
= RootWindow( x_dpy
, scrnum
);
142 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
) ||
144 printf("Error: couldn't get an EGL visual config\n");
149 assert(num_configs
> 0);
151 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
152 printf("Error: eglGetConfigAttrib() failed\n");
156 /* The X window visual must match the EGL config */
157 visTemplate
.visualid
= vid
;
158 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
160 printf("Error: couldn't get X visual\n");
164 /* window attributes */
165 attr
.background_pixel
= 0;
166 attr
.border_pixel
= 0;
167 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
168 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
169 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
171 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
172 0, visInfo
->depth
, InputOutput
,
173 visInfo
->visual
, mask
, &attr
);
175 /* set hints and properties */
177 XSizeHints sizehints
;
180 sizehints
.width
= width
;
181 sizehints
.height
= height
;
182 sizehints
.flags
= USSize
| USPosition
;
183 XSetNormalHints(x_dpy
, win
, &sizehints
);
184 XSetStandardProperties(x_dpy
, win
, name
, name
,
185 None
, (char **)NULL
, 0, &sizehints
);
188 eglBindAPI(EGL_OPENGL_API
);
190 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
192 printf("Error: glXCreateContext failed\n");
196 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
199 printf("Error: eglCreateWindowSurface failed\n");
211 event_loop(Display
*dpy
, Window win
,
212 EGLDisplay egl_dpy
, EGLSurface egl_surf
)
218 XNextEvent(dpy
, &event
);
220 switch (event
.type
) {
224 case ConfigureNotify
:
225 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
231 code
= XLookupKeysym(&event
.xkey
, 0);
232 if (code
== XK_Left
) {
235 else if (code
== XK_Right
) {
238 else if (code
== XK_Up
) {
241 else if (code
== XK_Down
) {
245 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
247 if (buffer
[0] == 27) {
261 eglSwapBuffers(egl_dpy
, egl_surf
);
271 printf(" -display <displayname> set the display to run on\n");
272 printf(" -info display OpenGL renderer info\n");
277 main(int argc
, char *argv
[])
279 const int winWidth
= 300, winHeight
= 300;
285 char *dpyName
= NULL
;
286 GLboolean printInfo
= GL_FALSE
;
287 EGLint egl_major
, egl_minor
;
291 for (i
= 1; i
< argc
; i
++) {
292 if (strcmp(argv
[i
], "-display") == 0) {
296 else if (strcmp(argv
[i
], "-info") == 0) {
305 x_dpy
= XOpenDisplay(dpyName
);
307 printf("Error: couldn't open display %s\n",
308 dpyName
? dpyName
: getenv("DISPLAY"));
312 egl_dpy
= eglGetDisplay(x_dpy
);
314 printf("Error: eglGetDisplay() failed\n");
318 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
319 printf("Error: eglInitialize() failed\n");
323 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
324 printf("EGL_VERSION = %s\n", s
);
326 make_x_window(x_dpy
, egl_dpy
,
327 "xegl_tri", 0, 0, winWidth
, winHeight
,
328 &win
, &egl_ctx
, &egl_surf
);
330 XMapWindow(x_dpy
, win
);
331 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
332 printf("Error: eglMakeCurrent() failed\n");
337 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
338 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
339 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
344 /* Set initial projection/viewing transformation.
345 * We can't be sure we'll get a ConfigureNotify event when the window
348 reshape(winWidth
, winHeight
);
350 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
);
352 eglDestroyContext(egl_dpy
, egl_ctx
);
353 eglDestroySurface(egl_dpy
, egl_surf
);
354 eglTerminate(egl_dpy
);
357 XDestroyWindow(x_dpy
, win
);
358 XCloseDisplay(x_dpy
);