Shared OpenGL context SDL2

Hi,

is it possible to create shared GL context using SDL2?. I only see SDL_GL_CreateContext(window) which creates a ctx for a specific window but I would like to be able to do say SDL_GL_CreateSharedContext(context) which shares "lists’ (http://msdn.microsoft.com/pl-pl/library/windows/desktop/dd374390(v=vs.85).aspx) with original context. Also, SDL_GL_MakeCurrent() takes window parameter, why? Making context current means creating it current for the execution thread that calls it and is not related to window.

I am porting a game from Qt4 to SDL2 and it uses background thread to do GL texture upload using a shared context created with the help of Qt.

Thanks! Works like a charm. Not being able to create a context without making it current is unfortunate but I really am happy SDL has portable solution for sharing mechanism. I am aware of issues you mentioned - as I said we alread have think implemented using Qt’s GL objects. Fortunately windowing / input was abstracted away enough that it took 1 day to make it work with SDL2 instead of Qt 4.8. Ony thing missing was background texture uploading and now we have it too. Thanks again.

Yes you can do that.

First you have to enable shared context in SDL_GL attributes. The last context created will be active in the creator thread. So create the glRenderContext last, or after creating use SDL_GL_MakeCurrent to make it current. This will also make sure that the glThreadContext is not active in this thread and can be activated in another one. (Only one can be current in a thread)

To call SDL_GL_MakeCurrent in the thread you just use the pointer to your main windows.

A example below: Note that a real loading thread would not get closed until the program is. Because MakeCurrent is very expensive. Better paused it by a Semaphore and then throw work at it when you need something done.

Code:
SDL_GLContext glRenderContext, glThreadContext;
SDL_Window *mainWindow;
SDL_atomic_t stuffIsReady;

int loadGlInBackground( void *ptr )
{
SDL_GL_MakeCurrent(mainWindow, glThreadContext);

//Do some fancy loading gl stuff in the background...

//It is very important in shared contexts to make sure the driver is done with all Objects before signaling other threads that they can use them!
GLsync fenceId = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
GLenum result;
while(true)
{
	glClientWaitSync(fenceId, GL_SYNC_FLUSH_COMMANDS_BIT, GLuint64(5000000000)); //5 Second timeout
	if(result != GL_TIMEOUT_EXPIRED) break; //we ignore timeouts and wait until all OpenGL commands are processed!
}

SDL_AtomicIncRef(&stuffIsReady);

//im not 100% sure what happens to a context that still is active when a thread gets closed.
//But you can't call SDL_GL_DeleteContext on it!
//So I just unbind it from this thread and call SDL_GL_DeleteContext in the main thread at closing.
SDL_GL_MakeCurrent(mainWindow, NULL);
return 0;

}

int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
cout << "Unable to initialize SDL: " << SDL_GetError() << endl;
return -1;
}
else
{
cout << “sdl init ok” << endl;
}
mainWindow = SDL_CreateWindow(“SDL2 window”, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

if(mainWindow == NULL){
	std::cout << "Could not create window: " << SDL_GetError() << std::endl;
	return -1;
}

SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
glThreadContext = SDL_GL_CreateContext(mainWindow);
glRenderContext = SDL_GL_CreateContext(mainWindow);

SDL_Thread *thread = SDL_CreateThread( loadGlInBackground, "testThread", (void *)NULL);
while(true)
{
	//Event handling and all the fancy rendering...
	if (SDL_AtomicGet(&stuffIsReady) == 1)
	{
		//now the opengl stuff loaded by the thread can be used
	}
}

int threadReturnValue;
SDL_WaitThread(thread, &threadReturnValue);
SDL_GL_DeleteContext(glThreadContext);
SDL_GL_DeleteContext(glRenderContext);
SDL_DestroyWindow(mainWindow);
SDL_Quit();
return 0;

}