Hello everyone.
I’m programming a flight simulator app and I have data for the whole world.
Then, there is a lot of textures and geometry to load so I made a background thread that dynamically load all that data depending on my position on Earth.
Since I’m using SOIL to load my textures, I need to create a 2nd context for that background thread that will share OpenGL data with the main thread’s context.
I use GLX to manage my window and I didn’t find any example of this. I just know which functions to use but I’m facing some problems.
Here’s what I do:
- init XLib thread support
- create the foreground context
- create the background context with the foreground one as shareList
- make the foreground context current for the rendering thread
- create the loader thread passing a structure containing the Display, the Window and the background context
- in the loader thread, make the background context current
It crashes with a segfault on the last step, when I call glXMakeCurrent with the Display, the Window and the thread context…
I’m doing something wrong but I don’t know what and can’t find solutions on forums.
Do you have any idea ?
Thank you for your help !
Here’s my full code :
main
Display *dpy;
Window win;
GLXContext foregroundCtx, backgroundCtx;
int32_t main(int32_t argc, char** argv)
{
//init my own stuff (data paths, ini...)
initVisualSystem(argc, argv);
//create the window
initXDisplay();
glewInit();
//init my openGL stuff and create background thread
init(dpy, &backgroundCtx, &win, argc, argv);
event_loop(dpy, win);
cleanVisualSystem();
//XClean
glXDestroyContext(dpy, foregroundCtx);
glXDestroyContext(dpy, backgroundCtx);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return 0;
}
initXDisplay
void initXDisplay()
{
XInitThreads();
dpy = XOpenDisplay(NULL);
if (!dpy)
{
cerr << "Error: couldn't open display" << endl;
exit(1);
}
uint32_t width = renderer.getView()->getWidth();
uint32_t height = renderer.getView()->getHeight();
make_window(dpy, "XN3", 0, 0, width, height, &win, &foregroundCtx, &backgroundCtx);
XMapWindow(dpy, win);
[b]glXMakeCurrent(dpy, win, foregroundCtx);[/b]
if (FULLSCREEN)
{
makeFullscreen(dpy, win);
}
hideCursor(dpy, win);
}
static void make_window( Display *dpy, const char *name,
int x, int y, int width, int height,
Window *winRet, GLXContext *foregroundCtxRet, GLXContext *backgroundCtxRet)
{
if(VSYNC)
putenv( (char *) "__GL_SYNC_TO_VBLANK=1" );
else
putenv( (char *) "__GL_SYNC_TO_VBLANK=0" );
int attrib[] = { GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 24,
GLX_SAMPLE_BUFFERS , 1*MULTISAMPLING, // <-- MSAA
GLX_SAMPLES , 4*MULTISAMPLING, // <-- MSAA
None };
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
Window win;
GLXContext foregroundCtx, backgroundCtx;
XVisualInfo *visinfo;
scrnum = DefaultScreen( dpy );
root = RootWindow( dpy, scrnum );
visinfo = glXChooseVisual( dpy, scrnum, attrib );
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 | KeyReleaseMask | ButtonPress | PointerMotionMask;
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);
}
foregroundCtx = glXCreateContext( dpy, visinfo, NULL, True );
if (!foregroundCtx) {
printf("Error: glXCreateContext for mainCtx failed
");
exit(1);
}
backgroundCtx = glXCreateContext( dpy, visinfo, foregroundCtx, True );
if (!backgroundCtx) {
printf("Error: glXCreateContext for threadCtx failed
");
exit(1);
}
XFree(visinfo);
*winRet = win;
*foregroundCtxRet = foregroundCtx;
*backgroundCtxRet = backgroundCtx;
}
init
void init(Display *dpy, GLXContext* backgroundCtx, Window* win, int32_t argc, char** argv)
{
//init my OpenGL stuff (shaders...)
...
SLoaderThread sLoaderThread;
sLoaderThread.pBV3DManager = renderer.getBV3DManager();
sLoaderThread.dpy = dpy;
sLoaderThread.backgroundCtx = backgroundCtx;
sLoaderThread.win = win;
pthread_create(&loaderThread, NULL, startLoaderThread, (void*)&sLoaderThread);
}
struct SLoaderThread
{
CBV3DManager* pBV3DManager; //manages my world geometries and textures
Display *dpy;
GLXContext* backgroundCtx;
Window* win;
};
void* startLoaderThread(void* data)
{
SLoaderThread* pSLoaderThread = (SLoaderThread*)data;
glXMakeCurrent(pSLoaderThread->dpy, *pSLoaderThread->win, *pSLoaderThread->backgroundCtx); //Crashes here with a segfault
while(1)
{
pSLoaderThread->pBV3DManager->updateZones();
}
return NULL;
}