#include #include #include #include #include #define GLX_GLXEXT_PROTOTYPES #include #include #include #include #include #define SEMAPHORE "/foobar-42" #define T "/foobar-43" #define R "/foobar-44" #define PERIOD 10 static int attr_list[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None }; static Display *dpy = NULL; static int screen = -1; static Window window = None; static GLXContext ctx = None; static sem_t *semaphore = SEM_FAILED; static sem_t *r = SEM_FAILED; static sem_t *t = SEM_FAILED; static int width = 400; static int height = 400; static void acquire_context (void) { sem_wait (semaphore); glXMakeCurrent (dpy, window, ctx); } static void release_context (void) { glXMakeCurrent (dpy, None, None); /*XSync (dpy, False);*/ sem_post (semaphore); } static gboolean draw_triangle (void) { static GLfloat rotTri = 0.0f; sem_wait (t); acquire_context (); glLoadIdentity (); glTranslatef (-1.5f, 0.0f, -6.0f); glRotatef (rotTri, 0.0f, 1.0f, 0.0f); glBegin (GL_TRIANGLES); /* front of pyramid */ glColor3f (1.0f, 0.0f, 0.0f); glVertex3f (0.0f, 1.0f, 0.0f); glColor3f (0.0f, 0.0f, 1.0f); glVertex3f (-1.0f, -1.0f, 1.0f); glColor3f (0.0f, 1.0f, 0.0f); glVertex3f (1.0f, -1.0f, 1.0f); /* right side of pyramid */ glColor3f (1.0f, 0.0f, 0.0f); glVertex3f (0.0f, 1.0f, 0.0f); glColor3f (0.0f, 1.0f, 0.0f); glVertex3f (1.0f, -1.0f, 1.0f); glColor3f( 0.0f, 0.0f, 1.0f); glVertex3f (1.0f, -1.0f, -1.0f); /* back of pyramid */ glColor3f (1.0f, 0.0f, 0.0f); glVertex3f (0.0f, 1.0f, 0.0f); glColor3f (0.0f, 0.0f, 1.0f); glVertex3f (1.0f, -1.0f, -1.0f); glColor3f (0.0f, 1.0f, 0.0f); glVertex3f (-1.0f, -1.0f, -1.0f); /* left side of pyramid */ glColor3f (1.0f, 0.0f, 0.0f); glVertex3f (0.0f, 1.0f, 0.0f); glColor3f (0.0f, 1.0f, 0.0f); glVertex3f (-1.0f, -1.0f, -1.0f); glColor3f (0.0f, 0.0f, 1.0f); glVertex3f (-1.0f, -1.0f, 1.0f); glEnd (); rotTri += 0.2f; release_context (); g_usleep (10000); return TRUE; } static gboolean draw_rectangle () { static GTimer *timer = NULL; static GLfloat rotQuad = 0.0f; if (!timer) timer = g_timer_new (); sem_wait (r); acquire_context (); glLoadIdentity (); glTranslatef (1.5f, 0.0f, -7.0f); glRotatef (rotQuad, 1.0f, 0.0f, 0.0f); glBegin (GL_QUADS); /* top of cube */ glColor3f (0.0f, 1.0f, 0.0f); glVertex3f (1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, 1.0f, 1.0f); glVertex3f (1.0f, 1.0f, 1.0f); /* bottom of cube */ glColor3f (1.0f, 0.5f, 0.0f); glVertex3f (1.0f, -1.0f, 1.0f); glVertex3f (-1.0f, -1.0f, 1.0f); glVertex3f (-1.0f, -1.0f, -1.0f); glVertex3f (1.0f, -1.0f, -1.0f); /* front of cube */ glColor3f (1.0f, 0.0f, 0.0f); glVertex3f (1.0f, 1.0f, 1.0f); glVertex3f (-1.0f, 1.0f, 1.0f); glVertex3f (-1.0f, -1.0f, 1.0f); glVertex3f (1.0f, -1.0f, 1.0f); /* back of cube */ glColor3f (1.0f, 1.0f, 0.0f); glVertex3f (-1.0f, 1.0f, -1.0f); glVertex3f (1.0f, 1.0f, -1.0f); glVertex3f (1.0f, -1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, -1.0f); /* right side of cube */ glColor3f (1.0f, 0.0f, 1.0f); glVertex3f (1.0f, 1.0f, -1.0f); glVertex3f (1.0f, 1.0f, 1.0f); glVertex3f (1.0f, -1.0f, 1.0f); glVertex3f (1.0f, -1.0f, -1.0f); /* left side of cube */ glColor3f (0.0f, 1.0f, 1.0f); glVertex3f (-1.0f, 1.0f, 1.0f); glVertex3f (-1.0f, 1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, -1.0f); glVertex3f (-1.0f, -1.0f, 1.0f); glEnd (); rotQuad -= 0.15f; release_context (); g_usleep (10000); return TRUE; } static gboolean swap_buffers (void) { acquire_context (); glXSwapBuffers (dpy, window); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); release_context (); sem_post (t); sem_post (r); return TRUE; } GLXContext init_glx (int width, int height) { XVisualInfo *vi; Colormap cmap; XSetWindowAttributes wa = {0}; GLXContext ctx; vi = glXChooseVisual (dpy, screen, attr_list); assert (vi); ctx = glXCreateContext (dpy, vi, 0, GL_FALSE); cmap = XCreateColormap (dpy, RootWindow (dpy, vi->screen), vi->visual, AllocNone); wa.colormap = cmap; wa.border_pixel = 0; wa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; window = XCreateWindow (dpy, RootWindow (dpy, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &wa); XMapRaised (dpy, window); return ctx; } static void resize (int width, int height) { glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluPerspective (45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); glMatrixMode (GL_MODELVIEW); } static void init_gl (void) { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } int main (int argc, char **argv) { XEvent event; Bool shared; GMainLoop *main_loop; dpy = XOpenDisplay (NULL); assert (dpy); screen = DefaultScreen (dpy); semaphore = sem_open (SEMAPHORE, O_CREAT, 0644, 0); if (semaphore == SEM_FAILED) { perror ("sem_open"); return 1; } r = sem_open (R, O_CREAT, 0644, 0); if (r == SEM_FAILED) { perror ("sem_open"); return 1; } t = sem_open (T, O_CREAT, 0644, 0); if (t == SEM_FAILED) { perror ("sem_open"); return 1; } main_loop = g_main_loop_new (NULL, FALSE); if (argc > 2) { ctx = glXImportContextEXT (dpy, atoi (argv[1])); printf ("Got shared context %i\n", (int)glXGetContextIDEXT (ctx)); shared = True; window = atoi (argv[2]); if (argc > 3 && strcmp (argv[3], "triangle") == 0) g_idle_add ((GSourceFunc)draw_triangle, NULL); else g_idle_add ((GSourceFunc)draw_rectangle, NULL); } else { ctx = init_glx (width, height); printf ("Created context %i and window %i\n", (int)glXGetContextIDEXT (ctx), (int)window); glXMakeCurrent (dpy, window, ctx); init_gl (); resize (width, height); glFlush (); shared = False; g_timeout_add (30, (GSourceFunc)swap_buffers, NULL); release_context (); } g_main_loop_run (main_loop); return 0; }