我希望能够在没有用户上下文或登录用户的服务器上使用硬件加速来渲染复杂的2D和3D图像。到目前为止我能做的最好的事情是Mesa3D,但因为它是纯粹的软件3D渲染,所以它很慢并且没有利用视频硬件加速。可能是Windows或Linux。我迄今为止在Windows中完成的大部分工作。
有关如何使用OpenGL或DirectX执行此操作的任何建议?
答案 0 :(得分:2)
对于Linux,EGL + MESA_platform_gbm
应该让你获得一个完全无头/无X11的OpenGL环境。
该规范有助于包含演示用法的示例程序:
// This example program creates an EGL surface from a GBM surface.
//
// If the macro EGL_MESA_platform_gbm is defined, then the program
// creates the surfaces using the methods defined in this specification.
// Otherwise, it uses the methods defined by the EGL 1.4 specification.
//
// Compile with `cc -std=c99 example.c -lgbm -lEGL`.
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <EGL/egl.h>
#include <gbm.h>
struct my_display {
struct gbm_device *gbm;
EGLDisplay egl;
};
struct my_config {
struct my_display dpy;
EGLConfig egl;
};
struct my_window {
struct my_config config;
struct gbm_surface *gbm;
EGLSurface egl;
};
static void
check_extensions(void)
{
#ifdef EGL_MESA_platform_gbm
const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!client_extensions) {
// EGL_EXT_client_extensions is unsupported.
abort();
}
if (!strstr(client_extensions, "EGL_MESA_platform_gbm")) {
abort();
}
#endif
}
static struct my_display
get_display(void)
{
struct my_display dpy;
int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC);
if (fd < 0) {
abort();
}
dpy.gbm = gbm_create_device(fd);
if (!dpy.gbm) {
abort();
}
#ifdef EGL_MESA_platform_gbm
dpy.egl = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy.gbm, NULL);
#else
dpy.egl = eglGetDisplay(dpy.gbm);
#endif
if (dpy.egl == EGL_NO_DISPLAY) {
abort();
}
EGLint major, minor;
if (!eglInitialize(dpy.egl, &major, &minor)) {
abort();
}
return dpy;
}
static struct my_config
get_config(struct my_display dpy)
{
struct my_config config = {
.dpy = dpy,
};
EGLint egl_config_attribs[] = {
EGL_BUFFER_SIZE, 32,
EGL_DEPTH_SIZE, EGL_DONT_CARE,
EGL_STENCIL_SIZE, EGL_DONT_CARE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE,
};
EGLint num_configs;
if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) {
abort();
}
EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig));
if (!eglChooseConfig(dpy.egl, egl_config_attribs,
configs, num_configs, &num_configs)) {
abort();
}
if (num_configs == 0) {
abort();
}
// Find a config whose native visual ID is the desired GBM format.
for (int i = 0; i < num_configs; ++i) {
EGLint gbm_format;
if (!eglGetConfigAttrib(dpy.egl, configs[i],
EGL_NATIVE_VISUAL_ID, &gbm_format)) {
abort();
}
if (gbm_format == GBM_FORMAT_XRGB8888) {
config.egl = configs[i];
free(configs);
return config;
}
}
// Failed to find a config with matching GBM format.
abort();
}
static struct my_window
get_window(struct my_config config)
{
struct my_window window = {
.config = config,
};
window.gbm = gbm_surface_create(config.dpy.gbm,
256, 256,
GBM_FORMAT_XRGB8888,
GBM_BO_USE_RENDERING);
if (!window.gbm) {
abort();
}
#ifdef EGL_MESA_platform_gbm
window.egl = eglCreatePlatformWindowSurfaceEXT(config.dpy.egl,
config.egl,
window.gbm,
NULL);
#else
window.egl = eglCreateWindowSurface(config.dpy.egl,
config.egl,
window.gbm,
NULL);
#endif
if (window.egl == EGL_NO_SURFACE) {
abort();
}
return window;
}
int
main(void)
{
check_extensions();
struct my_display dpy = get_display();
struct my_config config = get_config(dpy);
struct my_window window = get_window(config);
return 0;
}
您可以使用eglBindAPI( EGL_OPENGL_API )
来使用OpenGL而不是OpenGL ES。
答案 1 :(得分:1)
对于Windows,您可以在Windows 8 / Server 2012或更高版本上使用Direct3D 11“无头”(即没有输出窗口/交换链并在会话0中运行)与硬件设备。在此之前,人们使用WARP(软件渲染器)和/或NULL设备获得了一些运气。