【问题标题】:Offscreen Rendering in OpenGL or DirectxOpenGL 或 Directx 中的离屏渲染
【发布时间】:2016-12-21 20:44:07
【问题描述】:

我希望能够在没有用户上下文或登录用户的服务器上使用硬件加速来渲染复杂的 2D 和 3D 图像。到目前为止我能做的最好的事情是Mesa3D,但是因为它是纯软件 3D 渲染,所以速度很慢,并且没有利用视频硬件加速。可以是 Windows 或 Linux。到目前为止,我的大部分工作都是在 Windows 中完成的。

关于如何使用 OpenGL 或 DirectX 执行此操作的任何建议?

【问题讨论】:

  • "[Mesa] 是纯软件 3D 渲染,速度慢,没有利用视频硬件加速"...wat
  • 我猜我们没有使用 mesa3d 的硬件驱动程序,因为 windows 会话 0 用户上下文问题...我会收集更多信息...

标签: opengl 3d server 2d directx


【解决方案1】:

对于 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。

【讨论】:

    【解决方案2】:

    对于 Windows,您可以在 Windows 8 / Server 2012 或更高版本的硬件设备上使用 Direct3D 11“无头”(即没有输出窗口/交换链并在会话 0 中运行)。在此之前,人们在使用 WARP(软件渲染器)和/或 NULL 设备时有一些运气。

    Direct3D 11.1 Features

    【讨论】:

      猜你喜欢
      • 2018-06-11
      • 2011-04-20
      • 2010-09-17
      • 2014-07-28
      • 2014-01-12
      • 2020-11-14
      • 2018-01-17
      • 1970-01-01
      相关资源
      最近更新 更多