GLX_EXT_texture_from_pixmap

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,

Are you sure you have a recent XServer which supports this extension?

Good question, Im running:

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

That’s the latest one…

Just use “glxinfo”. It lists all supported extensions.

Philipp

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

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).

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