參考資訊:
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 -lGLESv2 -lEGL $ ./main