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 * Test drawing to two windows.
35 #include <X11/Xutil.h>
36 #include <X11/keysym.h>
38 #include <GLES/glext.h>
42 static int WinWidth
[2] = {150, 300}, WinHeight
[2] = {150, 300};
45 static GLfloat view_rotx
= 0.0, view_roty
= 0.0, view_rotz
= 0.0;
48 /* new window size or exposure */
50 reshape(int width
, int height
)
52 GLfloat ar
= (GLfloat
) width
/ (GLfloat
) height
;
54 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
56 glMatrixMode(GL_PROJECTION
);
58 #ifdef GL_VERSION_ES_CM_1_0
59 glFrustumf(-ar
, ar
, -1, 1, 5.0, 60.0);
61 glFrustum(-ar
, ar
, -1, 1, 5.0, 60.0);
64 glMatrixMode(GL_MODELVIEW
);
66 glTranslatef(0.0, 0.0, -10.0);
73 static const GLfloat verts
[3][2] = {
78 static const GLfloat colors
[3][4] = {
84 assert(win
== 0 || win
== 1);
86 reshape(WinWidth
[win
], WinHeight
[win
]);
88 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
91 glRotatef(view_rotx
, 1, 0, 0);
92 glRotatef(view_roty
, 0, 1, 0);
93 glRotatef(view_rotz
, 0, 0, 1);
97 glVertexPointer(2, GL_FLOAT
, 0, verts
);
98 glColorPointer(4, GL_FLOAT
, 0, colors
);
100 glEnableClientState(GL_VERTEX_ARRAY
);
101 glEnableClientState(GL_COLOR_ARRAY
);
103 glDrawArrays(GL_TRIANGLES
, 0, 3);
105 glDisableClientState(GL_VERTEX_ARRAY
);
106 glDisableClientState(GL_COLOR_ARRAY
);
116 glClearColor(0.4, 0.4, 0.4, 0.0);
121 * Create an RGB, double-buffered X window.
122 * Return the window and context handles.
125 make_x_window(Display
*x_dpy
, EGLDisplay egl_dpy
,
127 int x
, int y
, int width
, int height
,
132 static const EGLint attribs
[] = {
141 XSetWindowAttributes attr
;
145 XVisualInfo
*visInfo
, visTemplate
;
152 scrnum
= DefaultScreen( x_dpy
);
153 root
= RootWindow( x_dpy
, scrnum
);
155 if (!eglChooseConfig( egl_dpy
, attribs
, &config
, 1, &num_configs
)) {
156 printf("Error: couldn't get an EGL visual config\n");
161 assert(num_configs
> 0);
163 if (!eglGetConfigAttrib(egl_dpy
, config
, EGL_NATIVE_VISUAL_ID
, &vid
)) {
164 printf("Error: eglGetConfigAttrib() failed\n");
168 /* The X window visual must match the EGL config */
169 visTemplate
.visualid
= vid
;
170 visInfo
= XGetVisualInfo(x_dpy
, VisualIDMask
, &visTemplate
, &num_visuals
);
172 printf("Error: couldn't get X visual\n");
176 /* window attributes */
177 attr
.background_pixel
= 0;
178 attr
.border_pixel
= 0;
179 attr
.colormap
= XCreateColormap( x_dpy
, root
, visInfo
->visual
, AllocNone
);
180 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
181 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
183 win
= XCreateWindow( x_dpy
, root
, x
, y
, width
, height
,
184 0, visInfo
->depth
, InputOutput
,
185 visInfo
->visual
, mask
, &attr
);
187 /* set hints and properties */
189 XSizeHints sizehints
;
192 sizehints
.width
= width
;
193 sizehints
.height
= height
;
194 sizehints
.flags
= USSize
| USPosition
;
195 XSetNormalHints(x_dpy
, win
, &sizehints
);
196 XSetStandardProperties(x_dpy
, win
, name
, name
,
197 None
, (char **)NULL
, 0, &sizehints
);
201 eglBindAPI(EGL_OPENGL_API
);
203 eglBindAPI(EGL_OPENGL_ES_API
);
207 ctx
= eglCreateContext(egl_dpy
, config
, EGL_NO_CONTEXT
, NULL
);
209 printf("Error: eglCreateContext failed\n");
215 *surfRet
= eglCreateWindowSurface(egl_dpy
, config
, win
, NULL
);
218 printf("Error: eglCreateWindowSurface failed\n");
229 event_loop(Display
*dpy
, Window win1
, Window win2
,
230 EGLDisplay egl_dpy
, EGLSurface egl_surf1
, EGLSurface egl_surf2
,
238 XNextEvent(dpy
, &event
);
240 switch (event
.type
) {
244 case ConfigureNotify
:
245 if (event
.xconfigure
.window
== win1
)
249 WinWidth
[win
] = event
.xconfigure
.width
;
250 WinHeight
[win
] = event
.xconfigure
.height
;
256 code
= XLookupKeysym(&event
.xkey
, 0);
257 if (code
== XK_Left
) {
260 else if (code
== XK_Right
) {
263 else if (code
== XK_Up
) {
266 else if (code
== XK_Down
) {
270 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
272 if (buffer
[0] == 27) {
286 if (!eglMakeCurrent(egl_dpy
, egl_surf1
, egl_surf1
, egl_ctx
)) {
287 printf("Error: eglMakeCurrent(1) failed\n");
291 eglSwapBuffers(egl_dpy
, egl_surf1
);
294 if (!eglMakeCurrent(egl_dpy
, egl_surf2
, egl_surf2
, egl_ctx
)) {
295 printf("Error: eglMakeCurrent(2) failed\n");
299 eglSwapBuffers(egl_dpy
, egl_surf2
);
309 printf(" -display <displayname> set the display to run on\n");
310 printf(" -info display OpenGL renderer info\n");
315 main(int argc
, char *argv
[])
319 EGLSurface egl_surf1
, egl_surf2
;
322 char *dpyName
= NULL
;
323 GLboolean printInfo
= GL_FALSE
;
324 EGLint egl_major
, egl_minor
;
331 enum {GetString
, GetInteger
} type
;
333 {"GL_RENDERER", GL_RENDERER
, GetString
},
334 {"GL_VERSION", GL_VERSION
, GetString
},
335 {"GL_VENDOR", GL_VENDOR
, GetString
},
336 {"GL_EXTENSIONS", GL_EXTENSIONS
, GetString
},
337 {"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES
, GetInteger
},
338 {"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES
, GetInteger
},
341 for (i
= 1; i
< argc
; i
++) {
342 if (strcmp(argv
[i
], "-display") == 0) {
346 else if (strcmp(argv
[i
], "-info") == 0) {
355 x_dpy
= XOpenDisplay(dpyName
);
357 printf("Error: couldn't open display %s\n",
358 dpyName
? dpyName
: getenv("DISPLAY"));
362 egl_dpy
= eglGetDisplay(x_dpy
);
364 printf("Error: eglGetDisplay() failed\n");
368 if (!eglInitialize(egl_dpy
, &egl_major
, &egl_minor
)) {
369 printf("Error: eglInitialize() failed\n");
373 s
= eglQueryString(egl_dpy
, EGL_VERSION
);
374 printf("EGL_VERSION = %s\n", s
);
376 s
= eglQueryString(egl_dpy
, EGL_VENDOR
);
377 printf("EGL_VENDOR = %s\n", s
);
379 s
= eglQueryString(egl_dpy
, EGL_EXTENSIONS
);
380 printf("EGL_EXTENSIONS = %s\n", s
);
382 s
= eglQueryString(egl_dpy
, EGL_CLIENT_APIS
);
383 printf("EGL_CLIENT_APIS = %s\n", s
);
385 make_x_window(x_dpy
, egl_dpy
,
386 "xegl_two_win #1", 0, 0, WinWidth
[0], WinHeight
[0],
387 &win1
, &egl_ctx
, &egl_surf1
);
389 make_x_window(x_dpy
, egl_dpy
,
390 "xegl_two_win #2", WinWidth
[0] + 50, 0,
391 WinWidth
[1], WinHeight
[1],
392 &win2
, NULL
, &egl_surf2
);
394 XMapWindow(x_dpy
, win1
);
396 XMapWindow(x_dpy
, win2
);
398 if (!eglMakeCurrent(egl_dpy
, egl_surf1
, egl_surf1
, egl_ctx
)) {
399 printf("Error: eglMakeCurrent() failed\n");
404 for (i
= 0; i
< sizeof(info_items
)/sizeof(info_items
[0]); i
++) {
405 switch (info_items
[i
].type
) {
407 printf("%s = %s\n", info_items
[i
].name
, (char *)glGetString(info_items
[i
].value
));
411 glGetIntegerv(info_items
[i
].value
, &rv
);
412 printf("%s = %d\n", info_items
[i
].name
, rv
);
421 event_loop(x_dpy
, win1
, win2
, egl_dpy
, egl_surf1
, egl_surf2
, egl_ctx
);
423 eglDestroyContext(egl_dpy
, egl_ctx
);
424 eglDestroySurface(egl_dpy
, egl_surf1
);
425 eglDestroySurface(egl_dpy
, egl_surf2
);
426 eglTerminate(egl_dpy
);
428 XDestroyWindow(x_dpy
, win1
);
429 XDestroyWindow(x_dpy
, win2
);
430 XCloseDisplay(x_dpy
);