ubuntu22上C/C++程序使用weston+wayland+OpenGLES渲染

发布于:2024-10-10 ⋅ 阅读:(64) ⋅ 点赞:(0)

一,安装依赖软件:sudo apt install zlib1g-dev libssl-dev libgles2-mesa-dev libsystemd-dev libpng-dev libglib2.0-dev libwayland-dev weston libweston-9-dev

二,启动:

# 运行weston
weston -Swayland-1

# 运行程序
./yourprogram

  注意:这里启动weston用的wayland-1,所以代码中也要用wayland-1。

三,代码:

#include "wayland-client.h"
#include "wayland-egl.h"
#include "wayland-util.h"
#include <GLES2/gl2.h>
#include <EGL/egl.h>

typedef struct stWlContextStruct {
    struct wl_display *wlDisplay;
    struct wl_registry *wlRegistry;
    struct wl_compositor *wlCompositor;
    struct wl_egl_window *wlNativeWindow;
    struct wl_surface *wlSurface;
    struct wl_shell *wlShell;
    struct wl_shell_surface *wlShellSurface;
    int width;
    int height;
} WLContextStruct;

void handlePing(void *data, struct wl_shell_surface *shellSurface, uint32_t serial) {
    wl_shell_surface_pong(shellSurface, serial);
}

void handleConfigure(void *data, struct wl_shell_surface *shellSurface, uint32_t edges, int32_t width, int32_t height) {
}

void handlePopupDone(void *data, struct wl_shell_surface *shellSurface) {
}

const struct wl_shell_surface_listener shellSurfaceListener = {
    handlePing,
    handleConfigure,
    handlePopupDone,
};

void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) {
    Navinfo::WLContextStruct *p_wlCtx = (Navinfo::WLContextStruct *)data;
    if (0 == strcmp(interface, "wl_compositor")) {
        p_wlCtx->wlCompositor = (wl_compositor *)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
    } else if (0 == strcmp(interface, "wl_compositor")) {
        p_wlCtx->wlShell = (struct wl_shell *)wl_registry_bind(registry, id, &wl_shell_interface, 1);
    }
}

const struct wl_registry_listener registry_listener = {
    registry_handle_global,
    NULL,
};

int main() {
    // wayland part
    unsigned int surfaceWidth = 800;
    unsigned int surfaceHeight = 600;
    WLContextStruct wlContextStruct;
    memset(&wlContextStruct, 0, sizeof(wlContextStruct));

    wlContextStruct.wlDisplay = wl_display_connect("wayland-1");
    if (NULL == wlContextStruct.wlDisplay) {
        LOG_INFO("failed to connect to Wayland display");
        return 1;
    }

    wlContextStruct.wlRegistry = wl_display_get_registry(wlContextStruct.wlDisplay);
    wl_registry_add_listener(wlContextStruct.wlRegistry, &registry_listener, &wlContextStruct);
    wl_display_dispatch(wlContextStruct.wlDisplay);
    wl_display_roundtrip(wlContextStruct.wlDisplay);

    wlContextStruct.wlSurface = wl_compositor_create_surface(wlContextStruct.wlCompositor);

    wlContextStruct.wlShellSurface = wl_shell_get_shell_surface(wlContextStruct.wlShell, wlContextStruct.wlSurface);
    wl_shell_surface_add_listener(reinterpret_cast<struct wl_shell_surface *>(wlContextStruct.wlShellSurface), &shellSurfaceListener, &wlContextStruct);

    wlContextStruct.wlNativeWindow = wl_egl_window_create(wlContextStruct.wlSurface, surfaceWidth, surfaceHeight);

    wl_shell_surface_set_title(wlContextStruct.wlShellSurface, "Hi_WL");
    wl_shell_surface_set_toplevel(wlContextStruct.wlShellSurface);

    // egl part
    EGLNativeWindowType eglWindow = (EGLNativeWindowType)wlContextStruct.wlNativeWindow;
    EGLDisplay eglDisplay = eglGetDisplay((EGLNativeDisplayType)wlContextStruct.wlDisplay);

    EGLint major, minor;
    eglInitialize(eglDisplay, &major, &minor);

    eglBindAPI(EGL_OPENGL_ES_API);

    EGLint count;
    if (!eglGetConfigs(eglDisplay, nullptr, 0, &count) || count < 1) {
        return 1;
    }

    EGLConfig configFound;
    EGLConfig *configs = static_cast<EGLConfig *>(malloc(count * sizeof(EGLConfig)));
    if(configs)
    {
        memset(configs, 0, count * sizeof(EGLConfig));
        static const EGLint kConfigAttributes[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_ALPHA_SIZE, 8,
            EGL_DEPTH_SIZE, 24,
            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
            EGL_NONE};
        EGLint n;
        ret = eglChooseConfig(eglDisplay, kConfigAttributes, configs, count, &n);
        if ((ret != EGL_TRUE) || (n < 1)) {
            return 1;
        }

        configFound = configs[0];

        free(configs);
        configs = nullptr;
    }

    static const EGLint kContextAttibutes[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };

    EGLContext eEglContext = eglCreateContext(eglDisplay, configFound, EGL_NO_CONTEXT, kContextAttibutes);
    if (eEglContext == EGL_NO_CONTEXT) {
        return 1;
    }

    EGLSurface eglSurface = eglCreateWindowSurface(eglDisplay, configFound, (EGLNativeWindowType)eglWindow, nullptr);
    ret = eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eEglContext);
    if (ret != EGL_TRUE) {
        return 1;
    }

    // render part
    while (true)
    {
        // render ...
        eglSwapBuffers(eglDisplay, eglSurface);
    }

    return 0;
}