Merge remote branch 'origin/7.8'
[mesa.git] / progs / egl / opengles1 / two_win.c
1 /*
2 * Copyright (C) 2008 Brian Paul All Rights Reserved.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
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.
20 */
21
22 /*
23 * Test drawing to two windows.
24 * Brian Paul
25 * August 2008
26 */
27
28
29 #include <assert.h>
30 #include <math.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <X11/Xlib.h>
35 #include <X11/Xutil.h>
36 #include <X11/keysym.h>
37 #include <GLES/gl.h>
38 #include <GLES/glext.h>
39 #include <EGL/egl.h>
40
41
42 static int WinWidth[2] = {150, 300}, WinHeight[2] = {150, 300};
43
44
45 static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
46
47
48 /* new window size or exposure */
49 static void
50 reshape(int width, int height)
51 {
52 GLfloat ar = (GLfloat) width / (GLfloat) height;
53
54 glViewport(0, 0, (GLint) width, (GLint) height);
55
56 glMatrixMode(GL_PROJECTION);
57 glLoadIdentity();
58 #ifdef GL_VERSION_ES_CM_1_0
59 glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
60 #else
61 glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
62 #endif
63
64 glMatrixMode(GL_MODELVIEW);
65 glLoadIdentity();
66 glTranslatef(0.0, 0.0, -10.0);
67 }
68
69
70 static void
71 draw(int win)
72 {
73 static const GLfloat verts[3][2] = {
74 { -1, -1 },
75 { 1, -1 },
76 { 0, 1 }
77 };
78 static const GLfloat colors[3][4] = {
79 { 1, 0, 0, 1 },
80 { 0, 1, 0, 1 },
81 { 0, 0, 1, 1 }
82 };
83
84 assert(win == 0 || win == 1);
85
86 reshape(WinWidth[win], WinHeight[win]);
87
88 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
89
90 glPushMatrix();
91 glRotatef(view_rotx, 1, 0, 0);
92 glRotatef(view_roty, 0, 1, 0);
93 glRotatef(view_rotz, 0, 0, 1);
94
95 /* draw triangle */
96 {
97 glVertexPointer(2, GL_FLOAT, 0, verts);
98 glColorPointer(4, GL_FLOAT, 0, colors);
99
100 glEnableClientState(GL_VERTEX_ARRAY);
101 glEnableClientState(GL_COLOR_ARRAY);
102
103 glDrawArrays(GL_TRIANGLES, 0, 3);
104
105 glDisableClientState(GL_VERTEX_ARRAY);
106 glDisableClientState(GL_COLOR_ARRAY);
107 }
108
109 glPopMatrix();
110 }
111
112
113 static void
114 init(void)
115 {
116 glClearColor(0.4, 0.4, 0.4, 0.0);
117 }
118
119
120 /*
121 * Create an RGB, double-buffered X window.
122 * Return the window and context handles.
123 */
124 static void
125 make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
126 const char *name,
127 int x, int y, int width, int height,
128 Window *winRet,
129 EGLContext *ctxRet,
130 EGLSurface *surfRet)
131 {
132 static const EGLint attribs[] = {
133 EGL_RED_SIZE, 1,
134 EGL_GREEN_SIZE, 1,
135 EGL_BLUE_SIZE, 1,
136 EGL_DEPTH_SIZE, 1,
137 EGL_NONE
138 };
139
140 int scrnum;
141 XSetWindowAttributes attr;
142 unsigned long mask;
143 Window root;
144 Window win;
145 XVisualInfo *visInfo, visTemplate;
146 int num_visuals;
147 EGLContext ctx;
148 EGLConfig config;
149 EGLint num_configs;
150 EGLint vid;
151
152 scrnum = DefaultScreen( x_dpy );
153 root = RootWindow( x_dpy, scrnum );
154
155 if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
156 printf("Error: couldn't get an EGL visual config\n");
157 exit(1);
158 }
159
160 assert(config);
161 assert(num_configs > 0);
162
163 if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
164 printf("Error: eglGetConfigAttrib() failed\n");
165 exit(1);
166 }
167
168 /* The X window visual must match the EGL config */
169 visTemplate.visualid = vid;
170 visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
171 if (!visInfo) {
172 printf("Error: couldn't get X visual\n");
173 exit(1);
174 }
175
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;
182
183 win = XCreateWindow( x_dpy, root, x, y, width, height,
184 0, visInfo->depth, InputOutput,
185 visInfo->visual, mask, &attr );
186
187 /* set hints and properties */
188 {
189 XSizeHints sizehints;
190 sizehints.x = x;
191 sizehints.y = y;
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);
198 }
199
200 #if USE_FULL_GL
201 eglBindAPI(EGL_OPENGL_API);
202 #else
203 eglBindAPI(EGL_OPENGL_ES_API);
204 #endif
205
206 if (ctxRet) {
207 ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
208 if (!ctx) {
209 printf("Error: eglCreateContext failed\n");
210 exit(1);
211 }
212 *ctxRet = ctx;
213 }
214
215 *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
216
217 if (!*surfRet) {
218 printf("Error: eglCreateWindowSurface failed\n");
219 exit(1);
220 }
221
222 XFree(visInfo);
223
224 *winRet = win;
225 }
226
227
228 static void
229 event_loop(Display *dpy, Window win1, Window win2,
230 EGLDisplay egl_dpy, EGLSurface egl_surf1, EGLSurface egl_surf2,
231 EGLContext egl_ctx)
232 {
233 while (1) {
234 int redraw = 0;
235 int win;
236 XEvent event;
237
238 XNextEvent(dpy, &event);
239
240 switch (event.type) {
241 case Expose:
242 redraw = 1;
243 break;
244 case ConfigureNotify:
245 if (event.xconfigure.window == win1)
246 win = 0;
247 else
248 win = 1;
249 WinWidth[win] = event.xconfigure.width;
250 WinHeight[win] = event.xconfigure.height;
251 break;
252 case KeyPress:
253 {
254 char buffer[10];
255 int r, code;
256 code = XLookupKeysym(&event.xkey, 0);
257 if (code == XK_Left) {
258 view_roty += 5.0;
259 }
260 else if (code == XK_Right) {
261 view_roty -= 5.0;
262 }
263 else if (code == XK_Up) {
264 view_rotx += 5.0;
265 }
266 else if (code == XK_Down) {
267 view_rotx -= 5.0;
268 }
269 else {
270 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
271 NULL, NULL);
272 if (buffer[0] == 27) {
273 /* escape */
274 return;
275 }
276 }
277 }
278 redraw = 1;
279 break;
280 default:
281 ; /*no-op*/
282 }
283
284 if (redraw) {
285 /* win 1 */
286 if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
287 printf("Error: eglMakeCurrent(1) failed\n");
288 return;
289 }
290 draw(0);
291 eglSwapBuffers(egl_dpy, egl_surf1);
292
293 /* win 2 */
294 if (!eglMakeCurrent(egl_dpy, egl_surf2, egl_surf2, egl_ctx)) {
295 printf("Error: eglMakeCurrent(2) failed\n");
296 return;
297 }
298 draw(1);
299 eglSwapBuffers(egl_dpy, egl_surf2);
300 }
301 }
302 }
303
304
305 static void
306 usage(void)
307 {
308 printf("Usage:\n");
309 printf(" -display <displayname> set the display to run on\n");
310 printf(" -info display OpenGL renderer info\n");
311 }
312
313
314 int
315 main(int argc, char *argv[])
316 {
317 Display *x_dpy;
318 Window win1, win2;
319 EGLSurface egl_surf1, egl_surf2;
320 EGLContext egl_ctx;
321 EGLDisplay egl_dpy;
322 char *dpyName = NULL;
323 GLboolean printInfo = GL_FALSE;
324 EGLint egl_major, egl_minor;
325 int i;
326 const char *s;
327
328 static struct {
329 char *name;
330 GLenum value;
331 enum {GetString, GetInteger} type;
332 } info_items[] = {
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},
339 };
340
341 for (i = 1; i < argc; i++) {
342 if (strcmp(argv[i], "-display") == 0) {
343 dpyName = argv[i+1];
344 i++;
345 }
346 else if (strcmp(argv[i], "-info") == 0) {
347 printInfo = GL_TRUE;
348 }
349 else {
350 usage();
351 return -1;
352 }
353 }
354
355 x_dpy = XOpenDisplay(dpyName);
356 if (!x_dpy) {
357 printf("Error: couldn't open display %s\n",
358 dpyName ? dpyName : getenv("DISPLAY"));
359 return -1;
360 }
361
362 egl_dpy = eglGetDisplay(x_dpy);
363 if (!egl_dpy) {
364 printf("Error: eglGetDisplay() failed\n");
365 return -1;
366 }
367
368 if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
369 printf("Error: eglInitialize() failed\n");
370 return -1;
371 }
372
373 s = eglQueryString(egl_dpy, EGL_VERSION);
374 printf("EGL_VERSION = %s\n", s);
375
376 s = eglQueryString(egl_dpy, EGL_VENDOR);
377 printf("EGL_VENDOR = %s\n", s);
378
379 s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
380 printf("EGL_EXTENSIONS = %s\n", s);
381
382 s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
383 printf("EGL_CLIENT_APIS = %s\n", s);
384
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);
388
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);
393
394 XMapWindow(x_dpy, win1);
395
396 XMapWindow(x_dpy, win2);
397
398 if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
399 printf("Error: eglMakeCurrent() failed\n");
400 return -1;
401 }
402
403 if (printInfo) {
404 for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
405 switch (info_items[i].type) {
406 case GetString:
407 printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
408 break;
409 case GetInteger: {
410 GLint rv = -1;
411 glGetIntegerv(info_items[i].value, &rv);
412 printf("%s = %d\n", info_items[i].name, rv);
413 break;
414 }
415 }
416 }
417 };
418
419 init();
420
421 event_loop(x_dpy, win1, win2, egl_dpy, egl_surf1, egl_surf2, egl_ctx);
422
423 eglDestroyContext(egl_dpy, egl_ctx);
424 eglDestroySurface(egl_dpy, egl_surf1);
425 eglDestroySurface(egl_dpy, egl_surf2);
426 eglTerminate(egl_dpy);
427
428 XDestroyWindow(x_dpy, win1);
429 XDestroyWindow(x_dpy, win2);
430 XCloseDisplay(x_dpy);
431
432 return 0;
433 }