根据您使用的操作系统和驱动程序的可用性,您可以使用 EGL 进行纯、无头、GPU 加速的 OpenGL 渲染。Nvidia 在https://developer.nvidia.com/blog/egl-eye-opengl-visualization-without-x-server/上有一个很好的开发者博客关于如何做到这一点
它的要点是,在显示设备上创建 EGL 上下文而不将其与输出相关联。来源(直接从链接文章复制):
#include <EGL/egl.h>
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
};
static const int pbufferWidth = …;
static const int pbufferHeight = …;
static const EGLint pbattr[] = {
EGL_WIDTH, pbufferWidth,
EGL_HEIGHT, pbufferHeight,
EGL_NONE,
};
int main(int argc, char *argv[])
{
EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint major, minor;
eglInitialize(eglDpy, &major, &minor);
EGLint numConfigs;
EGLConfig eglCfg;
eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);
EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg, pbattr);
eglBindAPI(EGL_OPENGL_API);
EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, NULL);
eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);
do_opengl_stuff();
eglTerminate(eglDpy);
return 0;
}
如果您无法访问 EGL,但您的操作系统和 GPU 受 Linux DRM/DRI 支持,您可以走 KMS/GBM 路线,并且值得通过扩展机制获得帧缓冲区对象(嗯,使用 Mesa,您可以即使使用 OpenGL-1.x,也可以像使用它们一样使用它们)。kmscube演示有一个“无表面”模式,它演示了如何做到这一点。
简而言之:EGL 是一种“干净”的方式。KMS 是一种“hacky”方式。
另一个选择,现在可能完全超出你的范围,是使用 Vulkan,严格来说,无头渲染是“默认”,在屏幕上获取内容的方法是对规范的实际扩展:
VK_KHR_wayland_surface
VK_KHR_xcb_surface
VK_KHR_xlib_surface
VK_KHR_win32_surface