Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Fixed bug 1946 - OpenGL contexts in threads
Browse files Browse the repository at this point in the history
The SDL OpenGL context code is now properly thread aware.  There are two new functions which return the current OpenGL window and context for the current thread.

There are still places in the cocoa driver where the OpenGL context needs to be updated when the view changes.  These will need a different solution and still use the last globally set context to avoid changing behavior.
  • Loading branch information
slouken committed Jul 12, 2013
1 parent 5358299 commit 3c23dc8
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 21 deletions.
10 changes: 10 additions & 0 deletions include/SDL_video.h
Expand Up @@ -889,6 +889,16 @@ extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *
extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window * window,
SDL_GLContext context);

/**
* \brief Get the currently active OpenGL window.
*/
extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);

/**
* \brief Get the currently active OpenGL context.
*/
extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void);

/**
* \brief Set the swap interval for the current OpenGL context.
*
Expand Down
3 changes: 2 additions & 1 deletion src/video/SDL_sysvideo.h
Expand Up @@ -302,7 +302,8 @@ struct SDL_VideoDevice
/* Cache current GL context; don't call the OS when it hasn't changed. */
SDL_Window *current_glwin;
SDL_GLContext current_glctx;
SDL_threadID current_glthread;
SDL_TLSID current_glwin_tls;
SDL_TLSID current_glctx_tls;

/* * * */
/* Data private to this driver */
Expand Down
55 changes: 40 additions & 15 deletions src/video/SDL_video.c
Expand Up @@ -500,6 +500,9 @@ SDL_VideoInit(const char *driver_name)
_this->gl_config.profile_mask = 0;
_this->gl_config.share_with_current_context = 0;

_this->current_glwin_tls = SDL_TLSCreate();
_this->current_glctx_tls = SDL_TLSCreate();

/* Initialize the video subsystem */
if (_this->VideoInit(_this) < 0) {
SDL_VideoQuit();
Expand Down Expand Up @@ -2738,7 +2741,8 @@ SDL_GL_CreateContext(SDL_Window * window)
/* Creating a context is assumed to make it current in the SDL driver. */
_this->current_glwin = window;
_this->current_glctx = ctx;
_this->current_glthread = SDL_ThreadID();
SDL_TLSSet(_this->current_glwin_tls, window, NULL);
SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);

return ctx;
}
Expand All @@ -2747,7 +2751,12 @@ int
SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
{
int retval;
SDL_threadID thread = SDL_ThreadID();

if (window == SDL_GL_GetCurrentWindow() &&
ctx == SDL_GL_GetCurrentContext()) {
/* We're already current. */
return 0;
}

if (!ctx) {
window = NULL;
Expand All @@ -2759,26 +2768,42 @@ SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
}
}

if ((window == _this->current_glwin) && (ctx == _this->current_glctx) && (thread == _this->current_glthread)) {
retval = 0; /* we're already current. */
} else {
retval = _this->GL_MakeCurrent(_this, window, ctx);
if (retval == 0) {
_this->current_glwin = window;
_this->current_glctx = ctx;
_this->current_glthread = thread;
}
retval = _this->GL_MakeCurrent(_this, window, ctx);
if (retval == 0) {
_this->current_glwin = window;
_this->current_glctx = ctx;
SDL_TLSSet(_this->current_glwin_tls, window, NULL);
SDL_TLSSet(_this->current_glctx_tls, ctx, NULL);
}

return retval;
}

SDL_Window *
SDL_GL_GetCurrentWindow(void)
{
if (!_this) {
SDL_UninitializedVideo();
return NULL;
}
return (SDL_Window *)SDL_TLSGet(_this->current_glwin_tls);
}

SDL_GLContext
SDL_GL_GetCurrentContext(void)
{
if (!_this) {
SDL_UninitializedVideo();
return NULL;
}
return (SDL_GLContext)SDL_TLSGet(_this->current_glctx_tls);
}

int
SDL_GL_SetSwapInterval(int interval)
{
if (!_this) {
return SDL_UninitializedVideo();
} else if (_this->current_glctx == NULL) {
} else if (SDL_GL_GetCurrentContext() == NULL) {
return SDL_SetError("No OpenGL context has been made current");
} else if (_this->GL_SetSwapInterval) {
return _this->GL_SetSwapInterval(_this, interval);
Expand All @@ -2792,7 +2817,7 @@ SDL_GL_GetSwapInterval(void)
{
if (!_this) {
return 0;
} else if (_this->current_glctx == NULL) {
} else if (SDL_GL_GetCurrentContext() == NULL) {
return 0;
} else if (_this->GL_GetSwapInterval) {
return _this->GL_GetSwapInterval(_this);
Expand Down Expand Up @@ -2820,7 +2845,7 @@ SDL_GL_DeleteContext(SDL_GLContext context)
return;
}

if (_this->current_glctx == context) {
if (SDL_GL_GetCurrentContext() == context) {
SDL_GL_MakeCurrent(NULL, NULL);
}

Expand Down
2 changes: 1 addition & 1 deletion src/video/cocoa/SDL_cocoaopengl.m
Expand Up @@ -178,7 +178,7 @@
}

if (_this->gl_config.share_with_current_context) {
share_context = (NSOpenGLContext*)(_this->current_glctx);
share_context = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
}

context = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:share_context];
Expand Down
2 changes: 1 addition & 1 deletion src/video/windows/SDL_windowsopengl.c
Expand Up @@ -535,7 +535,7 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window)
HGLRC context, share_context;

if (_this->gl_config.share_with_current_context) {
share_context = (HGLRC)(_this->current_glctx);
share_context = (HGLRC)SDL_GL_GetCurrentContext();
} else {
share_context = 0;
}
Expand Down
6 changes: 3 additions & 3 deletions src/video/x11/SDL_x11opengl.c
Expand Up @@ -532,7 +532,7 @@ X11_GL_CreateContext(_THIS, SDL_Window * window)
GLXContext context = NULL, share_context;

if (_this->gl_config.share_with_current_context) {
share_context = (GLXContext)(_this->current_glctx);
share_context = SDL_GL_GetCurrentContext();
} else {
share_context = NULL;
}
Expand Down Expand Up @@ -683,7 +683,7 @@ X11_GL_SetSwapInterval(_THIS, int interval)
} else if (_this->gl_data->glXSwapIntervalEXT) {
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
const SDL_WindowData *windowdata = (SDL_WindowData *)
_this->current_glwin->driverdata;
SDL_GL_GetCurrentWindow()->driverdata;

Window drawable = windowdata->xwindow;

Expand Down Expand Up @@ -727,7 +727,7 @@ X11_GL_GetSwapInterval(_THIS)
if (_this->gl_data->glXSwapIntervalEXT) {
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
const SDL_WindowData *windowdata = (SDL_WindowData *)
_this->current_glwin->driverdata;
SDL_GL_GetCurrentWindow()->driverdata;
Window drawable = windowdata->xwindow;
unsigned int allow_late_swap_tearing = 0;
unsigned int interval = 0;
Expand Down

0 comments on commit 3c23dc8

Please sign in to comment.