#include #include #include #include #include #include #include #include Display *Dpy = NULL; Window Win = 0; GLXContext Context1, Context2; int ExitFlag = GL_FALSE; volatile int thread = 1; void createCtxes() { int attrib[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None }; int scrnum; XSetWindowAttributes attr; unsigned long mask; Window root; XVisualInfo *visinfo; int width = 300, height = 300; scrnum = DefaultScreen(Dpy); root = RootWindow(Dpy, scrnum); visinfo = glXChooseVisual(Dpy, scrnum, attrib); if (!visinfo) { printf("Unable to find RGB, Z, double-buffered visual"); exit(0); } /* 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); if (!Win) { printf("Couldn't create window"); exit(0); } { XSizeHints sizehints; sizehints.x = 0; sizehints.y = 0; sizehints.width = width; sizehints.height = height; sizehints.flags = USSize | USPosition; XSetNormalHints(Dpy, Win, &sizehints); XSetStandardProperties(Dpy, Win, "glthreads", "glthreads", None, (char **)NULL, 0, &sizehints); } Context1 = glXCreateContext(Dpy, visinfo, NULL, True); if (!Context1) { printf("Couldn't create GLX context"); exit(0); } Context2 = glXCreateContext(Dpy, visinfo, Context1, True); if (!Context2) { printf("Couldn't create GLX context"); exit(0); } XMapWindow(Dpy, Win); XSync(Dpy, 0); } static void event_loop(Display *dpy) { XEvent event; int i; while (!ExitFlag) { XNextEvent(dpy, &event); switch (event.type) { case KeyPress: /* tell all threads to exit */ ExitFlag = GL_TRUE; /*printf("exit draw_loop %d\n", wt->Index);*/ return; default: /*no-op*/ ; } } } static void * thread1_function(void *p) { if(glXMakeCurrent(Dpy, Win, Context1) != GL_TRUE) { printf("glXMakeCurrent error\n"); return(0); } glEnable(GL_DEPTH_TEST); glColor3f(0, 0, 1); glDrawBuffer(GL_BACK); while(!ExitFlag) { printf("draw1\n"); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBegin(GL_QUADS); glVertex3f(0, 0, 0); glVertex3f(0, 1, 0); glVertex3f(1, 1, 0); glVertex3f(1, 0, 0); glEnd(); printf("done draw1\n"); thread = 2; while(thread != 1 && !ExitFlag) usleep(1); if(ExitFlag) return; printf("Flip\n"); glFinish(); glXSwapBuffers(Dpy, Win); } return NULL; } static void * thread2_function(void *p) { if(glXMakeCurrent(Dpy, Win, Context2) != GL_TRUE) { printf("glXMakeCurrent error\n"); return(0); } glColor3f(1,0, 0); glDrawBuffer(GL_BACK); glEnable(GL_DEPTH_TEST); while(!ExitFlag) { while(thread != 2 && !ExitFlag) usleep(1);; if(ExitFlag) return; printf("draw2\n"); glBegin(GL_QUADS); glVertex3f(0.5, 0.5, 0.1); glVertex3f(0.5, -1, 0.1); glVertex3f(-1, -1, 0.1); glVertex3f(-1, 0, 0.1); glEnd(); printf("done draw2\n"); glFinish(); thread = 1; } return NULL; } int main(int argc, char *argv[]) { pthread_t Thread1, Thread2; XInitThreads(); Dpy = XOpenDisplay(NULL); if (!Dpy) { fprintf(stderr, "Unable to open display %s\n", NULL); return -1; } createCtxes(); pthread_create(&Thread1, NULL, thread1_function, NULL); pthread_create(&Thread1, NULL, thread2_function, NULL); event_loop(Dpy); return 0; }