Skip to content

Instantly share code, notes, and snippets.

@larsbergstrom
Created December 11, 2013 22:19
Show Gist options
  • Save larsbergstrom/7919498 to your computer and use it in GitHub Desktop.
Save larsbergstrom/7919498 to your computer and use it in GitHub Desktop.
Sharing a pixmap across threads with/without separate XDisplay pointer
gcc visual.c -g -lGL -lX11 -lGLU -lpthread && ./a.out
Off-thread visual
Creating off-thread
Making current off-thread
Making current NONE off-thread
Destroying off-thread
Re-creating glx pixmap on-thread
larsberg@thor:~/tmp$
Off-thread visual
Creating off-thread
Making current off-thread
X Error of failed request: BadPixmap (invalid Pixmap parameter)
Major opcode of failed request: 153 (GLX)
Minor opcode of failed request: 13 (X_GLXCreateGLXPixmap)
Resource id in failed request: 0x3a00004
Serial number of failed request: 19
Current serial number in output stream: 20
larsberg@thor:~/tmp$
#include <math.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <GL/glx.h>
#include <GL/gl.h>
static int attributeList[] = {GLX_RGBA,
GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
static Bool WaitForNotify(Display *d,XEvent *e,char *arg) {
return(e->type == MapNotify) && (e->xmap.window == (Window)arg);
}
Pixmap pix;
int use_separate_display = 1;
void *off_thread(void *main_dpy) {
Display *dpy;
XVisualInfo *vi;
GLXPixmap px;
GLXContext cx;
printf("Off-thread visual\n");
if (use_separate_display) {
/* kaboom */
dpy = XOpenDisplay(0);
} else {
/* works fine */
dpy = (Display *)main_dpy;
}
vi = glXChooseVisual(dpy,DefaultScreen(dpy),attributeList);
if (vi == NULL)
{
printf("couldn't find the visual \n");
return 0;
}
/* create a GLX context */
if (!(cx = glXCreateContext(dpy,vi,0,GL_FALSE)))
{
fprintf(stderr, "glXGetContext failed!\n");
return 0;
}
printf("Creating off-thread\n");
px = glXCreateGLXPixmap (dpy, vi, pix);
printf("Making current off-thread\n");
if (!(glXMakeCurrent(dpy,px,cx)))
{
fprintf(stderr, "second glXMakeCurrent failed (pixmap)!\n");
return 0;
}
printf("Making current NONE off-thread\n");
if (!(glXMakeCurrent(dpy,None,None)))
{
fprintf(stderr, "glXMakeCurrent failed (None)!\n");
return 0;
}
printf("Destroying off-thread\n");
glXDestroyGLXPixmap(dpy, px);
return 0;
}
int main(int argc,char**argv)
{
Display *dpy;
XVisualInfo *vi;
GLXContext cx;
Colormap cmap;
XSetWindowAttributes swa;
Window win;
GLXPixmap px;
XEvent event;
GC gc;
XInitThreads();
/* get a connection */
dpy = XOpenDisplay(0);
/* get an appropriate visual */
vi = glXChooseVisual(dpy,DefaultScreen(dpy),attributeList);
if (vi == NULL)
{
printf("couldn't find the visual \n");
return 0;
}
/* create a GLX context */
if (!(cx = glXCreateContext(dpy,vi,0,GL_FALSE)))
{
fprintf(stderr, "glXGetContext failed!\n");
return 0;
}
/* create color map */
if (!(cmap = XCreateColormap(dpy,RootWindow(dpy,vi->screen),
vi->visual,AllocNone)))
{
fprintf(stderr, "XCreateColormap failed!\n");
return 0;
}
/* create window */
swa.colormap = cmap;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
win = XCreateWindow(dpy,RootWindow(dpy,vi->screen),0,0,500,500,0,vi->depth,
InputOutput,vi->visual,CWBorderPixel|CWColormap|CWEventMask,
&swa);
XMapWindow(dpy,win);
XIfEvent(dpy,&event,WaitForNotify,(char*)win);
pix = XCreatePixmap (dpy, RootWindow(dpy, vi->screen), 500, 500,
vi->depth);
{
pthread_t thread;
pthread_create(&thread, NULL, off_thread, (void*)dpy);
pthread_join(thread, NULL);
}
gc = XCreateGC (dpy, pix, 0, NULL);
printf("Re-creating glx pixmap on-thread\n");
px = glXCreateGLXPixmap (dpy, vi, pix);
/* connect the context to the glx pixmap */
if (!(glXMakeCurrent(dpy,px,cx)))
{
fprintf(stderr, "glXMakeCurrent failed (pixmap)!\n");
return 0;
}
glColor3f(1.0, 0.0, 0.0);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
glXWaitGL();
XCopyArea (dpy, pix, win, gc, 0, 0, 500, 500, 0, 0);
XFlush(dpy);
sleep(5);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment