gl: updated glxext.h to version 27
[mesa.git] / progs / es1 / xegl / bindtex.c
1 /*
2 * Simple demo for eglBindTexImage. Based on xegl_tri.c by
3 *
4 * Copyright (C) 2008 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 /*
25 * The spec says that eglBindTexImage supports only OpenGL ES context, but this
26 * demo uses OpenGL context. Keep in mind that this is non-standard.
27 */
28
29 #include <math.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/keysym.h>
36 #include <GLES/gl.h>
37 #include <EGL/egl.h>
38
39 static EGLDisplay dpy;
40 static EGLContext ctx_win, ctx_pbuf;
41 static EGLSurface surf_win, surf_pbuf;
42 static GLuint tex_pbuf;
43
44 static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
45 static GLboolean blend = GL_TRUE;
46 static GLuint color_flow;
47
48 static void
49 make_pbuffer(int width, int height)
50 {
51 static const EGLint config_attribs[] = {
52 EGL_RED_SIZE, 8,
53 EGL_GREEN_SIZE, 8,
54 EGL_BLUE_SIZE, 8,
55 EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
56 EGL_NONE
57 };
58 EGLint pbuf_attribs[] = {
59 EGL_WIDTH, width,
60 EGL_HEIGHT, height,
61 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
62 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
63 EGL_NONE
64 };
65 EGLConfig config;
66 EGLint num_configs;
67
68 if (!eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs) ||
69 !num_configs) {
70 printf("Error: couldn't get an EGL visual config for pbuffer\n");
71 exit(1);
72 }
73
74 ctx_pbuf = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
75 surf_pbuf = eglCreatePbufferSurface(dpy, config, pbuf_attribs);
76 if (surf_pbuf == EGL_NO_SURFACE) {
77 printf("failed to allocate pbuffer\n");
78 exit(1);
79 }
80 }
81
82 static void
83 use_pbuffer(void)
84 {
85 static int initialized;
86
87 eglMakeCurrent(dpy, surf_pbuf, surf_pbuf, ctx_pbuf);
88 if (!initialized) {
89 EGLint width, height;
90 GLfloat ar;
91
92 initialized = 1;
93
94 eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &width);
95 eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &height);
96 ar = (GLfloat) width / (GLfloat) height;
97
98 glViewport(0, 0, (GLint) width, (GLint) height);
99
100 glMatrixMode(GL_PROJECTION);
101 glLoadIdentity();
102 glFrustumf(-ar, ar, -1, 1, 1.0, 10.0);
103
104 glMatrixMode(GL_MODELVIEW);
105 glLoadIdentity();
106
107 /* y-inverted */
108 glScalef(1.0, -1.0, 1.0);
109
110 glTranslatef(0.0, 0.0, -5.0);
111
112 glClearColor(0.2, 0.2, 0.2, 0.0);
113
114 glGenTextures(1, &tex_pbuf);
115 }
116 }
117
118 static void
119 make_window(Display *x_dpy, const char *name,
120 int x, int y, int width, int height,
121 Window *winRet)
122 {
123 static const EGLint attribs[] = {
124 EGL_RED_SIZE, 8,
125 EGL_GREEN_SIZE, 8,
126 EGL_BLUE_SIZE, 8,
127 EGL_ALPHA_SIZE, 8,
128 EGL_DEPTH_SIZE, 8,
129 EGL_NONE
130 };
131
132 int scrnum;
133 XSetWindowAttributes attr;
134 unsigned long mask;
135 Window root;
136 Window win;
137 XVisualInfo *visInfo, visTemplate;
138 int num_visuals;
139 EGLConfig config;
140 EGLint num_configs, vid;
141
142 scrnum = DefaultScreen( x_dpy );
143 root = RootWindow( x_dpy, scrnum );
144
145 if (!eglChooseConfig(dpy, attribs, &config, 1, &num_configs) ||
146 !num_configs) {
147 printf("Error: couldn't get an EGL visual config\n");
148 exit(1);
149 }
150
151 if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
152 printf("Error: eglGetConfigAttrib() failed\n");
153 exit(1);
154 }
155
156 /* The X window visual must match the EGL config */
157 visTemplate.visualid = vid;
158 visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
159 if (!visInfo) {
160 printf("Error: couldn't get X visual\n");
161 exit(1);
162 }
163
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 attr.override_redirect = 0;
170 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
171
172 win = XCreateWindow( x_dpy, root, 0, 0, width, height,
173 0, visInfo->depth, InputOutput,
174 visInfo->visual, mask, &attr );
175
176 /* set hints and properties */
177 {
178 XSizeHints sizehints;
179 sizehints.x = x;
180 sizehints.y = y;
181 sizehints.width = width;
182 sizehints.height = height;
183 sizehints.flags = USSize | USPosition;
184 XSetNormalHints(x_dpy, win, &sizehints);
185 XSetStandardProperties(x_dpy, win, name, name,
186 None, (char **)NULL, 0, &sizehints);
187 }
188
189 ctx_win = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
190 if (!ctx_win) {
191 printf("Error: eglCreateContext failed\n");
192 exit(1);
193 }
194
195 surf_win = eglCreateWindowSurface(dpy, config, win, NULL);
196
197 XFree(visInfo);
198
199 *winRet = win;
200 }
201
202 static void
203 use_window(void)
204 {
205 static int initialized;
206
207 eglMakeCurrent(dpy, surf_win, surf_win, ctx_win);
208 if (!initialized) {
209 initialized = 1;
210 glEnable(GL_TEXTURE_2D);
211 glBindTexture(GL_TEXTURE_2D, tex_pbuf);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
213
214 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
215 }
216 }
217
218 static void
219 draw_triangle(void)
220 {
221 static const GLfloat verts[3][2] = {
222 { -3, -3 },
223 { 3, -3 },
224 { 0, 3 }
225 };
226 GLfloat colors[3][4] = {
227 { 1, 0, 0, 1 },
228 { 0, 1, 0, 1 },
229 { 0, 0, 1, 1 }
230 };
231 GLint i;
232
233 /* flow the color */
234 for (i = 0; i < 3; i++) {
235 GLint first = (i + color_flow / 256) % 3;
236 GLint second = (first + 1) % 3;
237 GLint third = (second + 1) % 3;
238 GLfloat c = (color_flow % 256) / 256.0f;
239
240 c = c * c * c;
241 colors[i][first] = 1.0f - c;
242 colors[i][second] = c;
243 colors[i][third] = 0.0f;
244 }
245
246 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
247
248 glVertexPointer(2, GL_FLOAT, 0, verts);
249 glColorPointer(4, GL_FLOAT, 0, colors);
250 glEnableClientState(GL_VERTEX_ARRAY);
251 glEnableClientState(GL_COLOR_ARRAY);
252
253 glDrawArrays(GL_TRIANGLES, 0, 3);
254
255 glDisableClientState(GL_VERTEX_ARRAY);
256 glDisableClientState(GL_COLOR_ARRAY);
257 }
258
259 static void
260 draw_textured_cube(void)
261 {
262 static const GLfloat verts[][2] = {
263 { -4, -4 },
264 { 4, -4 },
265 { 4, 4 },
266 { -4, 4 }
267 };
268 static const GLfloat colors[][4] = {
269 { 1, 1, 1, 0.5 },
270 { 1, 1, 1, 0.5 },
271 { 1, 1, 1, 0.5 },
272 { 1, 1, 1, 0.5 }
273 };
274 static const GLfloat texs[][2] = {
275 { 0, 0 },
276 { 1, 0 },
277 { 1, 1 },
278 { 0, 1 }
279 };
280 static const GLfloat xforms[6][4] = {
281 { 0, 0, 1, 0 },
282 { 90, 0, 1, 0 },
283 { 180, 0, 1, 0 },
284 { 270, 0, 1, 0 },
285 { 90, 1, 0, 0 },
286 { -90, 1, 0, 0 }
287 };
288 GLint i;
289
290 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
291
292 if (blend) {
293 glDisable(GL_DEPTH_TEST);
294 glEnable(GL_BLEND);
295 } else {
296 glEnable(GL_DEPTH_TEST);
297 glDisable(GL_BLEND);
298 }
299
300 glVertexPointer(2, GL_FLOAT, 0, verts);
301 glColorPointer(4, GL_FLOAT, 0, colors);
302 glTexCoordPointer(2, GL_FLOAT, 0, texs);
303
304 glEnableClientState(GL_VERTEX_ARRAY);
305 glEnableClientState(GL_COLOR_ARRAY);
306 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
307
308 for (i = 0; i < 6; i++) {
309 glPushMatrix();
310 glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
311 glTranslatef(0, 0, 4.1);
312 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
313 glPopMatrix();
314 }
315
316 glDisableClientState(GL_VERTEX_ARRAY);
317 glDisableClientState(GL_COLOR_ARRAY);
318 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
319 }
320
321 static void
322 draw(void)
323 {
324 use_pbuffer();
325 draw_triangle();
326
327 use_window();
328
329 eglBindTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
330
331 glPushMatrix();
332 glRotatef(view_rotx, 1, 0, 0);
333 glRotatef(view_roty, 0, 1, 0);
334 glRotatef(view_rotz, 0, 0, 1);
335
336 draw_textured_cube();
337
338 glPopMatrix();
339
340 eglReleaseTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
341 }
342
343 /* new window size or exposure */
344 static void
345 reshape(int width, int height)
346 {
347 GLfloat ar = (GLfloat) width / (GLfloat) height;
348
349 use_window();
350
351 glViewport(0, 0, (GLint) width, (GLint) height);
352
353 glMatrixMode(GL_PROJECTION);
354 glLoadIdentity();
355 glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
356
357 glMatrixMode(GL_MODELVIEW);
358 glLoadIdentity();
359 glTranslatef(0.0, 0.0, -40.0);
360 }
361
362 static void
363 event_loop(Display *x_dpy, Window win)
364 {
365 while (1) {
366 int redraw = 1;
367
368 if (XPending(x_dpy) > 0) {
369 XEvent event;
370 XNextEvent(x_dpy, &event);
371
372 switch (event.type) {
373 case Expose:
374 redraw = 1;
375 break;
376 case ConfigureNotify:
377 reshape(event.xconfigure.width, event.xconfigure.height);
378 break;
379 case KeyPress:
380 {
381 char buffer[10];
382 int r, code;
383 code = XLookupKeysym(&event.xkey, 0);
384 if (code == XK_Left) {
385 view_roty += 5.0;
386 }
387 else if (code == XK_Right) {
388 view_roty -= 5.0;
389 }
390 else if (code == XK_Up) {
391 view_rotx += 5.0;
392 }
393 else if (code == XK_Down) {
394 view_rotx -= 5.0;
395 }
396 else if (code == XK_b) {
397 blend = !blend;
398 }
399 else {
400 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
401 NULL, NULL);
402 if (buffer[0] == 27) {
403 /* escape */
404 return;
405 }
406 }
407 }
408 redraw = 1;
409 break;
410 default:
411 ; /*no-op*/
412 }
413 }
414
415 if (redraw) {
416 view_rotx += 1.0;
417 view_roty += 2.0;
418 view_rotz += 1.5;
419 color_flow += 20;
420 draw();
421 eglSwapBuffers(dpy, surf_win);
422 }
423 }
424 }
425
426 int
427 main(int argc, char *argv[])
428 {
429 const int winWidth = 300, winHeight = 300;
430 Display *x_dpy;
431 Window win;
432 char *dpyName = NULL;
433 EGLint egl_major, egl_minor;
434 const char *s;
435
436 x_dpy = XOpenDisplay(dpyName);
437 if (!x_dpy) {
438 printf("Error: couldn't open display %s\n",
439 dpyName ? dpyName : getenv("DISPLAY"));
440 return -1;
441 }
442
443 dpy = eglGetDisplay(x_dpy);
444 if (!dpy) {
445 printf("Error: eglGetDisplay() failed\n");
446 return -1;
447 }
448
449 if (!eglInitialize(dpy, &egl_major, &egl_minor)) {
450 printf("Error: eglInitialize() failed\n");
451 return -1;
452 }
453
454 s = eglQueryString(dpy, EGL_VERSION);
455 printf("EGL_VERSION = %s\n", s);
456
457 make_window(x_dpy, "color flow", 0, 0, winWidth, winHeight, &win);
458 make_pbuffer(winWidth, winHeight);
459
460 XMapWindow(x_dpy, win);
461
462 reshape(winWidth, winHeight);
463 event_loop(x_dpy, win);
464
465 glDeleteTextures(1, &tex_pbuf);
466
467 eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
468 eglTerminate(dpy);
469
470 XDestroyWindow(x_dpy, win);
471 XCloseDisplay(x_dpy);
472
473 return 0;
474 }