Skip to main

AK#Notes

EGL with XCB Example

main.c:

.c
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <xcb/xcb.h>

int main(void) {
    // Initialize XCB connection
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(conn)) {
        fprintf(stderr, "Cannot open display\n");
        return 1;
    }

    // Get first screen
    const xcb_setup_t *setup = xcb_get_setup(conn);
    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
    xcb_screen_t *screen = iter.data;

    // Create window
    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t values[] = {screen->white_pixel, XCB_EVENT_MASK_EXPOSURE};
    xcb_window_t win = xcb_generate_id(conn);
    xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, screen->root,
                     0, 0, 800, 600, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                     screen->root_visual, mask, values);
    xcb_map_window(conn, win);
    xcb_flush(conn);

    // Initialize EGL
    EGLDisplay egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (egl_dpy == EGL_NO_DISPLAY) {
        fprintf(stderr, "eglGetDisplay failed\n");
        xcb_disconnect(conn);
        return 1;
    }

    if (!eglInitialize(egl_dpy, NULL, NULL)) {
        fprintf(stderr, "eglInitialize failed\n");
        xcb_disconnect(conn);
        return 1;
    }

    // Choose EGL config
    EGLint config_attrs[] = {
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
    };
    EGLConfig egl_cfg;
    EGLint num_configs;
    if (!eglChooseConfig(egl_dpy, config_attrs, &egl_cfg, 1, &num_configs)) {
        fprintf(stderr, "eglChooseConfig failed\n");
        eglTerminate(egl_dpy);
        xcb_disconnect(conn);
        return 1;
    }

    // Create EGL surface
    EGLSurface egl_surf = eglCreateWindowSurface(egl_dpy, egl_cfg, win, NULL);
    if (egl_surf == EGL_NO_SURFACE) {
        fprintf(stderr, "eglCreateWindowSurface failed\n");
        eglTerminate(egl_dpy);
        xcb_disconnect(conn);
        return 1;
    }

    // Create EGL context
    EGLint ctx_attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
    EGLContext egl_ctx = eglCreateContext(egl_dpy, egl_cfg, EGL_NO_CONTEXT, ctx_attrs);
    if (egl_ctx == EGL_NO_CONTEXT) {
        fprintf(stderr, "eglCreateContext failed\n");
        eglDestroySurface(egl_dpy, egl_surf);
        eglTerminate(egl_dpy);
        xcb_disconnect(conn);
        return 1;
    }

    // Make context current
    eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);

    // Main loop
    while (1) {
        xcb_generic_event_t *ev = xcb_wait_for_event(conn);
        if (!ev) continue;

        switch (ev->response_type & ~0x80) {
        case XCB_EXPOSE:
            // Clear screen
            glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            eglSwapBuffers(egl_dpy, egl_surf);
            break;
        }
        free(ev);
    }

    // Cleanup
    eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(egl_dpy, egl_ctx);
    eglDestroySurface(egl_dpy, egl_surf);
    eglTerminate(egl_dpy);
    xcb_disconnect(conn);
    return 0;
}

Run Command:

cc main.c -lxcb -lEGL -lGL && ./a.out