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

查看:298
本文介绍了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天全站免登陆