Im trying to use this new extension, I found this sweet little example that show how to use it:
/*
gcc $(pkg-config --cflags --libs cairo) -lGL -o tex-test tex-test.c
*/
#define GLX_GLXEXT_PROTOTYPES 1
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "/usr/include/GL/gl.h"
#include "/usr/include/GL/glx.h"
#include "/usr/include/GL/glxext.h"
#include <X11/Xlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
static GLuint TexObj[2];
static GLfloat Angle = 0.0f;
static const int texture_width = 30, texture_height = 77;
static void
make_window(Display *dpy, const char *name,
int x, int y, int width, int height,
Window *winRet, GLXContext *ctxRet)
{
static const int attribs[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER, GL_TRUE,
GLX_DEPTH_SIZE, 1,
None
};
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
Window win;
GLXContext ctx;
XVisualInfo *visinfo;
GLXFBConfig *fbconfig;
int num_configs;
scrnum = DefaultScreen(dpy);
root = RootWindow(dpy, scrnum);
fbconfig = glXChooseFBConfig(dpy, scrnum, attribs, &num_configs);
if (fbconfig == NULL) {
printf("Error: couldn't get an RGB, Double-buffered visual
");
exit(1);
}
/* window attributes */
visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
if (!visinfo) {
printf("Error: couldn't get an RGB, 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 = glXCreateContext( dpy, visinfo, NULL, False );
if (!ctx) {
printf("Error: glXCreateContext failed
");
exit(1);
}
XFree(visinfo);
*winRet = win;
*ctxRet = ctx;
}
static void draw( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glColor3f( 1.0, 1.0, 1.0 );
/* draw first polygon */
glPushMatrix();
glTranslatef( -1.0, 0.0, 0.0 );
glRotatef( Angle, 0.0, 0.0, 1.0 );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, TexObj[0] );
glBegin( GL_POLYGON );
glTexCoord2i( 0, 0 ); glVertex2f( -1.0, -1.0 );
glTexCoord2i( texture_width, 0 ); glVertex2f( 1.0, -1.0 );
glTexCoord2i( texture_width, texture_height ); glVertex2f( 1.0, 1.0 );
glTexCoord2i( 0, texture_height ); glVertex2f( -1.0, 1.0 );
glEnd();
glPopMatrix();
/* draw second polygon */
glPushMatrix();
glTranslatef( 1.0, 0.0, 0.0 );
glRotatef( Angle-90.0, 0.0, 1.0, 0.0 );
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, TexObj[1] );
glBegin( GL_POLYGON );
glTexCoord2i( 0, 0 ); glVertex2f( -1.0, -1.0 );
glTexCoord2i( texture_width, 0 ); glVertex2f( 1.0, -1.0 );
glTexCoord2i( texture_width, texture_height ); glVertex2f( 1.0, 1.0 );
glTexCoord2i( 0, texture_height ); glVertex2f( -1.0, 1.0 );
glEnd();
glPopMatrix();
}
/* new window size or exposure */
static void reshape( int width, int height )
{
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/* glOrtho( -3.0, 3.0, -3.0, 3.0, -10.0, 10.0 );*/
glFrustum( -2.0, 2.0, -2.0, 2.0, 6.0, 20.0 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef( 0.0, 0.0, -8.0 );
}
static void draw_texture(cairo_surface_t *surface,
const char *text, int width, int height)
{
cairo_t *cr;
cairo_pattern_t *gradient;
cr = cairo_create(surface);
gradient = cairo_pattern_create_linear(width / 4, 0,
3 * width / 4, height);
cairo_pattern_add_color_stop_rgb(gradient, 0, 0, 0, 0);
cairo_pattern_add_color_stop_rgb(gradient, 1, 0.2, 0.2, 0.5);
cairo_set_source(cr, gradient);
cairo_pattern_destroy(gradient);
cairo_paint(cr);
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_move_to(cr, 0, 0);
cairo_line_to(cr, width, 0);
cairo_line_to(cr, width, height);
cairo_line_to(cr, 0, height);
cairo_close_path(cr);
cairo_stroke(cr);
cairo_move_to(cr, width / 10, height / 2);
cairo_set_font_size (cr, width / 3);
cairo_select_font_face (cr, "sans",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_show_text(cr, text);
cairo_destroy(cr);
}
static void create_image_texture(GLuint name, const char *text)
{
GLuint tex[texture_width * texture_height];
cairo_surface_t *surface;
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, name );
assert(glIsTexture(name));
surface = cairo_image_surface_create_for_data ((unsigned char *) tex,
CAIRO_FORMAT_ARGB32,
texture_width,
texture_height,
texture_width * 4);
draw_texture(surface, text, texture_width, texture_height);
glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, 3,
texture_width, texture_height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, tex );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT );
cairo_surface_destroy(surface);
}
static void create_pixmap_texture(Display *dpy, Window win,
GLuint name, const char *text)
{
static const int attribs[] = {
//GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
#if 0
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE
#endif
None
};
static const int pixmap_attribs[] = {
#if 0
GLX_TEXTURE_TARGET_ARB, GLX_TEXTURE_2D_EXT,
#endif
None
};
cairo_surface_t *surface;
GLXPixmap glxpixmap;
Pixmap pixmap;
XVisualInfo *visinfo;
GLXFBConfig *fbconfig;
int num_configs;
int scrnum;
Bool status;
glBindTexture( GL_TEXTURE_RECTANGLE_ARB, name );
assert(glIsTexture(name));
scrnum = DefaultScreen(dpy);
fbconfig = glXChooseFBConfig(dpy, scrnum, attribs, &num_configs);
if (fbconfig == NULL) {
printf("Error: couldn't get an RGB, Double-buffered fb config
");
exit(1);
}
/* window attributes */
visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
if (!visinfo) {
printf("Error: couldn't get an RGB, Double-buffered visual
");
exit(1);
}
pixmap = XCreatePixmap(dpy, win, texture_width, texture_height, 24);
surface = cairo_xlib_surface_create (dpy, pixmap, visinfo->visual,
texture_width, texture_height);
draw_texture(surface, text, texture_width, texture_height);
glxpixmap = glXCreatePixmap (dpy, fbconfig[0], pixmap, pixmap_attribs);
status = glXBindTexImageEXT (dpy, glxpixmap, GLX_FRONT_LEFT_EXT, NULL);
//if (status != GL_TRUE) {
// printf("Error: couldn't bind pixmap to texture
");
// exit(1);
//}
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT );
cairo_surface_destroy(surface);
}
static void init(Display *dpy, Window win)
{
glDisable( GL_DITHER );
/* Setup texturing */
glEnable( GL_TEXTURE_RECTANGLE_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
/* generate texture object IDs */
glGenTextures( 2, TexObj );
#if 0
//create_image_texture(TexObj[0], "A");
//create_image_texture(TexObj[1], "B");
#else
create_pixmap_texture(dpy, win, TexObj[0], "OKI");
create_pixmap_texture(dpy, win, TexObj[1], "DOKI");
#endif
}
static void
event_loop(Display *dpy, Window win)
{
while (1) {
while (XPending(dpy) > 0) {
XEvent event;
XNextEvent(dpy, &event);
switch (event.type) {
case Expose:
/* we'll redraw below */
break;
case ConfigureNotify:
reshape(event.xconfigure.width, event.xconfigure.height);
}
}
draw();
glXSwapBuffers(dpy, win);
Angle += 0.05;
}
}
int main( int argc, char *argv[] )
{
Display *dpy;
Window win;
GLXContext ctx;
dpy = XOpenDisplay(NULL);
if (!dpy) {
printf("Error: couldn't open display %s
", getenv("DISPLAY"));
return -1;
}
make_window(dpy, "tex-test", 0, 0, 300, 300, &win, &ctx);
XMapWindow(dpy, win);
glXMakeCurrent(dpy, win, ctx);
//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));
init(dpy, win);
event_loop(dpy, win);
glXDestroyContext(dpy, ctx);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return 0;
}
I can compile it fine but when I run it I got the following error (runtime):
X Error of failed request: GLXUnsupportedPrivateRequest
Major opcode of failed request: 145 (GLX)
Minor opcode of failed request: 16 (X_GLXVendorPrivate)
Serial number of failed request: 65
Current serial number in output stream: 68
After some digging I found that the problem comes from this call:
glXBindTexImageEXT
Is there a way to fix this problem? I even recompile MESA from CVS to make sure… still the same problem…
Someone have an idea?
Tks,