我以最小的方式使用 SDL 1.2 在 C++ 中创建跨平台 OpenGL 上下文(这是在 Win7 64 位上)。我还使用 glew 让我的上下文支持 OpenGL 4.2(我的驱动程序支持)。
事情在运行时正常工作,但我最近注意到在关闭调用 SDL_Quit 时发生随机崩溃。
使用 OpenGL 启动和关闭 SDL (1.2) 的正确顺序是什么?
这是我目前所做的:
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;
}
在初始化和关闭调用之间,我创建了许多 GL 资源(例如纹理、VBO、VAO、着色器等)并在每一帧渲染我的场景,在每一帧的末尾使用 SDL_GL_SwapBuffers()(非常典型)。像这样:
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;
}
在 ~MyObject MyObject::Shutdown() 中被调用。最近 SDL_Quit 使应用程序崩溃的地方。在我的渲染循环返回相同效果后,我也尝试在析构函数之外调用 Shutdown 。
我不做的一件事(我认为我不需要做)是在调用 Shutdown 之前为我分配的所有 GL 资源调用 glDelete* 函数(我认为它们会通过破坏上下文自动清理,我假设这是在 SDL_FreeSurface 或 SDL_Quit() 期间发生的。我当然在包装对象的 dtor 中调用 glDelete* 函数,最终被 ~MyObject 的故事调用,因为包装对象是其他对象的一部分MyObject 的成员。
作为一项实验,我尝试强制所有适当的 glDelete* 调用在 Shutdown() 之前发生,而我的崩溃似乎从未发生过。有趣的是,一周前我不需要这样做,根据 GIT,实际上没有任何改变(尽管可能是错误的)。
在使用 SDL 调用 MyObject::Shutdown 之前,是否真的有必要确保释放所有 GL 资源?看起来我可能做错了什么?