OpenGL是一种跨平台的图形渲染API,主要用于2D和3D图形的渲染。OpenGL实现通常由GPU厂商提供,使得程序可以不关心硬件实现直接与GPU做交互。一般情况下图形渲染在客户端进行,因为大部分渲染目标都是屏幕窗口。而不同操作系统的图形窗口系统实现千差万别,所以又有了EGL(Embedded-System Graphics Library) 接口,用于管理图形上下文、Surface,作为OpenGL与原始窗口系统之间的桥梁。
服务端渲染是相对小众的需求,主要场景有云渲染、媒体处理等。服务端渲染有一个问题是我们的服务通常部署在ECS或K8s上,不会配置GPU,也没有GUI界面,软硬件环境都不具备。要解决这个问题,我们可以借助开源的图形库libMesa。
OSMesa软件渲染
OSMesa (Off-Screen Mesa) 是libMesa的一部分。可以用于在没有窗口系统支持的情况下进衣赖于GPU进行渲染。OSMesa的使用也很简单,首先安装依赖:
1
| yum install -y mesa-libOSMesa-devel mesa-libGL-devel mesa-libEGL-devel
|
接下来是常规的创建GL上下文,这里需要引入<GL/osmesa.h>头文件,使用其提供系列函数实现GL上下文管理,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <stdio.h> #include <stdlib.h> #include <GL/osmesa.h> #include <GL/gl. h>
int main() { const int width = 800; const int height = 600; OSMesaContext ctx = 0SMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL); if (!ctx) { fprintf(stderr, "OSMesaCreateContext failed\n"); return 1; } void *buffer = malloc(width * height * 4); if (!buffer) { printf(stderr, "Buffer allocation failed\n"); OSMesaDestroyContext(ctx); return 1; }
void *buffer = malloc(width * height * 4); if (!buffer) { fprintf(stderr, "Buffer allocation failed\n"); OSMesaDestroyContext(ctx); return 1; }
OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, width, height);
glClearColor(1.0, 0.0, 0.0, 1.0); gLClear(GL_COLOR_BUFFER_BIT);
FILE *f = fopen("output. rgba", "wb"); if (f) { fwrite(buffer, width * height * 4, 1, f); fclose(f); printf("Image saved to output.rgba\n"); } else { fprintf(stderr, "Failed to open file for writing\n"); }
OSMesaMakeCurrent((OSMesaContext) nullptr, nullptr, GL_UNSIGNED_BYTE, 0, 0); free(buffer); OSMesaDestroyContext(ctx); return 0; }
|
这里我们创建了一块内存作为渲染缓冲区,渲染结果直接可以通过内存获取。当然,使用glReadPixels 读取结果也是一样的。
DRM硬件加速
如果你的服务部署在本地物理机并配置有显卡,或是配置了带GPU的ECS机器,那可以用DRM做硬件加速。DRM(Direct Rendering Manager)是Linux内核的一部分,用于管理图形显示的硬件加速以及图形上下文的切换。它的优点是可以不依赖图形窗口系统,直接与GPU通信,提高渲染性能。
这个方案我们项目里没有实际应用,相关实现可以参考libMesa提供的demo:
https://gitlab.freedesktop.org/mesa/demos/-/blob/main/src/egl/opengl/eglkms.c