OpenGL 或 Directx 中的离屏渲染 [英] Offscreen Rendering in OpenGL or Directx

查看:94
本文介绍了OpenGL 或 Directx 中的离屏渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to be able to render complex 2D and 3D images using hardware acceleration on a server with no user context or logged in user. The best thing I could do so far is Mesa3D, but because it is pure software 3D rendering it is slow and does not take advantage of the video hardware acceleration. Could be Windows or Linux. Most of my work I have done so far in Windows.

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

Any suggestions on how to do this with OpenGL or DirectX?

推荐答案

对于 Linux,EGL + MESA_platform_gbm 应该让您获得完全无头/无 X11 的 OpenGL 上下文.

For Linux, EGL + MESA_platform_gbm should let you get a completely headless/X11-less OpenGL context.

该规范有用地包含了一个示例程序演示用法:

The spec helpfully includes an example program demoing usage:

// 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.

You can use eglBindAPI( EGL_OPENGL_API ) to use OpenGL instead of OpenGL ES.

这篇关于OpenGL 或 Directx 中的离屏渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆