132001f49Smrg/*
232001f49Smrg * Copyright (C) 2008  Tunsgten Graphics,Inc.   All Rights Reserved.
332001f49Smrg */
432001f49Smrg
532001f49Smrg/*
632001f49Smrg * Test EGL render to texture.
732001f49Smrg * Brian Paul
832001f49Smrg * August 2008
932001f49Smrg */
1032001f49Smrg
1132001f49Smrg
1232001f49Smrg#include <assert.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include <stdlib.h>
1532001f49Smrg#include <stdio.h>
1632001f49Smrg#include <string.h>
1732001f49Smrg#include <X11/Xlib.h>
1832001f49Smrg#include <X11/Xutil.h>
1932001f49Smrg#include <X11/keysym.h>
2032001f49Smrg#include <GLES/gl.h>
2132001f49Smrg#include <GLES/glext.h>
2232001f49Smrg#include <EGL/egl.h>
2332001f49Smrg
2432001f49Smrg
2532001f49Smrgstatic int TexWidth = 256, TexHeight = 256;
2632001f49Smrg
2732001f49Smrgstatic int WinWidth = 300, WinHeight = 300;
2832001f49Smrg
2932001f49Smrgstatic GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
3032001f49Smrg
3132001f49Smrgstatic GLuint DotTexture, RenderTexture;
3232001f49Smrg
3332001f49Smrg
3432001f49Smrgstatic void
3532001f49SmrgNormal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
3632001f49Smrg{
3732001f49Smrg   n[0] = nx;
3832001f49Smrg   n[1] = ny;
3932001f49Smrg   n[2] = nz;
4032001f49Smrg}
4132001f49Smrg
4232001f49Smrgstatic void
4332001f49SmrgVertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
4432001f49Smrg{
4532001f49Smrg   v[0] = vx;
4632001f49Smrg   v[1] = vy;
4732001f49Smrg   v[2] = vz;
4832001f49Smrg}
4932001f49Smrg
5032001f49Smrgstatic void
5132001f49SmrgTexcoord(GLfloat *v, GLfloat s, GLfloat t)
5232001f49Smrg{
5332001f49Smrg   v[0] = s;
5432001f49Smrg   v[1] = t;
5532001f49Smrg}
5632001f49Smrg
5732001f49Smrg
5832001f49Smrg/* Borrowed from glut, adapted */
5932001f49Smrgstatic void
6032001f49Smrgdraw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
6132001f49Smrg{
6232001f49Smrg   int i, j;
6332001f49Smrg   GLfloat theta, phi, theta1;
6432001f49Smrg   GLfloat cosTheta, sinTheta;
6532001f49Smrg   GLfloat cosTheta1, sinTheta1;
6632001f49Smrg   GLfloat ringDelta, sideDelta;
6732001f49Smrg   GLfloat varray[100][3], narray[100][3], tarray[100][2];
6832001f49Smrg   int vcount;
6932001f49Smrg
7032001f49Smrg   glVertexPointer(3, GL_FLOAT, 0, varray);
7132001f49Smrg   glNormalPointer(GL_FLOAT, 0, narray);
7232001f49Smrg   glTexCoordPointer(2, GL_FLOAT, 0, tarray);
7332001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
7432001f49Smrg   glEnableClientState(GL_NORMAL_ARRAY);
7532001f49Smrg   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
7632001f49Smrg
7732001f49Smrg   ringDelta = 2.0 * M_PI / rings;
7832001f49Smrg   sideDelta = 2.0 * M_PI / nsides;
7932001f49Smrg
8032001f49Smrg   theta = 0.0;
8132001f49Smrg   cosTheta = 1.0;
8232001f49Smrg   sinTheta = 0.0;
8332001f49Smrg   for (i = rings - 1; i >= 0; i--) {
8432001f49Smrg      theta1 = theta + ringDelta;
8532001f49Smrg      cosTheta1 = cos(theta1);
8632001f49Smrg      sinTheta1 = sin(theta1);
8732001f49Smrg
8832001f49Smrg      vcount = 0; /* glBegin(GL_QUAD_STRIP); */
8932001f49Smrg
9032001f49Smrg      phi = 0.0;
9132001f49Smrg      for (j = nsides; j >= 0; j--) {
9232001f49Smrg         GLfloat s0, s1, t;
9332001f49Smrg         GLfloat cosPhi, sinPhi, dist;
9432001f49Smrg
9532001f49Smrg         phi += sideDelta;
9632001f49Smrg         cosPhi = cos(phi);
9732001f49Smrg         sinPhi = sin(phi);
9832001f49Smrg         dist = R + r * cosPhi;
9932001f49Smrg
10032001f49Smrg         s0 = 20.0 * theta / (2.0 * M_PI);
10132001f49Smrg         s1 = 20.0 * theta1 / (2.0 * M_PI);
10232001f49Smrg         t = 8.0 * phi / (2.0 * M_PI);
10332001f49Smrg
10432001f49Smrg         Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
10532001f49Smrg         Texcoord(tarray[vcount], s1, t);
10632001f49Smrg         Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
10732001f49Smrg         vcount++;
10832001f49Smrg
10932001f49Smrg         Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
11032001f49Smrg         Texcoord(tarray[vcount], s0, t);
11132001f49Smrg         Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist,  r * sinPhi);
11232001f49Smrg         vcount++;
11332001f49Smrg      }
11432001f49Smrg
11532001f49Smrg      /*glEnd();*/
11632001f49Smrg      assert(vcount <= 100);
11732001f49Smrg      glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
11832001f49Smrg
11932001f49Smrg      theta = theta1;
12032001f49Smrg      cosTheta = cosTheta1;
12132001f49Smrg      sinTheta = sinTheta1;
12232001f49Smrg   }
12332001f49Smrg
12432001f49Smrg   glDisableClientState(GL_VERTEX_ARRAY);
12532001f49Smrg   glDisableClientState(GL_NORMAL_ARRAY);
12632001f49Smrg   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
12732001f49Smrg}
12832001f49Smrg
12932001f49Smrg
13032001f49Smrgstatic void
13132001f49Smrgdraw_torus_to_texture(void)
13232001f49Smrg{
13332001f49Smrg   glViewport(0, 0, TexWidth, TexHeight);
13432001f49Smrg
13532001f49Smrg   glMatrixMode(GL_PROJECTION);
13632001f49Smrg   glLoadIdentity();
13732001f49Smrg   glFrustumf(-1, 1, -1, 1, 5.0, 60.0);
13832001f49Smrg
13932001f49Smrg   glMatrixMode(GL_MODELVIEW);
14032001f49Smrg   glLoadIdentity();
14132001f49Smrg   glTranslatef(0.0, 0.0, -15.0);
14232001f49Smrg
14332001f49Smrg   glClearColor(0.4, 0.4, 0.4, 0.0);
14432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
14532001f49Smrg
14632001f49Smrg   glBindTexture(GL_TEXTURE_2D, DotTexture);
14732001f49Smrg
14832001f49Smrg   glEnable(GL_LIGHTING);
14932001f49Smrg
15032001f49Smrg   glPushMatrix();
15132001f49Smrg   glRotatef(view_roty, 0, 1, 0);
15232001f49Smrg   glScalef(0.5, 0.5, 0.5);
15332001f49Smrg
15432001f49Smrg   draw_torus(1.0, 3.0, 30, 60);
15532001f49Smrg
15632001f49Smrg   glPopMatrix();
15732001f49Smrg
15832001f49Smrg   glDisable(GL_LIGHTING);
15932001f49Smrg
16032001f49Smrg#if 0
16132001f49Smrg   glBindTexture(GL_TEXTURE_2D, RenderTexture);
16232001f49Smrg   glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
16332001f49Smrg#endif
16432001f49Smrg
16532001f49Smrg   glFinish();
16632001f49Smrg}
16732001f49Smrg
16832001f49Smrg
16932001f49Smrgstatic void
17032001f49Smrgdraw_textured_quad(void)
17132001f49Smrg{
17232001f49Smrg   GLfloat ar = (GLfloat) WinWidth / (GLfloat) WinHeight;
17332001f49Smrg
17432001f49Smrg   glViewport(0, 0, WinWidth, WinHeight);
17532001f49Smrg
17632001f49Smrg   glMatrixMode(GL_PROJECTION);
17732001f49Smrg   glLoadIdentity();
17832001f49Smrg   glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
17932001f49Smrg
18032001f49Smrg   glMatrixMode(GL_MODELVIEW);
18132001f49Smrg   glLoadIdentity();
18232001f49Smrg   glTranslatef(0.0, 0.0, -8.0);
18332001f49Smrg
18432001f49Smrg   glClearColor(0.4, 0.4, 1.0, 0.0);
18532001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
18632001f49Smrg
18732001f49Smrg   glBindTexture(GL_TEXTURE_2D, RenderTexture);
18832001f49Smrg
18932001f49Smrg   glPushMatrix();
19032001f49Smrg   glRotatef(view_rotx, 1, 0, 0);
19132001f49Smrg   glRotatef(view_rotz, 0, 0, 1);
19232001f49Smrg
19332001f49Smrg   {
19432001f49Smrg      static const GLfloat texcoord[4][2] = {
19532001f49Smrg         { 0, 0 },  { 1, 0 },  { 0, 1 },  { 1, 1 }
19632001f49Smrg      };
19732001f49Smrg      static const GLfloat vertex[4][2] = {
19832001f49Smrg         { -1, -1 },  {  1, -1 },  { -1,  1 },  {  1,  1 }
19932001f49Smrg      };
20032001f49Smrg
20132001f49Smrg      glVertexPointer(2, GL_FLOAT, 0, vertex);
20232001f49Smrg      glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
20332001f49Smrg      glEnableClientState(GL_VERTEX_ARRAY);
20432001f49Smrg      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
20532001f49Smrg
20632001f49Smrg      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
20732001f49Smrg
20832001f49Smrg      glDisableClientState(GL_VERTEX_ARRAY);
20932001f49Smrg      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
21032001f49Smrg   }
21132001f49Smrg
21232001f49Smrg   glPopMatrix();
21332001f49Smrg}
21432001f49Smrg
21532001f49Smrg
21632001f49Smrg
21732001f49Smrgstatic void
21832001f49Smrgdraw(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
21932001f49Smrg     EGLContext egl_ctx)
22032001f49Smrg{
22132001f49Smrg   /*printf("Begin draw\n");*/
22232001f49Smrg
22332001f49Smrg   /* first draw torus to pbuffer /texture */
22432001f49Smrg#if 01
22532001f49Smrg   if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
22632001f49Smrg#else
22732001f49Smrg   if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
22832001f49Smrg#endif
22932001f49Smrg      printf("Error: eglMakeCurrent(pbuf) failed\n");
23032001f49Smrg      return;
23132001f49Smrg   }
23232001f49Smrg   draw_torus_to_texture();
23332001f49Smrg
23432001f49Smrg   /* draw textured quad to window */
23532001f49Smrg   if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
23632001f49Smrg      printf("Error: eglMakeCurrent(pbuffer) failed\n");
23732001f49Smrg      return;
23832001f49Smrg   }
23932001f49Smrg
24032001f49Smrg   glBindTexture(GL_TEXTURE_2D, RenderTexture);
24132001f49Smrg   eglBindTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
24232001f49Smrg   draw_textured_quad();
24332001f49Smrg   eglReleaseTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
24432001f49Smrg
24532001f49Smrg   eglSwapBuffers(egl_dpy, egl_surf);
24632001f49Smrg
24732001f49Smrg   /*printf("End draw\n");*/
24832001f49Smrg}
24932001f49Smrg
25032001f49Smrg
25132001f49Smrg
25232001f49Smrgstatic void
25332001f49Smrgmake_dot_texture(void)
25432001f49Smrg{
25532001f49Smrg#define SZ 64
25632001f49Smrg   GLenum Filter = GL_LINEAR;
25732001f49Smrg   GLubyte image[SZ][SZ][4];
25832001f49Smrg   GLuint i, j;
25932001f49Smrg
26032001f49Smrg   for (i = 0; i < SZ; i++) {
26132001f49Smrg      for (j = 0; j < SZ; j++) {
26232001f49Smrg         GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
26332001f49Smrg         d = sqrt(d);
26432001f49Smrg         if (d < SZ/3) {
26532001f49Smrg            image[i][j][0] = 255;
26632001f49Smrg            image[i][j][1] = 255;
26732001f49Smrg            image[i][j][2] = 255;
26832001f49Smrg            image[i][j][3] = 255;
26932001f49Smrg         }
27032001f49Smrg         else {
27132001f49Smrg            image[i][j][0] = 127;
27232001f49Smrg            image[i][j][1] = 127;
27332001f49Smrg            image[i][j][2] = 127;
27432001f49Smrg            image[i][j][3] = 255;
27532001f49Smrg         }
27632001f49Smrg      }
27732001f49Smrg   }
27832001f49Smrg
27932001f49Smrg   glGenTextures(1, &DotTexture);
28032001f49Smrg   glBindTexture(GL_TEXTURE_2D, DotTexture);
28132001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
28232001f49Smrg                GL_RGBA, GL_UNSIGNED_BYTE, image);
28332001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
28432001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
28532001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
28632001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
28732001f49Smrg#undef SZ
28832001f49Smrg}
28932001f49Smrg
29032001f49Smrg
29132001f49Smrgstatic void
29232001f49Smrgmake_render_texture(void)
29332001f49Smrg{
29432001f49Smrg   GLenum Filter = GL_LINEAR;
29532001f49Smrg   glGenTextures(1, &RenderTexture);
29632001f49Smrg   glBindTexture(GL_TEXTURE_2D, RenderTexture);
29732001f49Smrg   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
29832001f49Smrg                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
29932001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
30032001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
30132001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
30232001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
30332001f49Smrg}
30432001f49Smrg
30532001f49Smrg
30632001f49Smrgstatic void
30732001f49Smrginit(void)
30832001f49Smrg{
30932001f49Smrg   static const GLfloat red[4] = {1, 0, 0, 0};
31032001f49Smrg   static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
31132001f49Smrg   static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
31232001f49Smrg   static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
31332001f49Smrg   static const GLfloat pos[4] = {20, 20, 50, 1};
31432001f49Smrg
31532001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
31632001f49Smrg   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
31732001f49Smrg   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
31832001f49Smrg
31932001f49Smrg   glEnable(GL_LIGHT0);
32032001f49Smrg   glLightfv(GL_LIGHT0, GL_POSITION, pos);
32132001f49Smrg   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
32232001f49Smrg   glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
32332001f49Smrg
32432001f49Smrg   glEnable(GL_DEPTH_TEST);
32532001f49Smrg
32632001f49Smrg   make_dot_texture();
32732001f49Smrg   make_render_texture();
32832001f49Smrg
32932001f49Smrg   printf("DotTexture=%u RenderTexture=%u\n", DotTexture, RenderTexture);
33032001f49Smrg
33132001f49Smrg   glEnable(GL_TEXTURE_2D);
33232001f49Smrg}
33332001f49Smrg
33432001f49Smrg
33532001f49Smrg/*
33632001f49Smrg * Create an RGB, double-buffered X window.
33732001f49Smrg * Return the window and context handles.
33832001f49Smrg */
33932001f49Smrgstatic void
34032001f49Smrgmake_x_window(Display *x_dpy, EGLDisplay egl_dpy,
34132001f49Smrg              const char *name,
34232001f49Smrg              int x, int y, int width, int height,
34332001f49Smrg              Window *winRet,
34432001f49Smrg              EGLContext *ctxRet,
34532001f49Smrg              EGLSurface *surfRet)
34632001f49Smrg{
34732001f49Smrg   static const EGLint attribs[] = {
34832001f49Smrg      EGL_RED_SIZE, 1,
34932001f49Smrg      EGL_GREEN_SIZE, 1,
35032001f49Smrg      EGL_BLUE_SIZE, 1,
35132001f49Smrg      EGL_DEPTH_SIZE, 1,
35232001f49Smrg      EGL_NONE
35332001f49Smrg   };
35432001f49Smrg
35532001f49Smrg   int scrnum;
35632001f49Smrg   XSetWindowAttributes attr;
35732001f49Smrg   unsigned long mask;
35832001f49Smrg   Window root;
35932001f49Smrg   Window win;
36032001f49Smrg   XVisualInfo *visInfo, visTemplate;
36132001f49Smrg   int num_visuals;
36232001f49Smrg   EGLContext ctx;
36332001f49Smrg   EGLConfig config;
36432001f49Smrg   EGLint num_configs;
36532001f49Smrg   EGLint vid;
36632001f49Smrg
36732001f49Smrg   scrnum = DefaultScreen( x_dpy );
36832001f49Smrg   root = RootWindow( x_dpy, scrnum );
36932001f49Smrg
37032001f49Smrg   if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
37132001f49Smrg      printf("Error: couldn't get an EGL visual config\n");
37232001f49Smrg      exit(1);
37332001f49Smrg   }
37432001f49Smrg
37532001f49Smrg   assert(config);
37632001f49Smrg   assert(num_configs > 0);
37732001f49Smrg
37832001f49Smrg   if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
37932001f49Smrg      printf("Error: eglGetConfigAttrib() failed\n");
38032001f49Smrg      exit(1);
38132001f49Smrg   }
38232001f49Smrg
38332001f49Smrg   /* The X window visual must match the EGL config */
38432001f49Smrg   visTemplate.visualid = vid;
38532001f49Smrg   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
38632001f49Smrg   if (!visInfo) {
38732001f49Smrg      printf("Error: couldn't get X visual\n");
38832001f49Smrg      exit(1);
38932001f49Smrg   }
39032001f49Smrg
39132001f49Smrg   /* window attributes */
39232001f49Smrg   attr.background_pixel = 0;
39332001f49Smrg   attr.border_pixel = 0;
39432001f49Smrg   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
39532001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
39632001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
39732001f49Smrg
39832001f49Smrg   win = XCreateWindow( x_dpy, root, 0, 0, width, height,
39932001f49Smrg		        0, visInfo->depth, InputOutput,
40032001f49Smrg		        visInfo->visual, mask, &attr );
40132001f49Smrg
40232001f49Smrg   /* set hints and properties */
40332001f49Smrg   {
40432001f49Smrg      XSizeHints sizehints;
40532001f49Smrg      sizehints.x = x;
40632001f49Smrg      sizehints.y = y;
40732001f49Smrg      sizehints.width  = width;
40832001f49Smrg      sizehints.height = height;
40932001f49Smrg      sizehints.flags = USSize | USPosition;
41032001f49Smrg      XSetNormalHints(x_dpy, win, &sizehints);
41132001f49Smrg      XSetStandardProperties(x_dpy, win, name, name,
41232001f49Smrg                              None, (char **)NULL, 0, &sizehints);
41332001f49Smrg   }
41432001f49Smrg
41532001f49Smrg   eglBindAPI(EGL_OPENGL_ES_API);
41632001f49Smrg
41732001f49Smrg   ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
41832001f49Smrg   if (!ctx) {
41932001f49Smrg      printf("Error: eglCreateContext failed\n");
42032001f49Smrg      exit(1);
42132001f49Smrg   }
42232001f49Smrg
42332001f49Smrg   *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
42432001f49Smrg
42532001f49Smrg   if (!*surfRet) {
42632001f49Smrg      printf("Error: eglCreateWindowSurface failed\n");
42732001f49Smrg      exit(1);
42832001f49Smrg   }
42932001f49Smrg
43032001f49Smrg   XFree(visInfo);
43132001f49Smrg
43232001f49Smrg   *winRet = win;
43332001f49Smrg   *ctxRet = ctx;
43432001f49Smrg}
43532001f49Smrg
43632001f49Smrg
43732001f49Smrgstatic EGLSurface
43832001f49Smrgmake_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
43932001f49Smrg{
44032001f49Smrg   static const EGLint config_attribs[] = {
44132001f49Smrg      EGL_RED_SIZE, 1,
44232001f49Smrg      EGL_GREEN_SIZE, 1,
44332001f49Smrg      EGL_BLUE_SIZE, 1,
44432001f49Smrg      EGL_DEPTH_SIZE, 1,
44532001f49Smrg      EGL_NONE
44632001f49Smrg   };
44732001f49Smrg   EGLConfig config;
44832001f49Smrg   EGLSurface pbuf;
44932001f49Smrg   EGLint num_configs;
45032001f49Smrg   EGLint pbuf_attribs[15];
45132001f49Smrg   int i = 0;
45232001f49Smrg
45332001f49Smrg   pbuf_attribs[i++] = EGL_WIDTH;
45432001f49Smrg   pbuf_attribs[i++] = width;
45532001f49Smrg   pbuf_attribs[i++] = EGL_HEIGHT;
45632001f49Smrg   pbuf_attribs[i++] = height;
45732001f49Smrg   pbuf_attribs[i++] = EGL_TEXTURE_FORMAT;
45832001f49Smrg   pbuf_attribs[i++] = EGL_TEXTURE_RGBA;
45932001f49Smrg   pbuf_attribs[i++] = EGL_TEXTURE_TARGET;
46032001f49Smrg   pbuf_attribs[i++] = EGL_TEXTURE_2D;
46132001f49Smrg   pbuf_attribs[i++] = EGL_MIPMAP_TEXTURE;
46232001f49Smrg   pbuf_attribs[i++] = EGL_FALSE;
46332001f49Smrg   pbuf_attribs[i++] = EGL_NONE;
46432001f49Smrg   assert(i <= 15);
46532001f49Smrg
46632001f49Smrg   if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
46732001f49Smrg      printf("Error: couldn't get an EGL config for pbuffer\n");
46832001f49Smrg      exit(1);
46932001f49Smrg   }
47032001f49Smrg
47132001f49Smrg   pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
47232001f49Smrg
47332001f49Smrg   return pbuf;
47432001f49Smrg}
47532001f49Smrg
47632001f49Smrg
47732001f49Smrgstatic void
47832001f49Smrgevent_loop(Display *dpy, Window win,
47932001f49Smrg           EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
48032001f49Smrg           EGLContext egl_ctx)
48132001f49Smrg{
48232001f49Smrg   int anim = 0;
48332001f49Smrg
48432001f49Smrg   while (1) {
48532001f49Smrg      int redraw = 0;
48632001f49Smrg
48732001f49Smrg      if (!anim || XPending(dpy)) {
48832001f49Smrg         XEvent event;
48932001f49Smrg         XNextEvent(dpy, &event);
49032001f49Smrg
49132001f49Smrg         switch (event.type) {
49232001f49Smrg         case Expose:
49332001f49Smrg            redraw = 1;
49432001f49Smrg            break;
49532001f49Smrg         case ConfigureNotify:
49632001f49Smrg            if (event.xconfigure.window == win) {
49732001f49Smrg               WinWidth = event.xconfigure.width;
49832001f49Smrg               WinHeight = event.xconfigure.height;
49932001f49Smrg            }
50032001f49Smrg            break;
50132001f49Smrg         case KeyPress:
50232001f49Smrg            {
50332001f49Smrg               char buffer[10];
50432001f49Smrg               int r, code;
50532001f49Smrg               code = XLookupKeysym(&event.xkey, 0);
50632001f49Smrg               if (code == XK_Left) {
50732001f49Smrg               view_roty += 5.0;
50832001f49Smrg               }
50932001f49Smrg               else if (code == XK_Right) {
51032001f49Smrg                  view_roty -= 5.0;
51132001f49Smrg               }
51232001f49Smrg               else if (code == XK_Up) {
51332001f49Smrg                  view_rotx += 5.0;
51432001f49Smrg               }
51532001f49Smrg               else if (code == XK_Down) {
51632001f49Smrg                  view_rotx -= 5.0;
51732001f49Smrg               }
51832001f49Smrg               else {
51932001f49Smrg                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
52032001f49Smrg                                    NULL, NULL);
52132001f49Smrg                  if (buffer[0] == ' ') {
52232001f49Smrg                     anim = !anim;
52332001f49Smrg                  }
52432001f49Smrg                  else if (buffer[0] == 'z') {
52532001f49Smrg                     view_rotz += 5.0;
52632001f49Smrg                  }
52732001f49Smrg                  else if (buffer[0] == 'Z') {
52832001f49Smrg                     view_rotz -= 5.0;
52932001f49Smrg                  }
53032001f49Smrg                  else if (buffer[0] == 27) {
53132001f49Smrg                     /* escape */
53232001f49Smrg                     return;
53332001f49Smrg                  }
53432001f49Smrg               }
53532001f49Smrg            }
53632001f49Smrg            redraw = 1;
53732001f49Smrg            break;
53832001f49Smrg         default:
53932001f49Smrg            ; /*no-op*/
54032001f49Smrg         }
54132001f49Smrg      }
54232001f49Smrg
54332001f49Smrg      if (anim) {
54432001f49Smrg         view_rotx += 1.0;
54532001f49Smrg         view_roty += 2.0;
54632001f49Smrg         redraw = 1;
54732001f49Smrg      }
54832001f49Smrg
54932001f49Smrg      if (redraw) {
55032001f49Smrg         draw(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
55132001f49Smrg      }
55232001f49Smrg   }
55332001f49Smrg}
55432001f49Smrg
55532001f49Smrg
55632001f49Smrgstatic void
55732001f49Smrgusage(void)
55832001f49Smrg{
55932001f49Smrg   printf("Usage:\n");
56032001f49Smrg   printf("  -display <displayname>  set the display to run on\n");
56132001f49Smrg   printf("  -info                   display OpenGL renderer info\n");
56232001f49Smrg}
56332001f49Smrg
56432001f49Smrg
56532001f49Smrgint
56632001f49Smrgmain(int argc, char *argv[])
56732001f49Smrg{
56832001f49Smrg   Display *x_dpy;
56932001f49Smrg   Window win;
57032001f49Smrg   EGLSurface egl_surf, egl_pbuf;
57132001f49Smrg   EGLContext egl_ctx;
57232001f49Smrg   EGLDisplay egl_dpy;
57332001f49Smrg   char *dpyName = NULL;
57432001f49Smrg   GLboolean printInfo = GL_FALSE;
57532001f49Smrg   EGLint egl_major, egl_minor;
57632001f49Smrg   int i;
57732001f49Smrg   const char *s;
57832001f49Smrg
57932001f49Smrg   for (i = 1; i < argc; i++) {
58032001f49Smrg      if (strcmp(argv[i], "-display") == 0) {
58132001f49Smrg         dpyName = argv[i+1];
58232001f49Smrg         i++;
58332001f49Smrg      }
58432001f49Smrg      else if (strcmp(argv[i], "-info") == 0) {
58532001f49Smrg         printInfo = GL_TRUE;
58632001f49Smrg      }
58732001f49Smrg      else {
58832001f49Smrg         usage();
58932001f49Smrg         return -1;
59032001f49Smrg      }
59132001f49Smrg   }
59232001f49Smrg
59332001f49Smrg   x_dpy = XOpenDisplay(dpyName);
59432001f49Smrg   if (!x_dpy) {
59532001f49Smrg      printf("Error: couldn't open display %s\n",
59632001f49Smrg	     dpyName ? dpyName : getenv("DISPLAY"));
59732001f49Smrg      return -1;
59832001f49Smrg   }
59932001f49Smrg
60032001f49Smrg   egl_dpy = eglGetDisplay(x_dpy);
60132001f49Smrg   if (!egl_dpy) {
60232001f49Smrg      printf("Error: eglGetDisplay() failed\n");
60332001f49Smrg      return -1;
60432001f49Smrg   }
60532001f49Smrg
60632001f49Smrg   if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
60732001f49Smrg      printf("Error: eglInitialize() failed\n");
60832001f49Smrg      return -1;
60932001f49Smrg   }
61032001f49Smrg
61132001f49Smrg   s = eglQueryString(egl_dpy, EGL_VERSION);
61232001f49Smrg   printf("EGL_VERSION = %s\n", s);
61332001f49Smrg
61432001f49Smrg   s = eglQueryString(egl_dpy, EGL_VENDOR);
61532001f49Smrg   printf("EGL_VENDOR = %s\n", s);
61632001f49Smrg
61732001f49Smrg   s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
61832001f49Smrg   printf("EGL_EXTENSIONS = %s\n", s);
61932001f49Smrg
62032001f49Smrg   s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
62132001f49Smrg   printf("EGL_CLIENT_APIS = %s\n", s);
62232001f49Smrg
62332001f49Smrg   make_x_window(x_dpy, egl_dpy,
62432001f49Smrg                 "render_tex", 0, 0, WinWidth, WinHeight,
62532001f49Smrg                 &win, &egl_ctx, &egl_surf);
62632001f49Smrg
62732001f49Smrg   egl_pbuf = make_pbuffer(x_dpy, egl_dpy, TexWidth, TexHeight);
62832001f49Smrg   if (!egl_pbuf) {
62932001f49Smrg      printf("Error: eglCreatePBufferSurface() failed\n");
63032001f49Smrg      return -1;
63132001f49Smrg   }
63232001f49Smrg
63332001f49Smrg   XMapWindow(x_dpy, win);
63432001f49Smrg   if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
63532001f49Smrg      printf("Error: eglMakeCurrent() failed\n");
63632001f49Smrg      return -1;
63732001f49Smrg   }
63832001f49Smrg
63932001f49Smrg   if (printInfo) {
64032001f49Smrg      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
64132001f49Smrg      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
64232001f49Smrg      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
64332001f49Smrg      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
64432001f49Smrg   }
64532001f49Smrg
64632001f49Smrg   init();
64732001f49Smrg
64832001f49Smrg   event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
64932001f49Smrg
65032001f49Smrg   eglDestroyContext(egl_dpy, egl_ctx);
65132001f49Smrg   eglDestroySurface(egl_dpy, egl_surf);
65232001f49Smrg   eglTerminate(egl_dpy);
65332001f49Smrg
65432001f49Smrg
65532001f49Smrg   XDestroyWindow(x_dpy, win);
65632001f49Smrg   XCloseDisplay(x_dpy);
65732001f49Smrg
65832001f49Smrg   return 0;
65932001f49Smrg}
660