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