简体   繁体   中英

How to create a native X11 window for use with EGL

How does one create a native X11 window that works in EGL? Going through the eglIntro ( https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglIntro.xhtml ) there is little documentation on the matter. Alternatively, is there a way to create native windows through EGL itself? There is an EGLNativeWindowType that I assume can be used instead of whatever X11's native window types are.

No, EGL itself does not provide an Xlib wrapper. You have to create the window by yourself.

Here is a minimal sample to get you started. It refers to GLES2, but it should work with GLES1 also.

First, you declare the Xlib objects(display and window).

#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;
}

From the main function you will call the X event handler procedure. I have left commented printf calls to show how the event values are named, so there's no need to lookup the documentation. If the concept of "Event loop" is not clear, then I recommend reading about general UI event processing.

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;
    }
}

Finally, in the main() routine you create and open 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;
    }

The window is created and shown once you have the Display opened.

Finally, in the main() routine you create and open 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" );

When you have the window, intialise the EGL.

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

Once you have the EGL & Xlib objects, you can start the event processing loop.

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
}

This should get you started. The code is extracted from a larger project, so there might have be typos introduced while removing irrelevant things.

To conclude the answer and to be more precise, here EGLNativeWindowType is specialized to Window from X11/Xlib.h header and EGLNativeDisplayType is Display* .

An easier way might be to use libxcb , but I do not have any tested sample code. The GLFW library can be a useful source of OS-dependant OpenGL context creation routines.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM