Created
March 27, 2025 16:23
-
-
Save gulafaran/31c6a7f2bcffd13f0e2573b25e54da50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <wayland-client.h> | |
#include <wayland-egl.h> | |
#include <EGL/egl.h> | |
#include <EGL/eglplatform.h> | |
#include <GLES2/gl2.h> | |
#include "xdg-shell-client-protocol.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
const int SCREEN_WIDTH = 512; | |
const int SCREEN_HEIGHT = 512; | |
struct wl_display* display; | |
struct wl_registry* registry; | |
struct wl_compositor* compositor; | |
struct wl_surface* surface; | |
struct xdg_wm_base* wm_base; | |
struct xdg_surface* xdg_surface; | |
struct xdg_toplevel* xdg_toplevel; | |
struct wl_egl_window* egl_window; | |
EGLDisplay egl_display; | |
EGLContext egl_context; | |
EGLSurface egl_surface; | |
GLuint shader_program, vbo, vao, texture; | |
const char* vertex_shader_src = "#version 100\n" | |
"attribute vec2 a_position;\n" | |
"attribute vec2 a_texcoord;\n" | |
"varying vec2 v_texcoord;\n" | |
"void main() {\n" | |
" gl_Position = vec4(a_position, 0.0, 1.0);\n" | |
" v_texcoord = a_texcoord;\n" | |
"}"; | |
const char* fragment_shader_src = "#version 100\n" | |
"precision mediump float;\n" | |
"varying vec2 v_texcoord;\n" | |
"uniform sampler2D u_texture;\n" | |
"void main() {\n" | |
" gl_FragColor = texture2D(u_texture, v_texcoord);\n" | |
"}"; | |
void registry_handler(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version) { | |
if (strcmp(interface, "wl_compositor") == 0) { | |
compositor = wl_registry_bind(registry, id, &wl_compositor_interface, version < 4 ? version : 4); | |
} else if (strcmp(interface, "xdg_wm_base") == 0) { | |
wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, version < 3 ? version : 3); | |
} | |
} | |
void registry_remover(void* data, struct wl_registry* registry, uint32_t id) {} | |
const struct wl_registry_listener registry_listener = { | |
registry_handler, | |
registry_remover | |
}; | |
void init_wayland() { | |
display = wl_display_connect(NULL); | |
if (!display) { | |
fprintf(stderr, "Failed to connect to Wayland display\n"); | |
exit(1); | |
} | |
registry = wl_display_get_registry(display); | |
wl_registry_add_listener(registry, ®istry_listener, NULL); | |
wl_display_roundtrip(display); | |
if (!compositor || !wm_base) { | |
fprintf(stderr, "Failed to get Wayland compositor or XDG WM Base\n"); | |
exit(1); | |
} | |
surface = wl_compositor_create_surface(compositor); | |
xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, surface); | |
xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); | |
xdg_toplevel_set_title(xdg_toplevel, "OpenGL Wayland Window"); | |
wl_surface_commit(surface); | |
} | |
void init_egl() { | |
egl_display = eglGetDisplay((EGLNativeDisplayType)display); | |
eglInitialize(egl_display, NULL, NULL); | |
EGLConfig config; | |
EGLint num_config; | |
EGLint attributes[] = { | |
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
EGL_RED_SIZE, 8, | |
EGL_GREEN_SIZE, 8, | |
EGL_BLUE_SIZE, 8, | |
EGL_ALPHA_SIZE, 8, | |
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
EGL_NONE | |
}; | |
eglChooseConfig(egl_display, attributes, &config, 1, &num_config); | |
egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, NULL); | |
egl_window = wl_egl_window_create(surface, SCREEN_WIDTH, SCREEN_HEIGHT); | |
egl_surface = eglCreateWindowSurface(egl_display, config, (EGLNativeWindowType)egl_window, NULL); | |
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context); | |
} | |
void check_shader_compile(GLuint shader) { | |
GLint success; | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &success); | |
if (!success) { | |
char info_log[512]; | |
glGetShaderInfoLog(shader, 512, NULL, info_log); | |
fprintf(stderr, "Shader compilation error: %s\n", info_log); | |
exit(1); | |
} | |
} | |
void init_gl() { | |
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); | |
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL); | |
glCompileShader(vertex_shader); | |
check_shader_compile(vertex_shader); | |
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); | |
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL); | |
glCompileShader(fragment_shader); | |
check_shader_compile(fragment_shader); | |
shader_program = glCreateProgram(); | |
glAttachShader(shader_program, vertex_shader); | |
glAttachShader(shader_program, fragment_shader); | |
glLinkProgram(shader_program); | |
glUseProgram(shader_program); | |
// Vertex data (X, Y, U, V) | |
float vertices[] = { | |
-1.0f, -1.0f, 0.0f, 0.0f, | |
1.0f, -1.0f, 1.0f, 0.0f, | |
-1.0f, 1.0f, 0.0f, 1.0f, | |
1.0f, 1.0f, 1.0f, 1.0f | |
}; | |
glGenBuffers(1, &vbo); | |
glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); | |
GLint posAttrib = glGetAttribLocation(shader_program, "a_position"); | |
glEnableVertexAttribArray(posAttrib); | |
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); | |
GLint texAttrib = glGetAttribLocation(shader_program, "a_texcoord"); | |
glEnableVertexAttribArray(texAttrib); | |
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); | |
glGenTextures(1, &texture); | |
glBindTexture(GL_TEXTURE_2D, texture); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
unsigned char pixels[] = { 255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255, 255, 255, 0, 255 }; | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
} | |
int main() { | |
init_wayland(); | |
init_egl(); | |
init_gl(); | |
bool running = true; | |
while (running) { | |
wl_display_dispatch_pending(display); | |
glClear(GL_COLOR_BUFFER_BIT); | |
glUseProgram(shader_program); | |
glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
glEnableVertexAttribArray(0); // Position | |
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); | |
glEnableVertexAttribArray(1); // Texcoord | |
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); | |
glBindTexture(GL_TEXTURE_2D, texture); | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
eglSwapBuffers(egl_display, egl_surface); | |
} | |
wl_display_disconnect(display); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment