PBuffer + GLX_ATI_render_texture problem

Hi,

This thread reminded me of the GLX_ATI_render_texture extension.
So I tried to modify the fgl_glxgears version that comes with the ati drivers to support the GLX_ATI_render_texture extension but I failed to get it working. The program terminates with the following error messages:
“X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
Major opcode of failed request: 14 (X_GetGeometry)
Resource id in failed request: 0x0
Serial number of failed request: 43
Current serial number in output stream: 43”

Here is the modified source of fgl_glxgears.c.
I marked the lines that I changed with comments, search for “now:” to find them.
I’d be thankful for any help.

/*
 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/* $XFree86: xc/programs/glxgears/glxgears.c,v 1.2 2001/04/03 15:56:26 dawes Exp $ */

/*
 * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
 * Port by Brian Paul  23 March 2001
 *
 * Command line options:
 *    -info      print GL implementation information
 *    -help      print usage information
 */

/*
 * Modifing person:      Markus Neff, ATI Research GmbH
 * Date of modification: 2001/11/09
 * Latest change:        2002-Oct-10
 *
 * This is a modified version of the original "glxgears" demo, which demonstrates 
 * the usage of pixel buffers (pbuffers) whith an ATI Fire GL graphics board and 
 * a patched version of libGL.so.
 * Some other code in this example (the cube stuff) is taken from an OGL tutorial
 * by Jeff Molofee.
 *
 * The three gear wheels are rendered to a pbuffer instead of to a window. These 
 * images are loaded to texture memory to be mapped on the four faces of
 * a cube.
 *
 * The user can press the arrow keys to change his position relative to the
 * gears.
 */

//#define USE_GLU

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#ifdef USE_GLU
#include <GL/glu.h>
#endif
#include <GL/gl.h>
#include <GL/glx.h>
/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
#include <GL/glxATI.h>
/* change end ////////////////////////////////////////////////////////////////////////////////// */

#include <sys/time.h>
#include <unistd.h>

/* return current time (in seconds) */
static int
current_time(void)
{
   struct timeval tv;
   struct timezone tz;
   (void) gettimeofday(&tv, &tz);
   return (int) tv.tv_sec;
}

#ifndef M_PI
#define M_PI 3.14159265
#endif


/* dimensions of texture and pbuffer */
#define TEXTURE_SIZE_XY       256
#define TEXTURE_BORDER_WIDTH  3
/* now: changed: ////////////////////////////////////////////////////////////////////////////////// */
#define PBUFFER_WIDTH_HEIGHT  256 /*TEXTURE_SIZE_XY - 2*TEXTURE_BORDER_WIDTH*/
/* change end ////////////////////////////////////////////////////////////////////////////////// */


/* for simplicity, i take global var. for X and GLX resources */
static Display *dpy        = NULL;
static Window win          = 0;
static GLXPbuffer pbuf     = 0;
static GLXContext ctx_win  = NULL,
                  ctx_pbuf = NULL;
/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
static PFNGLXBINDTEXIMAGEATIPROC pglXBindTexImageATI = NULL;
static PFNGLXRELEASETEXIMAGEATIPROC pglXReleaseTexImageATI = NULL;
static PFNGLXDRAWABLEATTRIBATIPROC pglXDrawableAttribATI = NULL;
/* change end ////////////////////////////////////////////////////////////////////////////////// */

/* gears stuff */
static GLfloat view_rotx = 20.0,
               view_roty = 30.0,
               view_rotz = 0.0;
static GLint   gear1     = 0,
               gear2     = 0,
               gear3     = 0;
static GLfloat angle     = 0.0;

/* cube stuff */
static GLfloat rotX = 0;    /* X Rotation */
static GLfloat rotY = 0;    /* Y Rotation */
static GLfloat rotZ = 0;    /* Z Rotation */
static GLuint  texture[1];  /* Storage For One Texture */

static int loopcount = 0;   /* Counter for looping a fixed number of frames */

/*
 *  Draw a gear wheel. You'll probably want to call this function when
 *  building a display list since we do a lot of trig here.
 * 
 *  Input:  inner_radius - radius of hole at center
 *          outer_radius - radius at center of teeth
 *          width        - width of gear
 *          teeth        - number of teeth
 *          tooth_depth  - depth of tooth
 */
static void
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
     GLint teeth, GLfloat tooth_depth)
{
   GLint i;
   GLfloat r0, r1, r2;
   GLfloat angle, da;
   GLfloat u, v, len;

   r0 = inner_radius;
   r1 = outer_radius - tooth_depth / 2.0;
   r2 = outer_radius + tooth_depth / 2.0;

   da = 2.0 * M_PI / teeth / 4.0;

   glShadeModel(GL_FLAT);

   glNormal3f(0.0, 0.0, 1.0);

   /* draw front face */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;
      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      if (i < teeth) {
         glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
	     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
             width * 0.5);
      }
   }
   glEnd();

   /* draw front sides of teeth */
   glBegin(GL_QUADS);
   da = 2.0 * M_PI / teeth / 4.0;
   for (i = 0; i < teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
		 width * 0.5);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
		 width * 0.5);
   }
   glEnd();

   glNormal3f(0.0, 0.0, -1.0);

   /* draw back face */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      if (i < teeth) {
          glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 
              -width * 0.5);
          glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      }
   }
   glEnd();

   /* draw back sides of teeth */
   glBegin(GL_QUADS);
   da = 2.0 * M_PI / teeth / 4.0;
   for (i = 0; i < teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
          -width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
          -width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
   }
   glEnd();

   /* draw outward faces of teeth */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i < teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;

      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
      u = r2 * cos(angle + da) - r1 * cos(angle);
      v = r2 * sin(angle + da) - r1 * sin(angle);
      len = sqrt(u * u + v * v);
      u /= len;
      v /= len;
      glNormal3f(v, -u, 0.0);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
      glNormal3f(cos(angle), sin(angle), 0.0);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
          width * 0.5);
      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
          -width * 0.5);
      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
      glNormal3f(v, -u, 0.0);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
          width * 0.5);
      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
          -width * 0.5);
      glNormal3f(cos(angle), sin(angle), 0.0);
   }

   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);

   glEnd();

   glShadeModel(GL_SMOOTH);

   /* draw inside radius cylinder */
   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= teeth; i++) {
      angle = i * 2.0 * M_PI / teeth;
      glNormal3f(-cos(angle), -sin(angle), 0.0);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
   }
   glEnd();
}


static void drawGears(void)
{
   glXMakeCurrent(dpy, pbuf, ctx_pbuf);

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   glPushMatrix();
   glRotatef(view_rotx, 1.0, 0.0, 0.0);
   glRotatef(view_roty, 0.0, 1.0, 0.0);
   glRotatef(view_rotz, 0.0, 0.0, 1.0);

   glPushMatrix();
   glTranslatef(-3.0, -2.0, 0.0);
   glRotatef(angle, 0.0, 0.0, 1.0);
   glCallList(gear1);
   glPopMatrix();

   glPushMatrix();
   glTranslatef(3.1, -2.0, 0.0);
   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
   glCallList(gear2);
   glPopMatrix();

   glPushMatrix();
   glTranslatef(-3.1, 4.2, 0.0);
   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
   glCallList(gear3);
   glPopMatrix();

   glPopMatrix();
   glFlush();

/* now: changed, removed: ////////////////////////////////////////////////////////////////////// */
   /*glBindTexture(GL_TEXTURE_2D, texture[0]);
   glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
                       TEXTURE_BORDER_WIDTH, TEXTURE_BORDER_WIDTH, 
                       0, 0, PBUFFER_WIDTH_HEIGHT, PBUFFER_WIDTH_HEIGHT);*/
/* change end ////////////////////////////////////////////////////////////////////////////////// */
}


static void drawCube(void)
{
    glXMakeCurrent(dpy, win, ctx_win);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    glRotatef(rotX, 1.0f, 0.0f, 0.0f);  /* rotate on the X axis */
    glRotatef(rotY, 0.0f, 1.0f, 0.0f);  /* rotate on the Y axis */
    glRotatef(rotZ, 0.0f, 0.0f, 1.0f);  /* rotate on the Z axis */

    glBindTexture(GL_TEXTURE_2D, texture[0]);   /* select our  texture */
/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
    pglXBindTexImageATI(dpy, pbuf, GLX_FRONT_LEFT_ATI);
/* change end ////////////////////////////////////////////////////////////////////////////////// */

    glBegin(GL_QUADS);
        /* front face */
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f); 
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        /* back face */
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f); 
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        /* right face */
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f); 
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        /* left face */
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f); 
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        /* top face */
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(1.0f, 1.0f, 1.0f); 
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-1.0f, 1.0f, 1.0f);
        /* bottom face */
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f); 
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
    glEnd();

/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
    pglXReleaseTexImageATI(dpy, pbuf, GLX_FRONT_LEFT_ATI);
/* change end ////////////////////////////////////////////////////////////////////////////////// */

    /* change the rotation angles */
    rotX += 0.3f;
    rotY += 0.2f;
    rotZ += 0.4f;

    glXSwapBuffers(dpy, win);
}


/* function called when pbuffer is created to setup scene */
static void reshapeGears(unsigned int width, unsigned int height)
{
   GLfloat h = (GLfloat) height / (GLfloat) width;

   glViewport(0, 0, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -40.0);
}

#ifndef USE_GLU
/* the below functions are directly originating from
   Mesa-4.0.4/src-glu/glu.c with file version 4.0.2 */

static void
frustum(GLdouble left, GLdouble right,
        GLdouble bottom, GLdouble top,
        GLdouble nearval, GLdouble farval)
{
   GLdouble x, y, a, b, c, d;
   GLdouble m[16];

   x = (2.0 * nearval) / (right - left);
   y = (2.0 * nearval) / (top - bottom);
   a = (right + left) / (right - left);
   b = (top + bottom) / (top - bottom);
   c = -(farval + nearval) / ( farval - nearval);
   d = -(2.0 * farval * nearval) / (farval - nearval);

#define M(row,col)  m[col*4+row] 
   M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
   M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
   M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
   M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
#undef M 

   glMultMatrixd(m);
}

static
void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
   GLdouble xmin, xmax, ymin, ymax;

   ymax = zNear * tan(fovy * M_PI / 360.0);
   ymin = -ymax;
   xmin = ymin * aspect;
   xmax = ymax * aspect;

   /* don't call glFrustum() because of error semantics (covglu) */
   frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
#endif /* USE_GLU */

/* function called when our window is resized */
static void reshapeCube(unsigned int width, unsigned int height)
{
    /* Prevent A Divide By Zero If The Window Is Too Small */
    if (height == 0)
        height = 1;
    /* Reset The Current Viewport And Perspective Transformation */
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
}


static void init(void)
{
   static GLfloat pos[4]   = { 5.0, 5.0, 10.0, 0.0 };
   static GLfloat red[4]   = { 0.8, 0.1, 0.0, 1.0 };
   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
   static GLfloat blue[4]  = { 0.2, 0.2, 1.0, 1.0 };
   unsigned char *whiteImage = NULL;
   
   
   /* create a "white" RGBA image as initial texture */
   whiteImage = malloc(TEXTURE_SIZE_XY*TEXTURE_SIZE_XY*4);
   if (NULL == whiteImage) {
       fprintf(stderr, "Error: not enough memory => bye ...
");
       exit(1);
   }
   memset(whiteImage, 255, TEXTURE_SIZE_XY*TEXTURE_SIZE_XY*4);

   /* stuff for window */
   glXMakeCurrent(dpy, win, ctx_win);

   glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
   glClearDepth(1.0f);
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_TEXTURE_2D);
   glShadeModel(GL_SMOOTH);
   glDepthFunc(GL_LEQUAL);
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
   glCullFace(GL_BACK);
   glEnable(GL_CULL_FACE);
   glPixelStorei(GL_UNPACK_ALIGNMENT,1);

   /* create the texture */
   glGenTextures(1, &texture[0]);
   glBindTexture(GL_TEXTURE_2D, texture[0]);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 
                TEXTURE_SIZE_XY, TEXTURE_SIZE_XY,
                0, GL_RGBA, GL_UNSIGNED_BYTE, whiteImage);
   free(whiteImage);
   

   /* stuff for pbuffer */
   glXMakeCurrent(dpy, pbuf, ctx_pbuf);

   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
   glClearColor(0.2f, 0.2f, 0.2f, 0.2f);

   glLightfv(GL_LIGHT0, GL_POSITION, pos);
   glEnable(GL_CULL_FACE);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
   reshapeGears(PBUFFER_WIDTH_HEIGHT, PBUFFER_WIDTH_HEIGHT);

   /* make the gears */
   gear1 = glGenLists(1);
   glNewList(gear1, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
   gear(1.0, 4.0, 1.0, 20, 0.7);
   glEndList();

   gear2 = glGenLists(1);
   glNewList(gear2, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
   gear(0.5, 2.0, 2.0, 10, 0.7);
   glEndList();

   gear3 = glGenLists(1);
   glNewList(gear3, GL_COMPILE);
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
   gear(1.3, 2.0, 0.5, 10, 0.7);
   glEndList();

   glEnable(GL_NORMALIZE);
}


/*
 * Create an RGBA, double-buffered window.
 */
static void make_window(const char *name, int x, int y, int width, int height)
{
   int attrib[] = { GLX_RGBA,
		    GLX_RED_SIZE, 1,
		    GLX_GREEN_SIZE, 1,
		    GLX_BLUE_SIZE, 1,
		    GLX_DOUBLEBUFFER,
		    GLX_DEPTH_SIZE, 1,
		    None };
   int scrnum;
   XSetWindowAttributes attr;
   unsigned long mask;
   Window root;
   XVisualInfo *visinfo;

   scrnum = DefaultScreen( dpy );
   root   = RootWindow( dpy, scrnum );

   visinfo = glXChooseVisual( dpy, scrnum, attrib );
   if (!visinfo) {
      printf("Error: couldn't get an RGBA, Double-buffered visual
");
      exit(1);
   }

   /* window attributes */
   attr.background_pixel = 0;
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

   win = XCreateWindow( dpy, root, 0, 0, width, height,
		        0, visinfo->depth, InputOutput,
		        visinfo->visual, mask, &attr );

   /* set hints and properties */
   {
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = width;
      sizehints.height = height;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(dpy, win, &sizehints);
      XSetStandardProperties(dpy, win, name, name,
                              None, (char **)NULL, 0, &sizehints);
   }

   ctx_win = glXCreateContext( dpy, visinfo, NULL, GL_TRUE );
   if (!ctx_win) {
      printf("Error: glXCreateContext failed
");
      exit(1);
   }

   XFree(visinfo);

   glXMakeCurrent(dpy, win, ctx_win);
}


/*
 * Create an RGBA, non double-buffered pbuffer.
 */
static void make_pbuffer(int width, int height)
{
   int scrnum;
   GLXFBConfig *fbconfig;
   XVisualInfo *visinfo;
   int nitems;

/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
   pglXBindTexImageATI = (PFNGLXBINDTEXIMAGEATIPROC)glXGetProcAddress("glXBindTexImageATI");
   pglXReleaseTexImageATI = (PFNGLXRELEASETEXIMAGEATIPROC)glXGetProcAddress("glXReleaseTexImageATI");
   pglXDrawableAttribATI = (PFNGLXDRAWABLEATTRIBATIPROC)glXGetProcAddress("glXDrawableAttribATI");
/* change end ////////////////////////////////////////////////////////////////////////////////// */

   int attrib[] = {
      GLX_DOUBLEBUFFER,  False,
      GLX_RED_SIZE,      1,
      GLX_GREEN_SIZE,    1,
      GLX_BLUE_SIZE,     1,
      GLX_DEPTH_SIZE,    1,
      GLX_RENDER_TYPE,   GLX_RGBA_BIT,
      GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
      GLX_BIND_TO_TEXTURE_RGBA_ATI, True,
/* change end ////////////////////////////////////////////////////////////////////////////////// */
      None
   };
   int pbufAttrib[] = {
      GLX_PBUFFER_WIDTH,   width,
      GLX_PBUFFER_HEIGHT,  height,
      GLX_LARGEST_PBUFFER, False,
/* now: changed, added: //////////////////////////////////////////////////////////////////////// */
      GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI,
      GLX_TEXTURE_TARGET_ATI, GLX_TEXTURE_2D_ATI,
/* change end ////////////////////////////////////////////////////////////////////////////////// */
      None
   };


   scrnum   = DefaultScreen( dpy );

   fbconfig = glXChooseFBConfig(dpy,
                                scrnum,
                                attrib,
                                &nitems);
   if (NULL == fbconfig) {
      fprintf(stderr,"Error: couldn't get fbconfig
");
      exit(1);
   }

   pbuf = glXCreatePbuffer(dpy, fbconfig[0], pbufAttrib);

   visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
   if (!visinfo) {
      fprintf(stderr, "Error: couldn't get an RGBA, double-buffered visual
");
      exit(1);
   }

   ctx_pbuf = glXCreateContext( dpy, visinfo, ctx_win, GL_TRUE );
   if (!ctx_pbuf) {
      fprintf(stderr, "Error: glXCreateContext failed
");
      exit(1);
   }

   XFree(fbconfig);
   XFree(visinfo);
}


static void event_loop(void)
{
   while (1) {
      while (XPending(dpy) > 0) {
         XEvent event;
         XNextEvent(dpy, &event);
         switch (event.type) {
         case Expose:
            /* we'll redraw below */
	        break;
         case ConfigureNotify:
            glXMakeCurrent(dpy, win, ctx_win);
	        reshapeCube(event.xconfigure.width, event.xconfigure.height);
	        break;
         case KeyPress:
            {
               char buffer[10];
               int r, code;
               code = XLookupKeysym(&event.xkey, 0);
               if (code == XK_Left) {
                  view_roty += 5.0;
               }
               else if (code == XK_Right) {
                  view_roty -= 5.0;
               }
               else if (code == XK_Up) {
                  view_rotx += 5.0;
               }
               else if (code == XK_Down) {
                  view_rotx -= 5.0;
               }
               else {
                  r = XLookupString(&event.xkey, buffer, sizeof(buffer),
                                    NULL, NULL);
                  if (buffer[0] == 27) {
                     /* escape */
                     return;
                  }
               }
            }
         }
      }

      /* next frame */
      angle += 2.0;

      drawGears();
      drawCube();

      /* calc framerate */
      {
         static int t0 = -1;
         static int frames = 0;
         int t = current_time();

         if (t0 < 0)
            t0 = t;

         frames++;

         if (t - t0 >= 5.0) {
            GLfloat seconds = t - t0;
            GLfloat fps = frames / seconds;
            printf("%d frames in %3.1f seconds = %6.3f FPS
", frames, seconds,
                   fps);
            t0 = t;
            frames = 0;
         }
      }

      if (loopcount > 0) {
         loopcount -= 1;
         if (loopcount < 1) {
            /* escape */
            return;
         }
      }
   }
}


static 
void my_print_usage(void)
{
    fprintf(stdout,
           "
"
           "Usage:
"
           "------
"
           "
"
           "-display <dpy>    redirect output to display <dpy>
"
           "-loop <n>         loop demo n frames then exit, n > 0
"
           "-help             print this information
"
           "-info             print GLX information (vendor etc.) to stdout
"
           "
");
}


int
main(int argc, char *argv[])
{
   int i;
   char *dpyName       = NULL;
   GLboolean printInfo = GL_FALSE;

   /* parse arguments */
   if (argc > 5) {
       fprintf(stdout,
               "%s: wrong number of arguments specified ...
",argv[0]);
       my_print_usage();
       exit(1);
   }

   for (i = 1; i < argc; i++) {
      if (strcmp(argv[i], "-display") == 0) {
         i++;
         if (i >= argc) {
            my_print_usage();
            exit(1);
         }
         dpyName = argv[i];
      }
      else if (strcmp(argv[i], "-loop") == 0) {
         i++;
         if (i >= argc) {
            my_print_usage();
            exit(1);
         }
         loopcount = atoi (argv[i]);
         if (loopcount <= 0) {
            my_print_usage();
            exit(1);
         }
      }
      else if (strcmp(argv[i], "-info") == 0) {
         printInfo = GL_TRUE;
      }
      else if (strcmp(argv[i], "-help") == 0) {
         my_print_usage();
         exit(1);
      }
      else {
         my_print_usage();
         exit(1);
      }
   }

   /* open the display */
   dpy = XOpenDisplay(dpyName);
   if (!dpy) {
      printf("Error: couldn't open display %s
", dpyName);
      return -1;
   }

   /* setup and initial window, pbuffer and texture */
   make_window("PBuffer GLXGears", 0, 0, 600, 600);
   XMapWindow(dpy, win);

   if (printInfo) {
      printf("GL_RENDERER   = %s
", (char *) glGetString(GL_RENDERER));
      printf("GL_VERSION    = %s
", (char *) glGetString(GL_VERSION));
      printf("GL_VENDOR     = %s
", (char *) glGetString(GL_VENDOR));
      printf("GL_EXTENSIONS = %s
", (char *) glGetString(GL_EXTENSIONS));
   }

   make_pbuffer(PBUFFER_WIDTH_HEIGHT, PBUFFER_WIDTH_HEIGHT);
   
   init();

   /* start processing of X events */
   event_loop();

   /* clean up */
   glXDestroyContext(dpy, ctx_win);
   XDestroyWindow(dpy, win);

   glXDestroyContext(dpy, ctx_pbuf);
   glXDestroyPbuffer(dpy, pbuf);

   XCloseDisplay(dpy);

   return 0;
}

Just a guess, try adding
{GLX_MIPMAP_TEXTURE_ATI, true/false}
to your pbuffer attribute list…

Originally posted by skynet:
Just a guess, try adding
{GLX_MIPMAP_TEXTURE_ATI, true/false}
to your pbuffer attribute list…

Thanks for the suggestion but the X_GetGeometry error seemed to come from the NPOT sized pbuffer.

But now I have another problem.
The program immediately exits with a seg fault.
When I use a debugger I can step to the first call of glXMakeCurrent(dpy, pbuf, ctx_pbuf) then the whole X server freezes.
So for some reason I cannot make the pbuffer context current.

I’m having simliar problems with either render to texture and floating point pbuffers (using the mysterious GLX_ATI_pixel_format_float extension that has not been described anywhere yet and only defines one value). I gave up after numerous SEGFAULT, crashes, etc…

Please let me know when/if you get it right.

With the new driver[1] released yesterday the program works now.

[1] http://www.ati.com/support/driver.html

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.