Merge remote branch 'origin/7.8'
[mesa.git] / progs / egl / opengles1 / render_tex.c
1 /*
2 * Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
3 */
4
5 /*
6 * Test EGL render to texture.
7 * Brian Paul
8 * August 2008
9 */
10
11
12 #include <assert.h>
13 #include <math.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19 #include <X11/keysym.h>
20 #include <GLES/gl.h>
21 #include <GLES/glext.h>
22 #include <EGL/egl.h>
23
24
25 static int TexWidth = 256, TexHeight = 256;
26
27 static int WinWidth = 300, WinHeight = 300;
28
29 static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
30
31 static GLuint DotTexture, RenderTexture;
32
33
34 static void
35 Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
36 {
37 n[0] = nx;
38 n[1] = ny;
39 n[2] = nz;
40 }
41
42 static void
43 Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
44 {
45 v[0] = vx;
46 v[1] = vy;
47 v[2] = vz;
48 }
49
50 static void
51 Texcoord(GLfloat *v, GLfloat s, GLfloat t)
52 {
53 v[0] = s;
54 v[1] = t;
55 }
56
57
58 /* Borrowed from glut, adapted */
59 static void
60 draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
61 {
62 int i, j;
63 GLfloat theta, phi, theta1;
64 GLfloat cosTheta, sinTheta;
65 GLfloat cosTheta1, sinTheta1;
66 GLfloat ringDelta, sideDelta;
67 GLfloat varray[100][3], narray[100][3], tarray[100][2];
68 int vcount;
69
70 glVertexPointer(3, GL_FLOAT, 0, varray);
71 glNormalPointer(GL_FLOAT, 0, narray);
72 glTexCoordPointer(2, GL_FLOAT, 0, tarray);
73 glEnableClientState(GL_VERTEX_ARRAY);
74 glEnableClientState(GL_NORMAL_ARRAY);
75 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
76
77 ringDelta = 2.0 * M_PI / rings;
78 sideDelta = 2.0 * M_PI / nsides;
79
80 theta = 0.0;
81 cosTheta = 1.0;
82 sinTheta = 0.0;
83 for (i = rings - 1; i >= 0; i--) {
84 theta1 = theta + ringDelta;
85 cosTheta1 = cos(theta1);
86 sinTheta1 = sin(theta1);
87
88 vcount = 0; /* glBegin(GL_QUAD_STRIP); */
89
90 phi = 0.0;
91 for (j = nsides; j >= 0; j--) {
92 GLfloat s0, s1, t;
93 GLfloat cosPhi, sinPhi, dist;
94
95 phi += sideDelta;
96 cosPhi = cos(phi);
97 sinPhi = sin(phi);
98 dist = R + r * cosPhi;
99
100 s0 = 20.0 * theta / (2.0 * M_PI);
101 s1 = 20.0 * theta1 / (2.0 * M_PI);
102 t = 8.0 * phi / (2.0 * M_PI);
103
104 Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
105 Texcoord(tarray[vcount], s1, t);
106 Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
107 vcount++;
108
109 Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
110 Texcoord(tarray[vcount], s0, t);
111 Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
112 vcount++;
113 }
114
115 /*glEnd();*/
116 assert(vcount <= 100);
117 glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
118
119 theta = theta1;
120 cosTheta = cosTheta1;
121 sinTheta = sinTheta1;
122 }
123
124 glDisableClientState(GL_VERTEX_ARRAY);
125 glDisableClientState(GL_NORMAL_ARRAY);
126 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
127 }
128
129
130 static void
131 draw_torus_to_texture(void)
132 {
133 glViewport(0, 0, TexWidth, TexHeight);
134
135 glMatrixMode(GL_PROJECTION);
136 glLoadIdentity();
137 glFrustumf(-1, 1, -1, 1, 5.0, 60.0);
138
139 glMatrixMode(GL_MODELVIEW);
140 glLoadIdentity();
141 glTranslatef(0.0, 0.0, -15.0);
142
143 glClearColor(0.4, 0.4, 0.4, 0.0);
144 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
145
146 glBindTexture(GL_TEXTURE_2D, DotTexture);
147
148 glEnable(GL_LIGHTING);
149
150 glPushMatrix();
151 glRotatef(view_roty, 0, 1, 0);
152 glScalef(0.5, 0.5, 0.5);
153
154 draw_torus(1.0, 3.0, 30, 60);
155
156 glPopMatrix();
157
158 glDisable(GL_LIGHTING);
159
160 #if 0
161 glBindTexture(GL_TEXTURE_2D, RenderTexture);
162 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
163 #endif
164
165 glFinish();
166 }
167
168
169 static void
170 draw_textured_quad(void)
171 {
172 GLfloat ar = (GLfloat) WinWidth / (GLfloat) WinHeight;
173
174 glViewport(0, 0, WinWidth, WinHeight);
175
176 glMatrixMode(GL_PROJECTION);
177 glLoadIdentity();
178 glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
179
180 glMatrixMode(GL_MODELVIEW);
181 glLoadIdentity();
182 glTranslatef(0.0, 0.0, -8.0);
183
184 glClearColor(0.4, 0.4, 1.0, 0.0);
185 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
186
187 glBindTexture(GL_TEXTURE_2D, RenderTexture);
188
189 glPushMatrix();
190 glRotatef(view_rotx, 1, 0, 0);
191 glRotatef(view_rotz, 0, 0, 1);
192
193 {
194 static const GLfloat texcoord[4][2] = {
195 { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }
196 };
197 static const GLfloat vertex[4][2] = {
198 { -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 }
199 };
200
201 glVertexPointer(2, GL_FLOAT, 0, vertex);
202 glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
203 glEnableClientState(GL_VERTEX_ARRAY);
204 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
205
206 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
207
208 glDisableClientState(GL_VERTEX_ARRAY);
209 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
210 }
211
212 glPopMatrix();
213 }
214
215
216
217 static void
218 draw(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
219 EGLContext egl_ctx)
220 {
221 /*printf("Begin draw\n");*/
222
223 /* first draw torus to pbuffer /texture */
224 #if 01
225 if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
226 #else
227 if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
228 #endif
229 printf("Error: eglMakeCurrent(pbuf) failed\n");
230 return;
231 }
232 draw_torus_to_texture();
233
234 /* draw textured quad to window */
235 if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
236 printf("Error: eglMakeCurrent(pbuffer) failed\n");
237 return;
238 }
239
240 glBindTexture(GL_TEXTURE_2D, RenderTexture);
241 eglBindTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
242 draw_textured_quad();
243 eglReleaseTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
244
245 eglSwapBuffers(egl_dpy, egl_surf);
246
247 /*printf("End draw\n");*/
248 }
249
250
251
252 static void
253 make_dot_texture(void)
254 {
255 #define SZ 64
256 GLenum Filter = GL_LINEAR;
257 GLubyte image[SZ][SZ][4];
258 GLuint i, j;
259
260 for (i = 0; i < SZ; i++) {
261 for (j = 0; j < SZ; j++) {
262 GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
263 d = sqrt(d);
264 if (d < SZ/3) {
265 image[i][j][0] = 255;
266 image[i][j][1] = 255;
267 image[i][j][2] = 255;
268 image[i][j][3] = 255;
269 }
270 else {
271 image[i][j][0] = 127;
272 image[i][j][1] = 127;
273 image[i][j][2] = 127;
274 image[i][j][3] = 255;
275 }
276 }
277 }
278
279 glGenTextures(1, &DotTexture);
280 glBindTexture(GL_TEXTURE_2D, DotTexture);
281 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
282 GL_RGBA, GL_UNSIGNED_BYTE, image);
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
287 #undef SZ
288 }
289
290
291 static void
292 make_render_texture(void)
293 {
294 GLenum Filter = GL_LINEAR;
295 glGenTextures(1, &RenderTexture);
296 glBindTexture(GL_TEXTURE_2D, RenderTexture);
297 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
298 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
303 }
304
305
306 static void
307 init(void)
308 {
309 static const GLfloat red[4] = {1, 0, 0, 0};
310 static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
311 static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
312 static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
313 static const GLfloat pos[4] = {20, 20, 50, 1};
314
315 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
316 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
317 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
318
319 glEnable(GL_LIGHT0);
320 glLightfv(GL_LIGHT0, GL_POSITION, pos);
321 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
322 glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
323
324 glEnable(GL_DEPTH_TEST);
325
326 make_dot_texture();
327 make_render_texture();
328
329 printf("DotTexture=%u RenderTexture=%u\n", DotTexture, RenderTexture);
330
331 glEnable(GL_TEXTURE_2D);
332 }
333
334
335 /*
336 * Create an RGB, double-buffered X window.
337 * Return the window and context handles.
338 */
339 static void
340 make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
341 const char *name,
342 int x, int y, int width, int height,
343 Window *winRet,
344 EGLContext *ctxRet,
345 EGLSurface *surfRet)
346 {
347 static const EGLint attribs[] = {
348 EGL_RED_SIZE, 1,
349 EGL_GREEN_SIZE, 1,
350 EGL_BLUE_SIZE, 1,
351 EGL_DEPTH_SIZE, 1,
352 EGL_NONE
353 };
354
355 int scrnum;
356 XSetWindowAttributes attr;
357 unsigned long mask;
358 Window root;
359 Window win;
360 XVisualInfo *visInfo, visTemplate;
361 int num_visuals;
362 EGLContext ctx;
363 EGLConfig config;
364 EGLint num_configs;
365 EGLint vid;
366
367 scrnum = DefaultScreen( x_dpy );
368 root = RootWindow( x_dpy, scrnum );
369
370 if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
371 printf("Error: couldn't get an EGL visual config\n");
372 exit(1);
373 }
374
375 assert(config);
376 assert(num_configs > 0);
377
378 if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
379 printf("Error: eglGetConfigAttrib() failed\n");
380 exit(1);
381 }
382
383 /* The X window visual must match the EGL config */
384 visTemplate.visualid = vid;
385 visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
386 if (!visInfo) {
387 printf("Error: couldn't get X visual\n");
388 exit(1);
389 }
390
391 /* window attributes */
392 attr.background_pixel = 0;
393 attr.border_pixel = 0;
394 attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
395 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
396 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
397
398 win = XCreateWindow( x_dpy, root, 0, 0, width, height,
399 0, visInfo->depth, InputOutput,
400 visInfo->visual, mask, &attr );
401
402 /* set hints and properties */
403 {
404 XSizeHints sizehints;
405 sizehints.x = x;
406 sizehints.y = y;
407 sizehints.width = width;
408 sizehints.height = height;
409 sizehints.flags = USSize | USPosition;
410 XSetNormalHints(x_dpy, win, &sizehints);
411 XSetStandardProperties(x_dpy, win, name, name,
412 None, (char **)NULL, 0, &sizehints);
413 }
414
415 eglBindAPI(EGL_OPENGL_ES_API);
416
417 ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
418 if (!ctx) {
419 printf("Error: eglCreateContext failed\n");
420 exit(1);
421 }
422
423 *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
424
425 if (!*surfRet) {
426 printf("Error: eglCreateWindowSurface failed\n");
427 exit(1);
428 }
429
430 XFree(visInfo);
431
432 *winRet = win;
433 *ctxRet = ctx;
434 }
435
436
437 static EGLSurface
438 make_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
439 {
440 static const EGLint config_attribs[] = {
441 EGL_RED_SIZE, 1,
442 EGL_GREEN_SIZE, 1,
443 EGL_BLUE_SIZE, 1,
444 EGL_DEPTH_SIZE, 1,
445 EGL_NONE
446 };
447 EGLConfig config;
448 EGLSurface pbuf;
449 EGLint num_configs;
450 EGLint pbuf_attribs[15];
451 int i = 0;
452
453 pbuf_attribs[i++] = EGL_WIDTH;
454 pbuf_attribs[i++] = width;
455 pbuf_attribs[i++] = EGL_HEIGHT;
456 pbuf_attribs[i++] = height;
457 pbuf_attribs[i++] = EGL_TEXTURE_FORMAT;
458 pbuf_attribs[i++] = EGL_TEXTURE_RGBA;
459 pbuf_attribs[i++] = EGL_TEXTURE_TARGET;
460 pbuf_attribs[i++] = EGL_TEXTURE_2D;
461 pbuf_attribs[i++] = EGL_MIPMAP_TEXTURE;
462 pbuf_attribs[i++] = EGL_FALSE;
463 pbuf_attribs[i++] = EGL_NONE;
464 assert(i <= 15);
465
466 if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
467 printf("Error: couldn't get an EGL config for pbuffer\n");
468 exit(1);
469 }
470
471 pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
472
473 return pbuf;
474 }
475
476
477 static void
478 event_loop(Display *dpy, Window win,
479 EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
480 EGLContext egl_ctx)
481 {
482 int anim = 0;
483
484 while (1) {
485 int redraw = 0;
486
487 if (!anim || XPending(dpy)) {
488 XEvent event;
489 XNextEvent(dpy, &event);
490
491 switch (event.type) {
492 case Expose:
493 redraw = 1;
494 break;
495 case ConfigureNotify:
496 if (event.xconfigure.window == win) {
497 WinWidth = event.xconfigure.width;
498 WinHeight = event.xconfigure.height;
499 }
500 break;
501 case KeyPress:
502 {
503 char buffer[10];
504 int r, code;
505 code = XLookupKeysym(&event.xkey, 0);
506 if (code == XK_Left) {
507 view_roty += 5.0;
508 }
509 else if (code == XK_Right) {
510 view_roty -= 5.0;
511 }
512 else if (code == XK_Up) {
513 view_rotx += 5.0;
514 }
515 else if (code == XK_Down) {
516 view_rotx -= 5.0;
517 }
518 else {
519 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
520 NULL, NULL);
521 if (buffer[0] == ' ') {
522 anim = !anim;
523 }
524 else if (buffer[0] == 'z') {
525 view_rotz += 5.0;
526 }
527 else if (buffer[0] == 'Z') {
528 view_rotz -= 5.0;
529 }
530 else if (buffer[0] == 27) {
531 /* escape */
532 return;
533 }
534 }
535 }
536 redraw = 1;
537 break;
538 default:
539 ; /*no-op*/
540 }
541 }
542
543 if (anim) {
544 view_rotx += 1.0;
545 view_roty += 2.0;
546 redraw = 1;
547 }
548
549 if (redraw) {
550 draw(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
551 }
552 }
553 }
554
555
556 static void
557 usage(void)
558 {
559 printf("Usage:\n");
560 printf(" -display <displayname> set the display to run on\n");
561 printf(" -info display OpenGL renderer info\n");
562 }
563
564
565 int
566 main(int argc, char *argv[])
567 {
568 Display *x_dpy;
569 Window win;
570 EGLSurface egl_surf, egl_pbuf;
571 EGLContext egl_ctx;
572 EGLDisplay egl_dpy;
573 char *dpyName = NULL;
574 GLboolean printInfo = GL_FALSE;
575 EGLint egl_major, egl_minor;
576 int i;
577 const char *s;
578
579 for (i = 1; i < argc; i++) {
580 if (strcmp(argv[i], "-display") == 0) {
581 dpyName = argv[i+1];
582 i++;
583 }
584 else if (strcmp(argv[i], "-info") == 0) {
585 printInfo = GL_TRUE;
586 }
587 else {
588 usage();
589 return -1;
590 }
591 }
592
593 x_dpy = XOpenDisplay(dpyName);
594 if (!x_dpy) {
595 printf("Error: couldn't open display %s\n",
596 dpyName ? dpyName : getenv("DISPLAY"));
597 return -1;
598 }
599
600 egl_dpy = eglGetDisplay(x_dpy);
601 if (!egl_dpy) {
602 printf("Error: eglGetDisplay() failed\n");
603 return -1;
604 }
605
606 if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
607 printf("Error: eglInitialize() failed\n");
608 return -1;
609 }
610
611 s = eglQueryString(egl_dpy, EGL_VERSION);
612 printf("EGL_VERSION = %s\n", s);
613
614 s = eglQueryString(egl_dpy, EGL_VENDOR);
615 printf("EGL_VENDOR = %s\n", s);
616
617 s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
618 printf("EGL_EXTENSIONS = %s\n", s);
619
620 s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
621 printf("EGL_CLIENT_APIS = %s\n", s);
622
623 make_x_window(x_dpy, egl_dpy,
624 "render_tex", 0, 0, WinWidth, WinHeight,
625 &win, &egl_ctx, &egl_surf);
626
627 egl_pbuf = make_pbuffer(x_dpy, egl_dpy, TexWidth, TexHeight);
628 if (!egl_pbuf) {
629 printf("Error: eglCreatePBufferSurface() failed\n");
630 return -1;
631 }
632
633 XMapWindow(x_dpy, win);
634 if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
635 printf("Error: eglMakeCurrent() failed\n");
636 return -1;
637 }
638
639 if (printInfo) {
640 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
641 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
642 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
643 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
644 }
645
646 init();
647
648 event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
649
650 eglDestroyContext(egl_dpy, egl_ctx);
651 eglDestroySurface(egl_dpy, egl_surf);
652 eglTerminate(egl_dpy);
653
654
655 XDestroyWindow(x_dpy, win);
656 XCloseDisplay(x_dpy);
657
658 return 0;
659 }