SDL_AddTimer + SDL_GL_MakeCurrent + Windows

I’m playing with C++, OpenGL and SDL doing a game that should be able to
run in Windows and Mac OS X.
I have a problem that only happens on Windows.

Let me describe the scenario.

First I create an OpenGL renderer and get the current context:

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Window.cpp#L103-L130

this->renderer = SDL_CreateRenderer(this->window, rendererIndex,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

this->context = SDL_GL_GetCurrentContext();

In my scene I add a timer to create some asteroids:

https://github.com/felipowsky/GrifoEngine/blob/master/examples/Spaceship/main.cpp#L182

this->timer.Start(INTERVAL_CREATE_ASTEROID,
SpaceshipScene::CreateAsteroidTimer, this);

Internally this timer uses SDL_AddTimer and keeps the current window and
context for itself:

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Timer.cpp#L38-L47

this->window = SDL_GL_GetCurrentWindow();
this->context = SDL_GL_GetCurrentContext();
this->callback = callback;
this->param = param;
this->timerId = SDL_AddTimer(interval, Timer::ExecuteCallback, this);

When the callback executes I use MakeCurrent to make sure that OpenGL will
run in the right context (the window and context from the main thread):

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Timer.cpp#L19-L33

bool hasContext = timer->window != NULL && timer->context != NULL;
if (hasContext) { SDL_GL_MakeCurrent(timer->window, timer->context);}

Uint32 result = timer->callback(interval, timer->param);

if (hasContext) { SDL_GL_MakeCurrent(timer->window, NULL);}

On Mac OS X this code is working perfectly, but on Windows it isn’t drawing
the asteroids on the window neither throwing any error.

I’ve tried to create a context for every callback execution, it works, but
the game runs slowly and doesn’t seem the right thing to do.

What am I doing wrong?

Thanks in advance.

After working a lot to solve this, I’ve discovered some interesting points.
It seems that Mac OS X allows me to use the same context for 2 threads, but
Windows doesn’t.
When I was trying to make the context current, on Windows I was receiving
"wglMakeCurrent failed: The requested resource is in use".

So I tried to create a different context for the thread. Now, it worked for
Windows, but on Mac, any texture that I was creating from the thread was
using “my screen as image” (any random part of my screen: menus, texts,
window, etc). Very weird.
This can be something related with my OpenGL implementation, but I have no
idea what I should look to solve this.

So, I’ve ended up doing 2 implementations.

One for Windows, that creates a new context and makes the current context
current again (for some reason this is necessary after creating a new
context on Windows):

SDL_GLContext context = SDL_GL_GetCurrentContext();
this->context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);

And one for Mac, that just uses the current context for the thread:

this->context = SDL_GL_GetCurrentContext();

Here is the complete code:
https://github.com/felipowsky/GrifoEngine/blob/9d7ea584b994ee57c35202120e1955ab01b588c9/sources/Timer.cpp#L43-L64

Does anybody know if this correct?

Thanks.On Tue, Jul 1, 2014 at 10:41 PM, Felipe Augusto <@Felipe_Augusto> wrote:

I’m playing with C++, OpenGL and SDL doing a game that should be able to
run in Windows and Mac OS X.
I have a problem that only happens on Windows.

Let me describe the scenario.

First I create an OpenGL renderer and get the current context:

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Window.cpp#L103-L130

this->renderer = SDL_CreateRenderer(this->window, rendererIndex,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

this->context = SDL_GL_GetCurrentContext();

In my scene I add a timer to create some asteroids:

https://github.com/felipowsky/GrifoEngine/blob/master/examples/Spaceship/main.cpp#L182

this->timer.Start(INTERVAL_CREATE_ASTEROID,
SpaceshipScene::CreateAsteroidTimer, this);

Internally this timer uses SDL_AddTimer and keeps the current window and
context for itself:

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Timer.cpp#L38-L47

this->window = SDL_GL_GetCurrentWindow();
this->context = SDL_GL_GetCurrentContext();
this->callback = callback;
this->param = param;
this->timerId = SDL_AddTimer(interval, Timer::ExecuteCallback, this);

When the callback executes I use MakeCurrent to make sure that OpenGL will
run in the right context (the window and context from the main thread):

https://github.com/felipowsky/GrifoEngine/blob/master/sources/Timer.cpp#L19-L33

bool hasContext = timer->window != NULL && timer->context != NULL;
if (hasContext) { SDL_GL_MakeCurrent(timer->window, timer->context);}

Uint32 result = timer->callback(interval, timer->param);

if (hasContext) { SDL_GL_MakeCurrent(timer->window, NULL);}

On Mac OS X this code is working perfectly, but on Windows it isn’t
drawing the asteroids on the window neither throwing any error.

I’ve tried to create a context for every callback execution, it works, but
the game runs slowly and doesn’t seem the right thing to do.

What am I doing wrong?

Thanks in advance.

You should create your context only once (on the same thread as you created your window, probably), and then make the current context NULL on the main thread, and make that context current on your other thread (and be sure to call SDL_GL_SwapWindow on the same thread as your context is current in.)
You won?t have to do anything else unless you switch which thread the context is current in later, in which case you should SDL_GL_MakeCurrent(?, NULL) on the old thread, and SDL_GL_MakeCurrent(?, context) on the new thread.On Jul 7, 2014, at 3:15 PM, Felipe Augusto wrote:

After working a lot to solve this, I’ve discovered some interesting points.
It seems that Mac OS X allows me to use the same context for 2 threads, but Windows doesn’t.
When I was trying to make the context current, on Windows I was receiving “wglMakeCurrent failed: The requested resource is in use”.

So I tried to create a different context for the thread. Now, it worked for Windows, but on Mac, any texture that I was creating from the thread was using “my screen as image” (any random part of my screen: menus, texts, window, etc). Very weird.
This can be something related with my OpenGL implementation, but I have no idea what I should look to solve this.

So, I’ve ended up doing 2 implementations.

One for Windows, that creates a new context and makes the current context current again (for some reason this is necessary after creating a new context on Windows):

SDL_GLContext context = SDL_GL_GetCurrentContext();
this->context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);

And one for Mac, that just uses the current context for the thread:

this->context = SDL_GL_GetCurrentContext();

Here is the complete code:
https://github.com/felipowsky/GrifoEngine/blob/9d7ea584b994ee57c35202120e1955ab01b588c9/sources/Timer.cpp#L43-L64

Does anybody know if this correct?

Thanks.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org