Skip to content

Instantly share code, notes, and snippets.

@rikusalminen
Created July 26, 2011 12:24
Show Gist options
  • Save rikusalminen/1106628 to your computer and use it in GitHub Desktop.
Save rikusalminen/1106628 to your computer and use it in GitHub Desktop.
multithreaded glx
#include <stdbool.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <GL/gl.h>
GLXContext glXCreateContextAttribsARB(
Display *dpy, GLXFBConfig config,
GLXContext share_context, Bool direct,
const int *attrib_list);
static void paint(Display *display, GLXWindow surface, GLXContext context)
{
printf("glXMakeContextCurrent\n");
glXMakeContextCurrent(display, surface, surface, context);
printf("glXMakeContextCurrent done\n");
glClearColor(0.2, 0.4, 0.7, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
printf("glXSwapBuffers\n");
glXSwapBuffers(display, surface);
printf("glXSwapBuffers done\n");
printf("glXMakeContextCurrent NULL \n");
glXMakeContextCurrent(display, None, None, NULL);
printf("glXMakeContextCurrent NULL done\n");
}
static void go_do_stuff(Display *display, Window window, GLXWindow surface, GLXContext context)
{
XMapRaised(display, window);
XFlush(display);
XEvent event;
bool quit = false;
while(!quit)
{
XNextEvent(display, &event);
switch(event.type)
{
case Expose:
paint(display, surface, context);
break;
case KeyPress:
quit = 1;
break;
}
}
XUnmapWindow(display, window);
XFlush(display);
}
#include <pthread.h>
struct painter
{
Display *display;
Window window;
GLXWindow surface;
GLXContext context;
pthread_mutex_t mutex;
pthread_cond_t cond;
bool stopped;
bool dirty;
};
void* painter_loop(void *ptr)
{
struct painter *painter = (struct painter*)ptr;
bool stopped = false;
while(!stopped)
{
printf("waiting.... \n");
pthread_mutex_lock(&painter->mutex);
while(!painter->dirty && !painter->stopped)
pthread_cond_wait(&painter->cond, &painter->mutex);
stopped = painter->stopped;
painter->dirty = false;
pthread_mutex_unlock(&painter->mutex);
printf("waiting.... done\n");
if(!stopped)
{
printf("painting... \n");
paint(painter->display, painter->surface, painter->context);
printf("painting... done\n");
}
}
return painter;
}
static void go_do_stuff2(Display *display, Window window, GLXWindow surface, GLXContext context)
{
struct painter painter = { display, window, surface, context,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER,
false, false };
pthread_t painter_thread;
pthread_create(&painter_thread, NULL, painter_loop, &painter);
XMapRaised(display, window);
XFlush(display);
XEvent event;
bool quit = false;
while(!quit)
{
printf("waiting for event... \n");
XNextEvent(display, &event);
printf("waiting for event... done\n");
switch(event.type)
{
case MapNotify:
printf("MapNotify\n");
break;
case Expose:
printf("Expose\n");
pthread_mutex_lock(&painter.mutex);
painter.dirty = true;
pthread_cond_signal(&painter.cond);
pthread_mutex_unlock(&painter.mutex);
break;
case KeyPress:
printf("KeyPress\n");
pthread_mutex_lock(&painter.mutex);
painter.stopped = true;
pthread_cond_signal(&painter.cond);
pthread_mutex_unlock(&painter.mutex);
quit = 1;
break;
}
}
XUnmapWindow(display, window);
XFlush(display);
void *painter_return;
pthread_join(painter_thread, &painter_return);
}
static void go_window(
Display *display,
int screen_num,
GLXFBConfig fb_config,
Visual *visual,
int depth,
Colormap colormap)
{
XSetWindowAttributes attrib;
attrib.colormap = colormap;
attrib.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask;
unsigned long attrib_mask = CWColormap | CWEventMask;
Window window = XCreateWindow(
display,
RootWindow(display, screen_num),
0, 0, 150, 150,
0,
depth,
InputOutput,
visual,
attrib_mask,
&attrib);
GLXWindow surface =
glXCreateWindow(display, fb_config, window, 0);
const int context_attributes[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
#ifdef DEBUG
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
#endif
None, None };
GLXContext context =
glXCreateContextAttribsARB(
display,
fb_config,
NULL, // shared context
True, // direct
context_attributes);
if(true) go_do_stuff2(display, window, surface, context);
else go_do_stuff(display, window, surface, context);
glXDestroyContext(display, context);
glXDestroyWindow(display, surface);
XDestroyWindow(display, window);
}
static void go_glx(Display *display, int screen_num)
{
const int fb_attributes[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 0,
GLX_GREEN_SIZE, 0,
GLX_BLUE_SIZE, 0,
GLX_ALPHA_SIZE, 0,
GLX_DEPTH_SIZE, 0,
GLX_STENCIL_SIZE, 0,
GLX_SAMPLE_BUFFERS, 0,
GLX_SAMPLES, 0,
None, None };
int num_configs;
GLXFBConfig* fb_configs =
glXChooseFBConfig(
display, screen_num,
fb_attributes, &num_configs);
GLXFBConfig fb_config = fb_configs[0];
XFree(fb_configs);
XVisualInfo *vi = glXGetVisualFromFBConfig(display, fb_config);
Visual *visual = vi->visual;
int depth = vi->depth;
XFree(vi);
Colormap colormap =
XCreateColormap(
display,
RootWindow(display, screen_num),
visual,
AllocNone);
go_window(display, screen_num, fb_config, visual, depth, colormap);
XFreeColormap(display, colormap);
return;
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
XInitThreads();
Display *display = XOpenDisplay(NULL);
int screen_num = DefaultScreen(display);
go_glx(display, screen_num);
XCloseDisplay(display);
printf("done\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment