0
votes

I am using SDL 1.2 in a minimal fashion to create a cross platform OpenGL context (this is on Win7 64bit) in C++. I also use glew to have my context support OpenGL 4.2 (which my driver supports).

Things work correctly at run-time but I have been noticing lately a random crash when shutting down on calling SDL_Quit.

What is the proper sequence for SDL (1.2) with OpenGL start up and shutdown?

Here is what i do currently:

int MyObj::Initialize(int width, int height, bool vsync, bool fullscreen)
{
  if(SDL_Init( SDL_INIT_EVERYTHING ) < 0) 
  {
    printf("SDL_Init failed: %s\n", SDL_GetError());
    return 0;
  }

  SDL_GL_SetAttribute(SDL_GL_RED_SIZE,          8);
  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,        8);
  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,         8);
  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE,        8);

  SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,        24);
  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,          8);
  SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,           24);

  SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,  0);
  SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,  vsync ? 1 : 0);

  if((m_SurfDisplay = SDL_SetVideoMode(width, height, 24, 
                                       SDL_HWSURFACE | 
                                       SDL_GL_DOUBLEBUFFER | 
                                       (fullscreen ? SDL_FULLSCREEN : 0) |
                                       SDL_OPENGL)) == NULL)
  {
    printf("SDL_SetVideoMode failed: %s\n", SDL_GetError());
    return 0;
  }

  GLenum err = glewInit();
  if (GLEW_OK != err) 
    return 0;

  m_Running = true;
  return 1;
}

int MyObj::Shutdown()
{   
  SDL_FreeSurface(m_SurfDisplay);
  SDL_Quit();

  return 1;
}

In between the init and shutdown calls i create a number of GL resources (e.g. Textures, VBOs, VAO, Shaders, etc.) and render my scene each frame, with a SDL_GL_SwapBuffers() at the end of each frame (pretty typical). Like so:

int MyObject::Run()
{
  SDL_Event Event;

  while(m_Running) 
  {
    while(SDL_PollEvent(&Event))
    { OnEvent(&Event); } //this eventually causes m_Running to be set to false on "esc"

    ProcessFrame();
    SDL_SwapBuffers();
  }
  return 1;
}

Within the ~MyObject MyObject::Shutdown() is called. Where just recently SDL_Quit crashes the app. I have also tried call Shutdown instead outside of the destructor, after my render loop returns to the same effect.

One thing that I do not do (that i didn't think I needed to do) is call the glDelete* functions for all my allocated GL resources before calling Shutdown (i thought they would automatically be cleaned up by the destruction of the context, which i assumed was happening during SDL_FreeSurface or SDL_Quit(). I of course call the glDelete* function in the dtors of there wrapping objects, which eventually get called by the tale of ~MyObject, since the wrapper objects are part of other objects that are members of MyObject.

As an experiment i trying forcing all the appropriate glDelete* calls to occur before Shutdown(), and my crash never seems to occur. Funny thing i did not need to do this a week ago, and really nothing has changed according to GIT (may be wrong though).

Is it really necessary to make sure all GL resources are freed before calling MyObject::Shutdown with SDL? Does it look like I might be doing something else wrong?

1

1 Answers

3
votes
m_SurfDisplay = SDL_SetVideoMode(...)
...
SDL_FreeSurface(m_SurfDisplay);
                ^^^^^^^^^^^^^ naughty naughty!

SDL_SetVideoMode():

The returned surface is freed by SDL_Quit and must not be freed by the caller.