【问题标题】:How to create a native X11 window for use with EGL如何创建用于 EGL 的原生 X11 窗口
【发布时间】:2021-02-03 12:17:35
【问题描述】:

如何创建在 EGL 中工作的原生 X11 窗口?通过 eglIntro (https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglIntro.xhtml) 几乎没有关于此事的文档。或者,有没有办法通过 EGL 本身创建本机窗口?有一个 EGLNativeWindowType 我认为可以用来代替 X11 的原生窗口类型。

【问题讨论】:

    标签: c opengl x11 egl


    【解决方案1】:

    不,EGL 本身不提供 Xlib 包装器。您必须自己创建窗口。

    以下是帮助您入门的最小示例。它指的是 GLES2,但它也应该适用于 GLES1。

    首先,声明 Xlib 对象(显示和窗口)。

    #include <stdio.h>
    
    #include <X11/Xlib.h>
    #include <X11/Xatom.h>
    #include <X11/Xutil.h>
    
    #include  <GLES2/gl2.h>
    #include  <EGL/egl.h>
    
    // Native handles for window and display
    Window      win;
    Display* xdisplay;
    
    // EGL-related objects
    EGLDisplay  egl_display;
    EGLConfig   egl_conf;
    EGLContext  egl_context;
    EGLSurface  egl_surface;
    
    int init_egl()
    {
        EGLint attr[] = {
            EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
            EGL_RED_SIZE,        8,
            EGL_GREEN_SIZE,      8,
            EGL_BLUE_SIZE,       8,
            // EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, /* If one needs GLES2 */
            EGL_NONE
        };
    
        EGLint num_config;
        EGLint major, minor;
    
        EGLint ctxattr[] = {
           EGL_CONTEXT_CLIENT_VERSION, 2,
           EGL_NONE
        };
    
        egl_display  =  eglGetDisplay( (EGLNativeDisplayType) xdisplay );
        if ( egl_display == EGL_NO_DISPLAY ) {
            printf("Error getting EGL display\n");
            return 0;
        }
    
        if ( !eglInitialize( egl_display, &major, &minor ) ) {
            printf("Error initializing EGL\n");
            return 0;
        }
    
        printf("EGL major: %d, minor %d\n", major, minor);
    
        /* create EGL rendering context */
        if ( !eglChooseConfig( shell->egl_display, attr, &shell->egl_conf, 1, &num_config ) ) {
            printf("Failed to choose config (eglError: %x)\n", eglGetError());
            return 0;
        }
    
        if ( num_config != 1 ) {
            return 0;
        }
    
        egl_surface = eglCreateWindowSurface ( egl_display, egl_conf, win, NULL );
        if (egl_surface == EGL_NO_SURFACE ) {
            printf("CreateWindowSurface, EGL eglError: %d\n", eglGetError() );
            return 0;
        }
    
        egl_context = eglCreateContext ( egl_display, egl_conf, EGL_NO_CONTEXT, ctxattr );
        if ( egl_context == EGL_NO_CONTEXT ) {
            printf("CreateContext, EGL eglError: %d\n", eglGetError() );
            return 0;
        }
    
        return 1;
    }
    

    您将从main 函数调用X 事件处理程序过程。我留下了对printf 调用的评论,以显示事件值的命名方式,因此无需查找文档。如果“事件循环”的概念不清楚,那么我建议阅读通用 UI 事件处理。

    void process_xevent(XEvent xev) {
        //    XNextEvent( xdisplay, &xev );
        switch (xev.type)
        {
            case MotionNotify:
                // printf("motion: %d %d\n", xev.xbutton.x, xev.xbutton.y);
                break;
            case KeyRelease:
                // printf("rel (%d)\n", XLookupKeysym (&xev.xkey, 0));
                break;
            case KeyPress:
                // printf("keypress (%d)\n", XLookupKeysym (&xev.xkey, 0));
                break;
            case ButtonPress:
                // printf("BPress: state = %d, button = %d, x = %d, y = %d\n", xev.xbutton.state, xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
                // printf("Type=%d\n", (int)xev.xbutton.type);
                break;
            case ButtonRelease:
                // printf("BRelease: state = %d, button = %d, x = %d, y = %d\n", xev.xbutton.state, xev.xbutton.button, xev.xbutton.x, xev.xbutton.y);
                // printf("Type=%d\n", (int)xev.xbutton.type);
                break;
        }
    }
    

    最后,在 main() 例程中创建并打开 display/Xwindow。

    int main()
    {
        int egl_error;
    
        Window root;
        XSetWindowAttributes  swa;
    
        /* open standard display (primary screen) */
        xdisplay = XOpenDisplay ( NULL );   
        if ( xdisplay == NULL ) {
            printf("Error opening X display\n");
            return 0;
        }
    

    一旦您打开了显示,就会创建并显示窗口。

    最后,在 main() 例程中创建并打开 display/Xwindow。

        // get the root window (usually the whole screen)
        root  =  DefaultRootWindow( shell->xdisplay );
    
        // list all events this window accepts
        swa.event_mask =
        StructureNotifyMask |
        ExposureMask        |
        PointerMotionMask   |
        KeyPressMask        |
        KeyReleaseMask      |
        ButtonPressMask     |
        ButtonReleaseMask;
    
        // Xlib's window creation
        win  =  XCreateWindow (
            xdisplay, root, 0, 0, 640, 480,   0,
            CopyFromParent, InputOutput, CopyFromParent, CWEventMask,
           &swa );
    
        XMapWindow ( xdisplay , win );         // make window visible
        XStoreName ( xdisplay , win , "EGL" );
    

    当你有窗口时,初始化 EGL。

        egl_error = init_egl();
        if (!egl_error) {
            return 1;
        }
    

    一旦你有了 EGL 和 Xlib 对象,你就可以开始事件处理循环了。

    while (1) {
            int keycode;
            XEvent  xev;
    
            if ( XPending ( xdisplay ) )
                if (XCheckWindowEvent(shell->xdisplay, shell->win, global_event_mask, &xev))
                    process_xevent(shell, xev);
    
           /* if (should_exit) { break; }   // set some global flag if you want to exit */
    
           eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context );
    
           /* Call OpenGL as you see fit */
    
           /* get rendered buffer to the screen */
           eglSwapBuffers ( egl_display, egl_surface );
       }
    
    
       // deinitialize
    }
    

    这应该可以帮助您入门。该代码是从一个较大的项目中提取的,因此在删除不相关的内容时可能会引入拼写错误。

    总结答案并更准确地说,这里EGLNativeWindowType 专门用于X11/Xlib.h 标头中的WindowEGLNativeDisplayTypeDisplay*

    更简单的方法可能是使用libxcb,但我没有任何经过测试的示例代码。 GLFW library 可以成为依赖于操作系统的 OpenGL 上下文创建例程的有用来源。

    【讨论】:

    • 谢谢。通过一点点调整,这为我提供了一个标准的黑色窗口。稍加调整,我就可以将其与我的项目集成。
    • glClearColor + glClear 组合提供了一个标准的非黑色窗口作为下一个测试)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多