>检测最新支持的OpenGL版本并使用它,但我想不出任何方法可以做到这一点.是的,我试过谷歌.
>使用试验和错误,我从最新版本开始(4.3,但我的GTX 460仅支持最多4.2,即使我更新了驱动程序),如果失败(通过检查SDL返回NULL检测到)上下文),我降低版本号,然后再试一次.
我使用的方法(#2)在创建4.3上下文后立即失败.我知道我的图形驱动程序现在只支持4.2,但我原以为GLX被设计为抛出一个错误,给出一个NULL上下文,并让你的程序继续运行,但它无法通过上下文的失败创建.我的假设是关于GLX如何表现错误?有没有办法在不创建上下文的情况下检测最新支持的版本?
因为我知道有些人喜欢看到演示错误的完整和最小的来源,这里是:
#include <SDL2/SDL.h> #include <SDL2/SDL_opengl.h> int main() { if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) { return -1; } SDL_Window* window = SDL_CreateWindow( "SDL Window",800,600,SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN ); if( window == nullptr ) { return -1; } unsigned int major = 4; unsigned int minor = 3; SDL_GLContext context = nullptr; while( context == nullptr ) { SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION,major ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION,minor ); context = SDL_GL_CreateContext( window ); if( context == nullptr ) { if( minor == 0 && major > 1 ) { --major; minor = 9; } else if( minor > 0 ) { --minor; } else { SDL_DestroyWindow( window ); return -1; } } } SDL_Delay( 5000 ); SDL_GL_DeleteContext( context ); SDL_DestroyWindow( window ); return 0; }
解决方法
我的猜测是第二次创建临时上下文失败,我建议使用调试信息构建SDL并尝试找出X11_GL_CreateContext()中的确切位置(或者至少插入几个printf).
另一方面,如果将SDL_GL_CONTEXT_MAJOR_VERSION和SDL_GL_CONTEXT_MINOR_VERSION保留为默认值,则已获得最大OpenGL版本.你只是没有得到一个前向兼容的上下文,这意味着它会让一些在未来版本中被认为是“错误”的行为漏掉.
此外,通常,创建具有最大版本的前向兼容上下文并不是一个好主意.例如.在OpenGL 3.2中,前向兼容配置文件强制使用顶点数组对象,这使得不使用VAO的旧代码被破坏.因此,如果为OpenGL 3.1(或任何其他版本)编写的应用程序试图获得最新的向前兼容配置文件,它实际上可能在将来停止工作.这不是一个好主意.
一种选择是决定使用一个向前兼容的配置文件,这通常非常有用,因为它报告有关已弃用功能的错误.如果您真的想要使用更多版本,则需要更多代码路径(=游戏引擎的更多版本).为了检测OpenGL版本,我建议创建一个虚拟SDL窗口,初始化一个简单的OpenGL配置文件,获取版本并关闭所有内容,然后再次初始化,使用您决定的版本.这应该工作.
另一种选择是仅将前向兼容配置文件用于开发,并使用简单的旧配置文件进行分发.它是最兼容的并且涉及的工作量最少(您希望无论如何都要忽略发布版本中的大多数OpenGL错误 – 驱动程序甚至可能会禁用错误报告).