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;
}