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
[] = {
127 XSetWindowAttributes attr
;
131 XVisualInfo
*visInfo
, visTemplate
;
138 scrnum
= DefaultScreen( x_dpy
);
139 root
= RootWindow( x_dpy
, scrnum
);
141 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
142 printf("Error: couldn't get an EGL visual config\n");
147 assert(num_configs
> 0);
149 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
150 printf("Error: eglGetConfigAttrib() failed\n");
154 /* The X window visual must match the EGL config */
155 visTemplate
.visualid
= vid
;
156 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
158 printf("Error: couldn't get X visual\n");
162 /* window attributes */
163 attr
.background_pixel
= 0;
164 attr
.border_pixel
= 0;
165 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
166 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
167 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
169 win
= XCreateWindow( x_dpy
, root
, 0, 0, width
, height
,
170 0, visInfo
->depth
, InputOutput
,
171 visInfo
->visual
, mask
, &attr
);
173 /* set hints and properties */
175 XSizeHints sizehints
;
178 sizehints
.width
= width
;
179 sizehints
.height
= height
;
180 sizehints
.flags
= USSize
| USPosition
;
181 XSetNormalHints(x_dpy
, win
, &sizehints
);
182 XSetStandardProperties(x_dpy
, win
, name
, name
,
183 None
, (char **)NULL
, 0, &sizehints
);
186 eglBindAPI(EGL_OPENGL_API
);
188 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
190 printf("Error: glXCreateContext failed\n");
194 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
197 printf("Error: eglCreateWindowSurface failed\n");
209 event_loop(Display
*dpy
, Window win
,
210 EGLDisplay egl_dpy
, EGLSurface egl_surf
)
216 XNextEvent(dpy
, &event
);
218 switch (event
.type
) {
222 case ConfigureNotify
:
223 reshape(event
.xconfigure
.width
, event
.xconfigure
.height
);
229 code
= XLookupKeysym(&event
.xkey
, 0);
230 if (code
== XK_Left
) {
233 else if (code
== XK_Right
) {
236 else if (code
== XK_Up
) {
239 else if (code
== XK_Down
) {
243 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
245 if (buffer
[0] == 27) {
259 eglSwapBuffers(egl_dpy
, egl_surf
);
269 printf(" -display <displayname> set the display to run on\n");
270 printf(" -info display OpenGL renderer info\n");
275 main(int argc
, char *argv
[])
277 const int winWidth
= 300, winHeight
= 300;
283 char *dpyName
= NULL
;
284 GLboolean printInfo
= GL_FALSE
;
285 EGLint egl_major
, egl_minor
;
289 for (i
= 1; i
< argc
; i
++) {
290 if (strcmp(argv
[i
], "-display") == 0) {
294 else if (strcmp(argv
[i
], "-info") == 0) {
303 x_dpy
= XOpenDisplay(dpyName
);
305 printf("Error: couldn't open display %s\n",
306 dpyName
? dpyName
: getenv("DISPLAY"));
310 egl_dpy
= eglGetDisplay(x_dpy
);
312 printf("Error: eglGetDisplay() failed\n");
316 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
317 printf("Error: eglInitialize() failed\n");
321 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
322 printf("EGL_VERSION = %s\n", s
);
324 make_x_window(x_dpy
, egl_dpy
,
325 "xegl_tri", 0, 0, winWidth
, winHeight
,
326 &win
, &egl_ctx
, &egl_surf
);
328 XMapWindow(x_dpy
, win
);
329 if (!eglMakeCurrent(egl_dpy
, egl_surf
, egl_surf
, egl_ctx
)) {
330 printf("Error: eglMakeCurrent() failed\n");
335 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
336 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION
));
337 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR
));
342 /* Set initial projection/viewing transformation.
343 * We can't be sure we'll get a ConfigureNotify event when the window
346 reshape(winWidth
, winHeight
);
348 event_loop(x_dpy
, win
, egl_dpy
, egl_surf
);
350 eglDestroyContext(egl_dpy
, egl_ctx
);
351 eglDestroySurface(egl_dpy
, egl_surf
);
352 eglTerminate(egl_dpy
);
355 XDestroyWindow(x_dpy
, win
);
356 XCloseDisplay(x_dpy
);