程式語言 - Wayland - Client - OpenGL ES 2.0 - Use Texture



參考資訊:
https://jan.newmarch.name/Wayland/index.html
https://wayland.freedesktop.org/docs/html/apa.html
https://bugaevc.gitbooks.io/writing-wayland-clients/content/

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <wayland-client.h>
#include <wayland-egl.h>

#include <EGL/egl.h>
#include <GLES2/gl2.h>

#define LCD_W 1080
#define LCD_H 2160
#define BUF_W 320
#define BUF_H 240

struct wl_shell *shell = NULL;
struct wl_display *dis = NULL;
struct wl_surface *surf = NULL;
struct wl_registry *reg = NULL;
struct wl_region *regn = NULL;
struct wl_compositor *comp = NULL;
struct wl_egl_window *egl_win = NULL;
struct wl_shell_surface *shell_surf = NULL;

EGLConfig egl_conf = 0;
EGLContext egl_ctx = 0;
EGLDisplay egl_dis = 0;
EGLSurface egl_surf = 0;

EGLint egl_attribs[] = {
    EGL_SURFACE_TYPE,
    EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE,
    EGL_OPENGL_ES2_BIT,
    EGL_RED_SIZE,
    8,
    EGL_GREEN_SIZE,
    8,
    EGL_BLUE_SIZE,
    8,
    EGL_NONE
};

EGLint ctx_attribs[] = {
    EGL_CONTEXT_CLIENT_VERSION, 
    2, 
    EGL_NONE
};

GLubyte pixels[BUF_W * BUF_H * 3] = {0};

GLfloat vVertices[] = {
    -1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 
    -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
     1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 
     1.0f,  1.0f, 0.0f, 1.0f, 0.0f
};

GLushort indices[] = {0, 1, 2, 0, 2, 3};

const char *vShaderSrc =
    "attribute vec4 a_position;   \n"
    "attribute vec2 a_texCoord;   \n"
    "varying vec2 v_texCoord;     \n"
    "void main()                  \n"
    "{                            \n"
    "   gl_Position = a_position; \n"
    "   v_texCoord = a_texCoord;  \n"
    "}                            \n";

const char *fShaderSrc =
    "#ifdef GL_ES                                         \n"
    "precision mediump float;                             \n"
    "#endif                                               \n"
    "varying vec2 v_texCoord;                             \n"
    "uniform sampler2D s_texture;                         \n"
    "void main()                                          \n"
    "{                                                    \n"
    "    gl_FragColor = texture2D(s_texture, v_texCoord); \n"
    "}                                                    \n";

void cb_handle(void *dat, struct wl_registry *reg, uint32_t id, const char *intf, uint32_t ver)
{
    if (strcmp(intf, "wl_compositor") == 0) {
        comp = wl_registry_bind(reg, id, &wl_compositor_interface, 3);
    }
    else if (strcmp(intf, "wl_shell") == 0) {
        shell = wl_registry_bind(reg, id, &wl_shell_interface, 1);
    }
}

void cb_remove(void *dat, struct wl_registry *reg, uint32_t id)
{
}

struct wl_registry_listener cb = {
    .global = cb_handle,
    .global_remove = cb_remove
};

int main(int argc, char **argv)
{
    dis = wl_display_connect(NULL);
    reg = wl_display_get_registry(dis);

    wl_registry_add_listener(reg, &cb, NULL);
    wl_display_dispatch(dis);
    wl_display_roundtrip(dis);

    surf = wl_compositor_create_surface(comp);
    shell_surf = wl_shell_get_shell_surface(shell, surf);
    wl_shell_surface_set_toplevel(shell_surf);

    regn = wl_compositor_create_region(comp);
    wl_region_add(regn, 0, 0, LCD_W, LCD_H);
    wl_surface_set_opaque_region(surf, regn);
    egl_win = wl_egl_window_create(surf, LCD_W, LCD_H);

    EGLConfig cfg = 0;
    EGLint major = 0, minor = 0, cnt = 0;

    egl_dis = eglGetDisplay((EGLNativeDisplayType)dis);
    eglInitialize(egl_dis, &major, &minor);
    eglGetConfigs(egl_dis, NULL, 0, &cnt);
    eglChooseConfig(egl_dis, egl_attribs, &cfg, 1, &cnt);
    egl_surf = eglCreateWindowSurface(egl_dis, cfg, egl_win, NULL);
    egl_ctx = eglCreateContext(egl_dis, cfg, EGL_NO_CONTEXT, ctx_attribs);
    eglMakeCurrent(egl_dis, egl_surf, egl_surf, egl_ctx);

    GLuint vShader = 0;
    GLuint fShader = 0;
    GLuint pObject = 0;

    vShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vShader, 1, &vShaderSrc, NULL);
    glCompileShader(vShader);

    fShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShader, 1, &fShaderSrc, NULL);
    glCompileShader(fShader);

    pObject = glCreateProgram();
    glAttachShader(pObject, vShader);
    glAttachShader(pObject, fShader);
    glLinkProgram(pObject);
    glUseProgram(pObject);

    GLuint textureId = 0;
    GLint positionLoc = glGetAttribLocation(pObject, "a_position");
    GLint texCoordLoc = glGetAttribLocation(pObject, "a_texCoord");
    GLint samplerLoc = glGetUniformLocation(pObject, "s_texture");

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glViewport(0, 0, LCD_W, LCD_H);
    glClear(GL_COLOR_BUFFER_BIT);
    glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices);
    glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]);
    glEnableVertexAttribArray(positionLoc);
    glEnableVertexAttribArray(texCoordLoc);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glUniform1i(samplerLoc, 0);

    int cc = 0;
    while (1) {
        int x = 0, y = 0;
        for (y = 0; y < BUF_H; y++) {
            for (x = 0; x < BUF_W; x++) {
                switch (cc % 3) {
                case 0:
                    pixels[(y * BUF_W * 3) + (x * 3) + 0] = 0xff;
                    pixels[(y * BUF_W * 3) + (x * 3) + 1] = 0x00;
                    pixels[(y * BUF_W * 3) + (x * 3) + 2] = 0x00;
                    break;
                case 1:
                    pixels[(y * BUF_W * 3) + (x * 3) + 0] = 0x00;
                    pixels[(y * BUF_W * 3) + (x * 3) + 1] = 0xff;
                    pixels[(y * BUF_W * 3) + (x * 3) + 2] = 0x00;
                    break;
                case 2:
                    pixels[(y * BUF_W * 3) + (x * 3) + 0] = 0x00;
                    pixels[(y * BUF_W * 3) + (x * 3) + 1] = 0x00;
                    pixels[(y * BUF_W * 3) + (x * 3) + 2] = 0xff;
                    break;
                }
            }
        }

        cc+= 1;
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, BUF_W, BUF_H, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
        eglSwapBuffers(egl_dis, egl_surf);
    }

    eglDestroySurface(egl_dis, egl_surf);
    eglDestroyContext(egl_dis, egl_ctx);
    wl_egl_window_destroy(egl_win);
    eglTerminate(egl_dis);

    wl_region_destroy(regn);
    wl_shell_surface_destroy(shell_surf);
    wl_shell_destroy(shell);
    wl_surface_destroy(surf);
    wl_compositor_destroy(comp);
    wl_registry_destroy(reg);
    wl_display_disconnect(dis);
    return 0;
}

編譯

$ gcc main.c -o main -lwayland-client -lwayland-egl -lEGL -lGLESv2