如何搭配GLFW配置GLEW?遭遇GLEW_ERROR_NO_GLX_DISPLAY错误
我在Ubuntu系统的小项目中自行编译构建了GLFW和GLEW,调用glewInit()时遇到错误,返回Unknown error。经排查,错误根源在glxewInit中,因display == NULL触发GLEW_ERROR_NO_GLX_DISPLAY。但禁用glewInit()后,窗口可正常运行并执行OpenGL基础渲染操作。
相关初始化代码
bool WindowGLFW::initialize() { // Initialize GLFW if (!glfwInit()) { std::string msg = std::string("GLFW library could not be initialized \n"); LOG_ON_MAIN_LOG(MESSAGE_STATUS_BAD(msg)); return false; } _width = _glfwParameters.width; _height = _glfwParameters.height; _ratioNumer = _glfwParameters.width; _ratioDenom = _glfwParameters.width; _nameWindow = _glfwParameters.width; /*set the Windows hint informations*/ glfwWindowHint(GLFW_RESIZABLE, _glfwParameters.resizable); glfwWindowHint(GLFW_VISIBLE, _glfwParameters.visible); glfwWindowHint(GLFW_DECORATED, _glfwParameters.decorated); glfwWindowHint(GLFW_FOCUSED, _glfwParameters.focused); glfwWindowHint(GLFW_AUTO_ICONIFY, _glfwParameters.auto_iconify); glfwWindowHint(GLFW_FLOATING, _glfwParameters.floating); glfwWindowHint(GLFW_MAXIMIZED, _glfwParameters.maximized); glfwWindowHint(GLFW_CENTER_CURSOR, _glfwParameters.center_cursor); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, _glfwParameters.transparent_framebuffer); glfwWindowHint(GLFW_FOCUS_ON_SHOW, _glfwParameters.focus_on_show); glfwWindowHint(GLFW_SCALE_TO_MONITOR, _glfwParameters.scale_to_monitor); /*set Framebuffer hint information*/ glfwWindowHint(GLFW_RED_BITS, _glfwParameters.red_bits); glfwWindowHint(GLFW_GREEN_BITS, _glfwParameters.green_bits); glfwWindowHint(GLFW_BLUE_BITS, _glfwParameters.blue_bits); glfwWindowHint(GLFW_ALPHA_BITS, _glfwParameters.alpha_bits); glfwWindowHint(GLFW_DEPTH_BITS, _glfwParameters.depth_bits); glfwWindowHint(GLFW_ACCUM_RED_BITS, _glfwParameters.accum_red_bits); glfwWindowHint(GLFW_ACCUM_GREEN_BITS, _glfwParameters.accum_green_bits); glfwWindowHint(GLFW_ACCUM_BLUE_BITS, _glfwParameters.accum_blue_bits); glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, _glfwParameters.accum_alpha_bits); glfwWindowHint(GLFW_AUX_BUFFERS, _glfwParameters.aux_buffers); glfwWindowHint(GLFW_SAMPLES, _glfwParameters.samples); glfwWindowHint(GLFW_SRGB_CAPABLE, _glfwParameters.srgb_capable); glfwWindowHint(GLFW_STENCIL_BITS, _glfwParameters.stencil_bits); /*set Monitor hint information*/ glfwWindowHint(GLFW_REFRESH_RATE, _glfwParameters.refresh_rate); /*set Context hint information*/ glfwWindowHint(GLFW_CLIENT_API, _glfwParameters.client_api); glfwWindowHint(GLFW_CONTEXT_CREATION_API, _glfwParameters.context_creation_api); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _glfwParameters.context_version_major); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _glfwParameters.context_version_minor); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, _glfwParameters.context_forward_compat); glfwWindowHint(GLFW_OPENGL_PROFILE, _glfwParameters.opengl_profile); glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, _glfwParameters.context_release_behaviour); glfwWindowHint(GLFW_CONTEXT_NO_ERROR, _glfwParameters.context_no_error); glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, _glfwParameters.opengl_robustness); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, _glfwParameters.opengl_debug_context); //probably should switch to c++14 to use make_unique...whatever _window = std::unique_ptr<GLFWwindow, customGLFWWindowDeletor>( glfwCreateWindow(_width, _height, _nameWindow.c_str(), glfwGetPrimaryMonitor(), NULL)); if(!_window.get()) { /* think about maybe changing this and the other * occurrence of a manager. To have dissociation between * managers and actual code (separate manager and current code) */ std::string msg = std::string("window can not be initialized \n"); LOG_ON_MAIN_LOG(MESSAGE_STATUS_BAD(msg)); glfwTerminate(); return false; } /* Make the window's context current */ glfwMakeContextCurrent(_window.get()); std::string msg = std::string("GLFW window was created/initialized ! "); LOG_ON_MAIN_LOG(MESSAGE_STATUS_GOOD(msg)); //Initialize GLEW if(_glfwParameters.client_api == GLFW_OPENGL_API) { glewExperimental=GL_TRUE; GLenum err = glewInit(); if (err != GLEW_OK) { /* Need to convert uc_msg to i32 so uc_msg will be output as ainteger * and not a character then string for the MACRO */ std::cout << glewGetErrorString(err) << std::endl; std::cout << glewGetString(GLEW_VERSION) << std::endl; const unsigned char* uc_msg = glewGetErrorString(err); std::string msg = std::string(reinterpret_cast<const char*>(uc_msg)); LOG_ON_MAIN_LOG(MESSAGE_STATUS_BAD(msg)); glfwTerminate(); return -1; } } setCallbacks(); return true; }
禁用GLEW后可正常运行的渲染循环
while (!glfwWindowShouldClose( _window->getWindow().get() ) ) { /* Render here */ /* Set the clear color to black (0, 0, 0, 1) using OpenGL */ glClearColor(0.4f, 0.4f, 0.4f, 0.5f); /* Clear the color buffer */ glClear(GL_COLOR_BUFFER_BIT); /* Swap front and back buffers */ _window->swapBuffer(); /* Poll for and process events */ _window->poolEvents(); }
GLEW_ERROR_NO_GLX_DISPLAY的核心原因是GLEW无法获取有效的X11显示连接,结合你的场景,可从以下几个方向排查修复:
检查GLEW编译依赖
自行编译GLEW时,可能未正确链接GLX和X11相关库。重新编译时,确保启用GLX支持:- 若用CMake,需开启
BUILD_GLX选项; - 手动编译时,链接阶段添加
-lX11 -lGLX参数。
- 若用CMake,需开启
验证GLFW上下文配置
检查_glfwParameters中的上下文参数:- 确认
GLFW_CLIENT_API确实设置为GLFW_OPENGL_API,而非Vulkan等其他API; - 确保
GLFW_CONTEXT_VERSION_MAJOR和GLFW_CONTEXT_VERSION_MINOR设置为系统支持的OpenGL版本(Ubuntu建议至少3.3); - 若设置
GLFW_OPENGL_PROFILE,需保证是GLFW_OPENGL_CORE_PROFILE或GLFW_OPENGL_COMPAT_PROFILE,且与版本匹配。
- 确认
确保X11会话环境正常
若在无桌面的环境(如SSH远程)运行,需设置DISPLAY=:0环境变量;若在桌面环境,检查窗口管理器是否正常,可尝试在终端直接运行程序,而非IDE中启动。匹配GLEW与GLFW版本
自行编译的版本可能存在兼容性问题,建议使用稳定版本组合(如GLEW 2.2.0+ + GLFW 3.3+)重新编译两者。修复代码中的明显错误
初始化代码中_nameWindow = _glfwParameters.width;是将数值赋值给字符串类型的窗口名称,会导致无效窗口名,可能触发GLFW内部异常状态,建议修正为对应窗口名字段(如_nameWindow = _glfwParameters.window_name;)。
内容的提问来源于stack exchange,提问作者Benzait Sofiane

