132001f49Smrg/*
232001f49Smrg * Simple demo for eglBindTexImage.  Based on xegl_tri.c by
332001f49Smrg *
432001f49Smrg * Copyright (C) 2008  Brian Paul   All Rights Reserved.
532001f49Smrg *
632001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
732001f49Smrg * copy of this software and associated documentation files (the "Software"),
832001f49Smrg * to deal in the Software without restriction, including without limitation
932001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1032001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1132001f49Smrg * Software is furnished to do so, subject to the following conditions:
1232001f49Smrg *
1332001f49Smrg * The above copyright notice and this permission notice shall be included
1432001f49Smrg * in all copies or substantial portions of the Software.
1532001f49Smrg *
1632001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1732001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1932001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2032001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2132001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2232001f49Smrg */
2332001f49Smrg
2432001f49Smrg/*
2532001f49Smrg * The spec says that eglBindTexImage supports only OpenGL ES context, but this
2632001f49Smrg * demo uses OpenGL context.  Keep in mind that this is non-standard.
2732001f49Smrg */
2832001f49Smrg
2932001f49Smrg#include <math.h>
3032001f49Smrg#include <stdlib.h>
3132001f49Smrg#include <stdio.h>
3232001f49Smrg#include <string.h>
3332001f49Smrg#include <X11/Xlib.h>
3432001f49Smrg#include <X11/Xutil.h>
3532001f49Smrg#include <X11/keysym.h>
3632001f49Smrg#include <GLES/gl.h>
3732001f49Smrg#include <EGL/egl.h>
3832001f49Smrg
3932001f49Smrgstatic EGLDisplay dpy;
4032001f49Smrgstatic EGLContext ctx_win, ctx_pbuf;
4132001f49Smrgstatic EGLSurface surf_win, surf_pbuf;
4232001f49Smrgstatic GLuint tex_pbuf;
4332001f49Smrg
4432001f49Smrgstatic GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
4532001f49Smrgstatic GLboolean blend = GL_TRUE;
4632001f49Smrgstatic GLuint color_flow;
4732001f49Smrg
4832001f49Smrgstatic void
4932001f49Smrgmake_pbuffer(int width, int height)
5032001f49Smrg{
5132001f49Smrg   static const EGLint config_attribs[] = {
5232001f49Smrg      EGL_RED_SIZE, 8,
5332001f49Smrg      EGL_GREEN_SIZE, 8,
5432001f49Smrg      EGL_BLUE_SIZE, 8,
5532001f49Smrg      EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
5632001f49Smrg      EGL_NONE
5732001f49Smrg   };
5832001f49Smrg   EGLint pbuf_attribs[] = {
5932001f49Smrg      EGL_WIDTH, width,
6032001f49Smrg      EGL_HEIGHT, height,
6132001f49Smrg      EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
6232001f49Smrg      EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
6332001f49Smrg      EGL_NONE
6432001f49Smrg   };
6532001f49Smrg   EGLConfig config;
6632001f49Smrg   EGLint num_configs;
6732001f49Smrg
6832001f49Smrg   if (!eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs) ||
6932001f49Smrg       !num_configs) {
7032001f49Smrg      printf("Error: couldn't get an EGL visual config for pbuffer\n");
7132001f49Smrg      exit(1);
7232001f49Smrg   }
7332001f49Smrg
7432001f49Smrg   ctx_pbuf = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
7532001f49Smrg   surf_pbuf = eglCreatePbufferSurface(dpy, config, pbuf_attribs);
7632001f49Smrg   if (surf_pbuf == EGL_NO_SURFACE) {
7732001f49Smrg      printf("failed to allocate pbuffer\n");
7832001f49Smrg      exit(1);
7932001f49Smrg   }
8032001f49Smrg}
8132001f49Smrg
8232001f49Smrgstatic void
8332001f49Smrguse_pbuffer(void)
8432001f49Smrg{
8532001f49Smrg   static int initialized;
8632001f49Smrg
8732001f49Smrg   eglMakeCurrent(dpy, surf_pbuf, surf_pbuf, ctx_pbuf);
8832001f49Smrg   if (!initialized) {
8932001f49Smrg      EGLint width, height;
9032001f49Smrg      GLfloat ar;
9132001f49Smrg
9232001f49Smrg      initialized = 1;
9332001f49Smrg
9432001f49Smrg      eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &width);
9532001f49Smrg      eglQuerySurface(dpy, surf_pbuf, EGL_WIDTH, &height);
9632001f49Smrg      ar = (GLfloat) width / (GLfloat) height;
9732001f49Smrg
9832001f49Smrg      glViewport(0, 0, (GLint) width, (GLint) height);
9932001f49Smrg
10032001f49Smrg      glMatrixMode(GL_PROJECTION);
10132001f49Smrg      glLoadIdentity();
10232001f49Smrg      glFrustumf(-ar, ar, -1, 1, 1.0, 10.0);
10332001f49Smrg
10432001f49Smrg      glMatrixMode(GL_MODELVIEW);
10532001f49Smrg      glLoadIdentity();
10632001f49Smrg
10732001f49Smrg      /* y-inverted */
10832001f49Smrg      glScalef(1.0, -1.0, 1.0);
10932001f49Smrg
11032001f49Smrg      glTranslatef(0.0, 0.0, -5.0);
11132001f49Smrg
11232001f49Smrg      glClearColor(0.2, 0.2, 0.2, 0.0);
11332001f49Smrg
11432001f49Smrg      glGenTextures(1, &tex_pbuf);
11532001f49Smrg   }
11632001f49Smrg}
11732001f49Smrg
11832001f49Smrgstatic void
11932001f49Smrgmake_window(Display *x_dpy, const char *name,
12032001f49Smrg            int x, int y, int width, int height,
12132001f49Smrg            Window *winRet)
12232001f49Smrg{
12332001f49Smrg   static const EGLint attribs[] = {
12432001f49Smrg      EGL_RED_SIZE, 8,
12532001f49Smrg      EGL_GREEN_SIZE, 8,
12632001f49Smrg      EGL_BLUE_SIZE, 8,
12732001f49Smrg      EGL_ALPHA_SIZE, 8,
12832001f49Smrg      EGL_DEPTH_SIZE, 8,
12932001f49Smrg      EGL_NONE
13032001f49Smrg   };
13132001f49Smrg
13232001f49Smrg   int scrnum;
13332001f49Smrg   XSetWindowAttributes attr;
13432001f49Smrg   unsigned long mask;
13532001f49Smrg   Window root;
13632001f49Smrg   Window win;
13732001f49Smrg   XVisualInfo *visInfo, visTemplate;
13832001f49Smrg   int num_visuals;
13932001f49Smrg   EGLConfig config;
14032001f49Smrg   EGLint num_configs, vid;
14132001f49Smrg
14232001f49Smrg   scrnum = DefaultScreen( x_dpy );
14332001f49Smrg   root = RootWindow( x_dpy, scrnum );
14432001f49Smrg
14532001f49Smrg   if (!eglChooseConfig(dpy, attribs, &config, 1, &num_configs) ||
14632001f49Smrg       !num_configs) {
14732001f49Smrg      printf("Error: couldn't get an EGL visual config\n");
14832001f49Smrg      exit(1);
14932001f49Smrg   }
15032001f49Smrg
15132001f49Smrg   if (!eglGetConfigAttrib(dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
15232001f49Smrg      printf("Error: eglGetConfigAttrib() failed\n");
15332001f49Smrg      exit(1);
15432001f49Smrg   }
15532001f49Smrg
15632001f49Smrg   /* The X window visual must match the EGL config */
15732001f49Smrg   visTemplate.visualid = vid;
15832001f49Smrg   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
15932001f49Smrg   if (!visInfo) {
16032001f49Smrg      printf("Error: couldn't get X visual\n");
16132001f49Smrg      exit(1);
16232001f49Smrg   }
16332001f49Smrg
16432001f49Smrg   /* window attributes */
16532001f49Smrg   attr.background_pixel = 0;
16632001f49Smrg   attr.border_pixel = 0;
16732001f49Smrg   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
16832001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
16932001f49Smrg   attr.override_redirect = 0;
17032001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
17132001f49Smrg
17232001f49Smrg   win = XCreateWindow( x_dpy, root, 0, 0, width, height,
17332001f49Smrg		        0, visInfo->depth, InputOutput,
17432001f49Smrg		        visInfo->visual, mask, &attr );
17532001f49Smrg
17632001f49Smrg   /* set hints and properties */
17732001f49Smrg   {
17832001f49Smrg      XSizeHints sizehints;
17932001f49Smrg      sizehints.x = x;
18032001f49Smrg      sizehints.y = y;
18132001f49Smrg      sizehints.width  = width;
18232001f49Smrg      sizehints.height = height;
18332001f49Smrg      sizehints.flags = USSize | USPosition;
18432001f49Smrg      XSetNormalHints(x_dpy, win, &sizehints);
18532001f49Smrg      XSetStandardProperties(x_dpy, win, name, name,
18632001f49Smrg                              None, (char **)NULL, 0, &sizehints);
18732001f49Smrg   }
18832001f49Smrg
18932001f49Smrg   ctx_win = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL );
19032001f49Smrg   if (!ctx_win) {
19132001f49Smrg      printf("Error: eglCreateContext failed\n");
19232001f49Smrg      exit(1);
19332001f49Smrg   }
19432001f49Smrg
19532001f49Smrg   surf_win = eglCreateWindowSurface(dpy, config, win, NULL);
19632001f49Smrg
19732001f49Smrg   XFree(visInfo);
19832001f49Smrg
19932001f49Smrg   *winRet = win;
20032001f49Smrg}
20132001f49Smrg
20232001f49Smrgstatic void
20332001f49Smrguse_window(void)
20432001f49Smrg{
20532001f49Smrg   static int initialized;
20632001f49Smrg
20732001f49Smrg   eglMakeCurrent(dpy, surf_win, surf_win, ctx_win);
20832001f49Smrg   if (!initialized) {
20932001f49Smrg      initialized = 1;
21032001f49Smrg      glEnable(GL_TEXTURE_2D);
21132001f49Smrg      glBindTexture(GL_TEXTURE_2D, tex_pbuf);
21232001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
21332001f49Smrg
21432001f49Smrg      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
21532001f49Smrg   }
21632001f49Smrg}
21732001f49Smrg
21832001f49Smrgstatic void
21932001f49Smrgdraw_triangle(void)
22032001f49Smrg{
22132001f49Smrg   static const GLfloat verts[3][2] = {
22232001f49Smrg      { -3, -3 },
22332001f49Smrg      {  3, -3 },
22432001f49Smrg      {  0,  3 }
22532001f49Smrg   };
22632001f49Smrg   GLfloat colors[3][4] = {
22732001f49Smrg      { 1, 0, 0, 1 },
22832001f49Smrg      { 0, 1, 0, 1 },
22932001f49Smrg      { 0, 0, 1, 1 }
23032001f49Smrg   };
23132001f49Smrg   GLint i;
23232001f49Smrg
23332001f49Smrg   /* flow the color */
23432001f49Smrg   for (i = 0; i < 3; i++) {
23532001f49Smrg      GLint first = (i + color_flow / 256) % 3;
23632001f49Smrg      GLint second = (first + 1) % 3;
23732001f49Smrg      GLint third = (second + 1) % 3;
23832001f49Smrg      GLfloat c = (color_flow % 256) / 256.0f;
23932001f49Smrg
24032001f49Smrg      c = c * c * c;
24132001f49Smrg      colors[i][first] = 1.0f - c;
24232001f49Smrg      colors[i][second] = c;
24332001f49Smrg      colors[i][third] = 0.0f;
24432001f49Smrg   }
24532001f49Smrg
24632001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
24732001f49Smrg
24832001f49Smrg   glVertexPointer(2, GL_FLOAT, 0, verts);
24932001f49Smrg   glColorPointer(4, GL_FLOAT, 0, colors);
25032001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
25132001f49Smrg   glEnableClientState(GL_COLOR_ARRAY);
25232001f49Smrg
25332001f49Smrg   glDrawArrays(GL_TRIANGLES, 0, 3);
25432001f49Smrg
25532001f49Smrg   glDisableClientState(GL_VERTEX_ARRAY);
25632001f49Smrg   glDisableClientState(GL_COLOR_ARRAY);
25732001f49Smrg}
25832001f49Smrg
25932001f49Smrgstatic void
26032001f49Smrgdraw_textured_cube(void)
26132001f49Smrg{
26232001f49Smrg   static const GLfloat verts[][2] = {
26332001f49Smrg      { -4, -4 },
26432001f49Smrg      {  4, -4 },
26532001f49Smrg      {  4,  4 },
26632001f49Smrg      { -4,  4 }
26732001f49Smrg   };
26832001f49Smrg   static const GLfloat colors[][4] = {
26932001f49Smrg      { 1, 1, 1, 0.5 },
27032001f49Smrg      { 1, 1, 1, 0.5 },
27132001f49Smrg      { 1, 1, 1, 0.5 },
27232001f49Smrg      { 1, 1, 1, 0.5 }
27332001f49Smrg   };
27432001f49Smrg   static const GLfloat texs[][2] = {
27532001f49Smrg      { 0, 0 },
27632001f49Smrg      { 1, 0 },
27732001f49Smrg      { 1, 1 },
27832001f49Smrg      { 0, 1 }
27932001f49Smrg   };
28032001f49Smrg   static const GLfloat xforms[6][4] = {
28132001f49Smrg      {   0, 0, 1, 0 },
28232001f49Smrg      {  90, 0, 1, 0 },
28332001f49Smrg      { 180, 0, 1, 0 },
28432001f49Smrg      { 270, 0, 1, 0 },
28532001f49Smrg      {  90, 1, 0, 0 },
28632001f49Smrg      { -90, 1, 0, 0 }
28732001f49Smrg   };
28832001f49Smrg   GLint i;
28932001f49Smrg
29032001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
29132001f49Smrg
29232001f49Smrg   if (blend) {
29332001f49Smrg      glDisable(GL_DEPTH_TEST);
29432001f49Smrg      glEnable(GL_BLEND);
29532001f49Smrg   } else {
29632001f49Smrg      glEnable(GL_DEPTH_TEST);
29732001f49Smrg      glDisable(GL_BLEND);
29832001f49Smrg   }
29932001f49Smrg
30032001f49Smrg   glVertexPointer(2, GL_FLOAT, 0, verts);
30132001f49Smrg   glColorPointer(4, GL_FLOAT, 0, colors);
30232001f49Smrg   glTexCoordPointer(2, GL_FLOAT, 0, texs);
30332001f49Smrg
30432001f49Smrg   glEnableClientState(GL_VERTEX_ARRAY);
30532001f49Smrg   glEnableClientState(GL_COLOR_ARRAY);
30632001f49Smrg   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
30732001f49Smrg
30832001f49Smrg   for (i = 0; i < 6; i++) {
30932001f49Smrg      glPushMatrix();
31032001f49Smrg      glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
31132001f49Smrg      glTranslatef(0, 0, 4.1);
31232001f49Smrg      glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
31332001f49Smrg      glPopMatrix();
31432001f49Smrg   }
31532001f49Smrg
31632001f49Smrg   glDisableClientState(GL_VERTEX_ARRAY);
31732001f49Smrg   glDisableClientState(GL_COLOR_ARRAY);
31832001f49Smrg   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
31932001f49Smrg}
32032001f49Smrg
32132001f49Smrgstatic void
32232001f49Smrgdraw(void)
32332001f49Smrg{
32432001f49Smrg   use_pbuffer();
32532001f49Smrg   draw_triangle();
32632001f49Smrg
32732001f49Smrg   use_window();
32832001f49Smrg
32932001f49Smrg   eglBindTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
33032001f49Smrg
33132001f49Smrg   glPushMatrix();
33232001f49Smrg   glRotatef(view_rotx, 1, 0, 0);
33332001f49Smrg   glRotatef(view_roty, 0, 1, 0);
33432001f49Smrg   glRotatef(view_rotz, 0, 0, 1);
33532001f49Smrg
33632001f49Smrg   draw_textured_cube();
33732001f49Smrg
33832001f49Smrg   glPopMatrix();
33932001f49Smrg
34032001f49Smrg   eglReleaseTexImage(dpy, surf_pbuf, EGL_BACK_BUFFER);
34132001f49Smrg}
34232001f49Smrg
34332001f49Smrg/* new window size or exposure */
34432001f49Smrgstatic void
34532001f49Smrgreshape(int width, int height)
34632001f49Smrg{
34732001f49Smrg   GLfloat ar = (GLfloat) width / (GLfloat) height;
34832001f49Smrg
34932001f49Smrg   use_window();
35032001f49Smrg
35132001f49Smrg   glViewport(0, 0, (GLint) width, (GLint) height);
35232001f49Smrg
35332001f49Smrg   glMatrixMode(GL_PROJECTION);
35432001f49Smrg   glLoadIdentity();
35532001f49Smrg   glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
35632001f49Smrg
35732001f49Smrg   glMatrixMode(GL_MODELVIEW);
35832001f49Smrg   glLoadIdentity();
35932001f49Smrg   glTranslatef(0.0, 0.0, -40.0);
36032001f49Smrg}
36132001f49Smrg
36232001f49Smrgstatic void
36332001f49Smrgevent_loop(Display *x_dpy, Window win)
36432001f49Smrg{
36532001f49Smrg   while (1) {
36632001f49Smrg      int redraw = 1;
36732001f49Smrg
36832001f49Smrg      if (XPending(x_dpy) > 0) {
36932001f49Smrg         XEvent event;
37032001f49Smrg         XNextEvent(x_dpy, &event);
37132001f49Smrg
37232001f49Smrg         switch (event.type) {
37332001f49Smrg         case Expose:
37432001f49Smrg            redraw = 1;
37532001f49Smrg            break;
37632001f49Smrg         case ConfigureNotify:
37732001f49Smrg            reshape(event.xconfigure.width, event.xconfigure.height);
37832001f49Smrg            break;
37932001f49Smrg         case KeyPress:
38032001f49Smrg            {
38132001f49Smrg               char buffer[10];
38232001f49Smrg               int r, code;
38332001f49Smrg               code = XLookupKeysym(&event.xkey, 0);
38432001f49Smrg               if (code == XK_Left) {
38532001f49Smrg                  view_roty += 5.0;
38632001f49Smrg               }
38732001f49Smrg               else if (code == XK_Right) {
38832001f49Smrg                  view_roty -= 5.0;
38932001f49Smrg               }
39032001f49Smrg               else if (code == XK_Up) {
39132001f49Smrg                  view_rotx += 5.0;
39232001f49Smrg               }
39332001f49Smrg               else if (code == XK_Down) {
39432001f49Smrg                  view_rotx -= 5.0;
39532001f49Smrg               }
39632001f49Smrg               else if (code == XK_b) {
39732001f49Smrg                  blend = !blend;
39832001f49Smrg               }
39932001f49Smrg               else {
40032001f49Smrg                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
40132001f49Smrg                        NULL, NULL);
40232001f49Smrg                  if (buffer[0] == 27) {
40332001f49Smrg                     /* escape */
40432001f49Smrg                     return;
40532001f49Smrg                  }
40632001f49Smrg               }
40732001f49Smrg            }
40832001f49Smrg            redraw = 1;
40932001f49Smrg            break;
41032001f49Smrg         default:
41132001f49Smrg            ; /*no-op*/
41232001f49Smrg         }
41332001f49Smrg      }
41432001f49Smrg
41532001f49Smrg      if (redraw) {
41632001f49Smrg         view_rotx += 1.0;
41732001f49Smrg         view_roty += 2.0;
41832001f49Smrg         view_rotz += 1.5;
41932001f49Smrg         color_flow += 20;
42032001f49Smrg         draw();
42132001f49Smrg         eglSwapBuffers(dpy, surf_win);
42232001f49Smrg      }
42332001f49Smrg   }
42432001f49Smrg}
42532001f49Smrg
42632001f49Smrgint
42732001f49Smrgmain(int argc, char *argv[])
42832001f49Smrg{
42932001f49Smrg   const int winWidth = 300, winHeight = 300;
43032001f49Smrg   Display *x_dpy;
43132001f49Smrg   Window win;
43232001f49Smrg   char *dpyName = NULL;
43332001f49Smrg   EGLint egl_major, egl_minor;
43432001f49Smrg   const char *s;
43532001f49Smrg
43632001f49Smrg   x_dpy = XOpenDisplay(dpyName);
43732001f49Smrg   if (!x_dpy) {
43832001f49Smrg      printf("Error: couldn't open display %s\n",
43932001f49Smrg	     dpyName ? dpyName : getenv("DISPLAY"));
44032001f49Smrg      return -1;
44132001f49Smrg   }
44232001f49Smrg
44332001f49Smrg   dpy = eglGetDisplay(x_dpy);
44432001f49Smrg   if (!dpy) {
44532001f49Smrg      printf("Error: eglGetDisplay() failed\n");
44632001f49Smrg      return -1;
44732001f49Smrg   }
44832001f49Smrg
44932001f49Smrg   if (!eglInitialize(dpy, &egl_major, &egl_minor)) {
45032001f49Smrg      printf("Error: eglInitialize() failed\n");
45132001f49Smrg      return -1;
45232001f49Smrg   }
45332001f49Smrg
45432001f49Smrg   s = eglQueryString(dpy, EGL_VERSION);
45532001f49Smrg   printf("EGL_VERSION = %s\n", s);
45632001f49Smrg
45732001f49Smrg   make_window(x_dpy, "color flow", 0, 0, winWidth, winHeight, &win);
45832001f49Smrg   make_pbuffer(winWidth, winHeight);
45932001f49Smrg
46032001f49Smrg   XMapWindow(x_dpy, win);
46132001f49Smrg
46232001f49Smrg   reshape(winWidth, winHeight);
46332001f49Smrg   event_loop(x_dpy, win);
46432001f49Smrg
46532001f49Smrg   glDeleteTextures(1, &tex_pbuf);
46632001f49Smrg
46732001f49Smrg   eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
46832001f49Smrg   eglTerminate(dpy);
46932001f49Smrg
47032001f49Smrg   XDestroyWindow(x_dpy, win);
47132001f49Smrg   XCloseDisplay(x_dpy);
47232001f49Smrg
47332001f49Smrg   return 0;
47432001f49Smrg}
475