I am currently working on a program for which I need a headless opengl context. Ideally, it will be possible to run without an X server on Linux. My research tells me that EGL is the only way to do this (please tell me if there is another way, as I strongly prefer C++ APIs to C apis like EGL). Looking at this tutorial and the EGL reference, I came up with this code, in the form of a minimum and complete example:
#include <EGL/egl.h>
#include <glad/glad.h>
#include <iostream>
#include <exception>
class GlException : public std::exception{
public:
GlException(const std::string &message) : m_message(message) {}
const char *what() const noexcept override { return m_message.c_str(); }
private:
std::string m_message;
};
void createOpenGlContext() {
constexpr EGLint configAttribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
constexpr EGLint pbufferAttribs[] = {
EGL_WIDTH, 1600,
EGL_HEIGHT, 900,
EGL_NONE,
};
EGLDisplay m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLBoolean result = eglInitialize(m_display, nullptr, nullptr);
if(result != EGL_TRUE){
switch(eglGetError()){
case EGL_BAD_DISPLAY:
throw GlException("Failed to initialize EGL Display: EGL_BAD_DISPLAY");
case EGL_NOT_INITIALIZED:
throw GlException("Failed to initialize EGL Display: EGL_NOT_INITIALIZED");
default:
throw GlException("Failed to initialize EGL Display: unknown error");
}
}
EGLint numConfigs;
EGLConfig eglConfig;
result = eglChooseConfig(m_display, configAttribs, &eglConfig, 1, &numConfigs);
if(result != EGL_TRUE){
switch(eglGetError()){
case EGL_BAD_DISPLAY:
throw GlException("Failed to configure EGL Display: EGL_BAD_DISPLAY");
case EGL_BAD_ATTRIBUTE:
throw GlException("Failed to configure EGL Display: EGL_BAD_ATTRIBUTE");
case EGL_NOT_INITIALIZED:
throw GlException("Failed to configure EGL Display: EGL_NOT_INITIALIZED");
case EGL_BAD_PARAMETER:
throw GlException("Failed to configure EGL Display: EGL_BAD_PARAMETER");
default:
throw GlException("Failed to configure EGL Display: unknown error");
}
}
EGLSurface surface = eglCreatePbufferSurface(m_display, eglConfig, pbufferAttribs);
eglBindAPI(EGL_OPENGL_API);
EGLContext context = eglCreateContext(m_display, eglConfig, EGL_NO_CONTEXT, nullptr);
}
int main(){
createOpenGlContext();
if(!gladLoadGL()){
std::cerr << "Failed to load OpenGl function pointers" << std::endl;
return -1;
}
return 0;
}
When I call gladLoadGl
in that code, it fails as can be determined via its return value, suggesting that a context has not been created, despite almost exactly using the code from the Nvidia blog (presumably Nvidia knows what they are doing with OpenGl.). I attempted to find someone else with the same error with my preferred search engine, but nothing useful came up. What is wrong with my code?
I am using this glad configuration. I am using Arch Linux, fully updated. I have a Gtx 1070 with the latest drivers from Nvidia. The above code fails when run with an available X server. I have not tested it in a headless environment.
@GM的建议起作用了,在现有的createOpenGlContext
函数解决了问题之前,添加了对eglMakeCurrent的调用。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.