PDA

View Full Version : GLX_EXT_texture_from_pixmap



bobGL
04-28-2006, 07:02 PM
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, &amp;num_configs);
if (fbconfig == NULL) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
exit(1);
}

/* window attributes */
visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
if (!visinfo) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
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, &amp;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, &amp;sizehints);
XSetStandardProperties(dpy, win, name, name,
None, (char **)NULL, 0, &amp;sizehints);
}

ctx = glXCreateContext( dpy, visinfo, NULL, False );
if (!ctx) {
printf("Error: glXCreateContext failed\n");
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, &amp;num_configs);
if (fbconfig == NULL) {
printf("Error: couldn't get an RGB, Double-buffered fb config\n");
exit(1);
}

/* window attributes */
visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);

if (!visinfo) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
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\n");
// 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, &amp;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\n", getenv("DISPLAY"));
return -1;
}

make_window(dpy, "tex-test", 0, 0, 300, 300, &amp;win, &amp;ctx);
XMapWindow(dpy, win);
glXMakeCurrent(dpy, win, ctx);

//printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
//printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
//printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
//printf("GL_EXTENSIONS = %s\n", (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,

sijuober
04-29-2006, 12:52 AM
Are you sure you have a recent XServer which supports this extension?

bobGL
04-29-2006, 04:05 AM
Good question, Im running:

Display 0:0 [The X.Org Foundation 11.0 70000000]

That's the latest one...

PkK
04-29-2006, 04:12 AM
Just use "glxinfo". It lists all supported extensions.

Philipp

bobGL
04-29-2006, 04:17 AM
When I do glxinfo, I cannot see GLX_EXT_texture_from_pixmap, but if I use:

DISPLAY=:0 LD_LIBRARY_PATH=/usr/lib/ glxinfo

I can see it in the GLX extensions, and when I run my test prog I use:

DISPLAY=:0 LD_LIBRARY_PATH=/usr/lib/ ./tex-test

Same thing happen:

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

sijuober
04-30-2006, 01:59 PM
It don't seems that your XServer has this extension. If you call glxinfo like the way you do, I think it uses the extensions from the recompiled Mesa Library. I think you will also have to recompile your XServer (fetching the newest from cvs which has this extension).