Ubuntu 上没有 X Server 无法使用 EGL

Unable to use EGL without X Server on Ubuntu

我想在 Ubuntu 16.04 上打开没有 X 服务器的 OpenGL 上下文。使用 nvidia 390.48 驱动程序。我可以使用 https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/ 上的官方文档重现结果。

我现在想创建一个帧缓冲区对象。

我尝试使用以下改编自 https://github.com/parallel-forall/code-samples/blob/master/posts/egl_OpenGl_without_Xserver/tinyegl.cc

的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

#ifdef USE_EGL_GET_DISPLAY
#include <EGL/egl.h>
#else
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif

#ifdef USE_EGL_SURFACE
#include <GL/gl.h>
#else
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#endif

//ID for FBO and RBO
unsigned int FboID[1], RboID[1];

static const int pbufferWidth = 9, pbufferHeight = 9;

int main(int argc, char *argv[])
{

EGLDisplay display;
EGLContext context;

// 1. Initialize EGL
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY) {
        fprintf(stderr, "Error! Failed to eglGetDisplay\n");
        return false;
}
EGLint major, minor;
EGLBoolean eglStatus = eglInitialize(display, &major, &minor);
if (eglStatus == EGL_FALSE) {
        fprintf(stderr, "Error! Failed to eglInitialize\n");
        return false;
}
fprintf(stderr, "EGL Version %d . %d\n", major, minor);

// 2. Choose config
static const EGLint configAttribs[] = {
        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_DEPTH_SIZE, 8,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        EGL_NONE
};
EGLint numConfigs;
EGLConfig eglCfg;
eglStatus = eglChooseConfig(display, configAttribs, &eglCfg, 1, &numConfigs);
if (eglStatus == EGL_FALSE) {
        fprintf(stderr, "Error! Failed to eglChooseConfig\n");
        return false;
}
// 3. Create surface
const EGLint pbufferAttribs[] = {
        EGL_WIDTH, pbufferWidth,
        EGL_HEIGHT, pbufferHeight,
        EGL_NONE
};
EGLSurface surface = eglCreatePbufferSurface(display, eglCfg, pbufferAttribs);
if (surface == EGL_NO_SURFACE) {
        fprintf(stderr, "Error! Failed to eglCreatePbufferSurface\n");
        return false;
}
// 4. Bind API(OpenGL)
eglStatus = eglBindAPI(EGL_OPENGL_API);
if (eglStatus == EGL_FALSE) {
        fprintf(stderr, "Error! Failed to eglBindAPI\n");
        return false;
}
// 5.Create context and make it current
context = eglCreateContext(display, eglCfg, EGL_NO_CONTEXT, NULL);
if (context == EGL_NO_CONTEXT) {
        fprintf(stderr, "Error! Failed to eglCreateContext\n");
        return false;
}
eglStatus = eglMakeCurrent(display, surface, surface, context);
if (eglStatus == EGL_FALSE) {
        fprintf(stderr, "Error! Failed to eglMakeCurrent\n");
        return false;
}
// manually create the OpenGL buffers and textures: A  framebuffer object with associated
// texture and depth buffers.
// create a 2D texture as the color buffer
GLuint texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D,  texId);
glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA8,  pbufferWidth, pbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);    

// create a renderbuffer for storing the depth component
GLuint rbId;
glGenRenderbuffers(1, &rbId);
glBindRenderbuffer(GL_RENDERBUFFER, rbId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, pbufferWidth, pbufferHeight);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

// create the framebuffer and attach the texture (color buffer) and the renderbuffer (depth buffer)
GLuint fbId;
glGenFramebuffers(1, &fbId);
glBindFramebuffer(GL_FRAMEBUFFER, fbId);    

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbId);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
            fprintf(stderr, "Error! status = %d\n", status);
}

eglTerminate(display);
return 0;
}

但 GL_FRAMEBUFFER 的状态似乎没有变为“完成”

编译命令:

g++ main.cc -lEGL  -lGL

有没有人有解决此问题的想法或创建帧缓冲区对象的替代方法?

根据 NVIDIA's blog,您需要 link libOpenGL.so 而不是 libGL.so。

g++ tinyegl.cc -o tinyegl -lEGL /usr/lib/nvidia-390/libOpenGL.so

我不确定,但是“-lOpenGL”不工作。 所以,需要使用 /usr/lib/{nvidia-driver-path}/libOpenGL.so