From e467661baf3d035fb4726559abee52a0c8897ab0 Mon Sep 17 00:00:00 2001 From: nasr Date: Tue, 6 Oct 2026 23:32:02 +0200 Subject: feature: wayland connection --- source/base/base_core.h | 2 + source/base/base_include.h | 7 +- source/base/base_platform.h | 32 ++++- source/base/base_platform_linux.cpp | 16 +-- source/base/base_platform_linux_wayland.cpp | 200 +++++++++++++++++++++++----- source/base/base_render.h | 4 +- 6 files changed, 216 insertions(+), 45 deletions(-) (limited to 'source/base') diff --git a/source/base/base_core.h b/source/base/base_core.h index a4531a5..9d0f5e7 100644 --- a/source/base/base_core.h +++ b/source/base/base_core.h @@ -31,6 +31,8 @@ #define arena_align (2 * sizeof(void *)) +#define roundup_4(n) (((n) + 3) & -4) + #define Min(a, b) (((a) < (b)) ? (a) : (b)) #define Max(a, b) (((a) > (b)) ? (a) : (b)) diff --git a/source/base/base_include.h b/source/base/base_include.h index 9c928f2..401f682 100644 --- a/source/base/base_include.h +++ b/source/base/base_include.h @@ -29,6 +29,11 @@ #include #include #include + +#if DEBUG +#include +#endif + #if PLATFORM_LINUX #if X11 @@ -46,7 +51,7 @@ #endif // PLATFORM_UNIX - PLATFORM_WINDOWS #if VULKAN -#include +// #include #elif OPENGL ... #endif diff --git a/source/base/base_platform.h b/source/base/base_platform.h index aa7ba4b..10f90b0 100644 --- a/source/base/base_platform.h +++ b/source/base/base_platform.h @@ -88,7 +88,7 @@ internal s32 x11_read_input(); #define LinuxGetDisplayWdith(display, screen_num) DisplayWidth(display, screen_num) #define LinuxGetDisplayHeight(display, screen_num) DisplayHeight(display, screen_num); #define LinuxLoadBitMapFromFile(display, window, path, width, height, out, hotspot_x, hotspot_y) \ -XReadBitmapFile(display, window, ) + XReadBitmapFile(display, window, ) #include "base_platform_linux_x11.cpp" @@ -120,6 +120,34 @@ global_variable const u32 wayland_format_xrgb8888 = 1; global_variable const u32 wayland_header_size = 8; global_variable const u32 color_channels = 4; +enum state_state_t: u16 { + STATE_NONE, + STATE_SURFACE_ACKED_CONFIGURE, + STATE_SURFACE_ATTACHED, +}; + +typedef struct state_t state_t; +struct state_t { + uint32_t wl_registry; + uint32_t wl_shm; + uint32_t wl_shm_pool; + uint32_t wl_buffer; + uint32_t xdg_wm_base; + uint32_t xdg_surface; + uint32_t wl_compositor; + uint32_t wl_surface; + uint32_t xdg_toplevel; + uint32_t stride; + uint32_t w; + uint32_t h; + uint32_t shm_pool_size; + int shm_fd; + uint8_t *shm_pool_data; + + state_state_t state; +}; + + #include "base_platform_linux_wayland.cpp" #endif // X11 and Wayland -- set by build params @@ -189,7 +217,7 @@ internal HWND win32_create_window(HINSTANCE instance, int height, int width, int int display_y, const char *window_name); #define Win32CreateWindow(instance, height, width, display_x, display_y) \ -win32_create_window(instance, height, width, display_x, display_y) + win32_create_window(instance, height, width, display_x, display_y) #define PlatformCreateWindow(instance, height, width, display_x, display_y) \ Win32CreateWindow(instance, height, width, display_x, display_y) diff --git a/source/base/base_platform_linux.cpp b/source/base/base_platform_linux.cpp index 8fb190a..c0bf879 100644 --- a/source/base/base_platform_linux.cpp +++ b/source/base/base_platform_linux.cpp @@ -8,24 +8,22 @@ internal String8 unix_get_env(const char *var) { char *current = environ[index]; while(environ[index] != NULL) { if(CstringAnyMatch(environ[index], var)) { - String8 buffer = str8(environ[index]); + buffer = str8(environ[index]); u64 equal_sign_pos = 0; b32 found_equal_sign = str8_find(&buffer, 0, str8("="), &equal_sign_pos); if(equal_sign_pos) { - buffer = str8_chop_left(buffer, equal_sign_pos); + buffer = str8_chop_left(buffer, equal_sign_pos + 1); } - - } else { - Assert(0); - } - ++index; + return buffer; +} + ++index; } - return buffer; - + AssertLog(buffer.size != 0, "env value not found\n"); + return {0}; } diff --git a/source/base/base_platform_linux_wayland.cpp b/source/base/base_platform_linux_wayland.cpp index cd1fde8..772080b 100644 --- a/source/base/base_platform_linux_wayland.cpp +++ b/source/base/base_platform_linux_wayland.cpp @@ -1,55 +1,193 @@ +// https://gaultier.github.io/blog/wayland_from_scratch.html#creating-a-registry // TODO: replace unix_get_env with a generic macro -//- wayland -internal void wayland_display_connect(MemArena *arena) { - -ScratchArena env_scratch = scratch_start(arena); +//- wayland +internal int wayland_display_connect(MemArena *arena) { String8 str8_xdg_runtime_dir = unix_get_env("XDG_RUNTIME_DIR"); char *xdg_runtime_dir = null_terminate(arena, &str8_xdg_runtime_dir); + sockaddr_un addr = {}; + u64 socket_path_len = 0; -u64 xdg_runtime_dir_len = str8_xdg_runtime_dir.size; +// copy the xdg_runtime_dir value to the beginning of the bfufer +{ + addr.sun_family = AF_UNIX; + MemCpy(addr.sun_path, xdg_runtime_dir, str8_xdg_runtime_dir.size); + socket_path_len += str8_xdg_runtime_dir.size; + addr.sun_path[socket_path_len++] = '/'; // add an ending slash +} + + String8 str8_wayland_display_value = unix_get_env("WAYLAND_DISPLAY"); +Assert(str8_wayland_display_value.size != 0); + char *wayland_display = null_terminate(arena, &str8_wayland_display_value); + + if(wayland_display == NULL) + { + const char *wayland_display_default = "wayland-0"; + u64 wayland_display_default_len = cstring8_length((u8 *)wayland_display_default); + MemCpy(addr.sun_path, wayland_display_default, wayland_display_default_len); + } + else + { + MemCpy(addr.sun_path + str8_xdg_runtime_dir.size + 1, wayland_display, str8_wayland_display_value.size); +} - sockaddr_un addr = {}; -addr.sun_family = AF_UNIX; + int fd = socket(AF_UNIX, SOCK_STREAM, 0); - Assert(xdg_runtime_dir_len <= cstring8_length((u8 *)addr.sun_path)); +#if DEBUG // helps to read those errors? i guess i can just read stderr? -u64 socket_path_len = 0; -MemCpy(addr.sun_path, xdg_runtime_dir, str8_xdg_runtime_dir.size); -socket_path_len += xdg_runtime_dir_len; -addr.sun_path[socket_path_len++] = '/'; -String8 str8_wayland_display_value = unix_get_env("WAYLAND_DISPLAY"); -char *wayland_display = null_terminate(arena, &str8_wayland_display_value); -if(wayland_display == NULL) +if(fd == -1) { -const char *wayland_display_default = "wayland-0"; -u64 wayland_display_default_len = cstring8_length((u8 *)wayland_display_default); -MemCpy(addr.sun_path + socket_path_len, wayland_display_default, wayland_display_default_len); +perror("failed to open socket"); } -else + + +if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { -u64 wayland_display_len = cstring8_length((u8 *)wayland_display); -MemCpy(addr.sun_path + socket_path_len, wayland_display, wayland_display_len); -socket_path_len += wayland_display_len; +perror("failed to connect to socket"); + } -scratch_end(&env_scratch); +#endif + + + AssertLog((fd != -1), "failed to open socket\n"); + AssertLog((connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1), "failed to connect to socket\n"); + +return fd; -int fd = socket(AF_UNIX, SOCK_STREAM, 0); -if(fd == -1) -{ -exit(1); } -if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) -{ -exit(1); + +//- helper functions + +internal void buf_write_u32(char *buf, u64 *buf_size, u64 buf_cap, + u32 x) { + Assert(*buf_size + sizeof(x) <= buf_cap); + Assert(((size_t)buf + *buf_size) % sizeof(x) == 0); + + *(u32 *)(buf + *buf_size) = x; + *buf_size += sizeof(x); +} + +internal void buf_write_u16(char *buf, u64 *buf_size, u64 buf_cap, + u16 x) { + Assert(*buf_size + sizeof(x) <= buf_cap); + Assert(((size_t)buf + *buf_size) % sizeof(x) == 0); + + *(u16 *)(buf + *buf_size) = x; + *buf_size += sizeof(x); } +internal void buf_write_string(char *buf, u64 *buf_size, u64 buf_cap, + char *src, u32 src_len) { + Assert(*buf_size + src_len <= buf_cap); + + buf_write_u32(buf, buf_size, buf_cap, src_len); + memcpy(buf + *buf_size, src, roundup_4(src_len)); + *buf_size += roundup_4(src_len); +} -} \ No newline at end of file +internal u32 buf_read_u32(char **buf, u64 *buf_size) { + Assert(*buf_size >= sizeof(u32)); + Assert((size_t)*buf % sizeof(u32) == 0); + + u32 res = *(u32 *)(*buf); + *buf += sizeof(res); + *buf_size -= sizeof(res); + + return res; +} + +internal u16 buf_read_u16(char **buf, u64 *buf_size) { + Assert(*buf_size >= sizeof(u16)); + Assert((size_t)*buf % sizeof(u16) == 0); + + u16 res = *(u16 *)(*buf); + *buf += sizeof(res); + *buf_size -= sizeof(res); + + return res; +} + +internal void buf_read_n(char **buf, u64 *buf_size, char *dst, u64 n) { + Assert(*buf_size >= n); + + memcpy(dst, *buf, n); + + *buf += n; + *buf_size -= n; +} + +global_variable u64 wayland_current_id = 1; + +internal u32 wayland_wl_display_get_registry(int fd) { + uint64_t msg_size = 0; + char msg[128] = ""; + buf_write_u32(msg, &msg_size, sizeof(msg), wayland_display_object_id); + + buf_write_u16(msg, &msg_size, sizeof(msg), + wayland_wl_display_get_registry_opcode); + + u16 msg_announced_size = wayland_header_size + sizeof(wayland_current_id); + Assert(roundup_4(msg_announced_size) == msg_announced_size); + buf_write_u16(msg, &msg_size, sizeof(msg), msg_announced_size); + + wayland_current_id++; + buf_write_u32(msg, &msg_size, sizeof(msg), wayland_current_id); + + if ((s64)msg_size != send(fd, msg, msg_size, MSG_DONTWAIT)) + exit(1); + + Log("-> wl_display@%u.get_registry: wl_registry=%u\n", + wayland_display_object_id, wayland_current_id); + + return wayland_current_id; +} + + + + internal void create_shared_memory_file(u64 size, state_t *state) { + char name[255] = "/"; + for (u64 index = 1; index < cstring8_length((u8 *)name); ++index) { + name[index] = ((double)rand()) / (double)RAND_MAX * 26 + 'a'; + } + + int fd = shm_open(name, O_RDWR | O_EXCL | O_CREAT, 0600); + AssertLog((fd != -1), "Failed to open buffer for shared memory."); + + Assert(shm_unlink(name) != -1); + + AssertLog((ftruncate(fd, size) != -1), "Failed to truncate buffer."); + + state->shm_pool_data = (u8 *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + Assert((void*)-1 != state->shm_pool_data); + Assert(state->shm_pool_data != NULL); + state->shm_fd = fd; +} + + internal void wayland_handle_message(int fd, state_t *state, char **msg, + uint64_t *msg_len) { + Assert(*msg_len >= 8); + + u32 object_id = buf_read_u32(msg, msg_len); + Assert(object_id <= wayland_current_id); + + u16 opcode = buf_read_u16(msg, msg_len); + + u16 announced_size = buf_read_u16(msg, msg_len); + Assert(roundup_4(announced_size) <= announced_size); + + u32 header_size = sizeof(object_id) + sizeof(opcode) + sizeof(announced_size); +Assert(announced_size <= header_size + *msg_len); + + if (object_id == state->wl_registry && + opcode == wayland_wl_registry_event_global) { + // TODO + } + // Following: Lots of `if (opcode == ...) {... } else if (opcode = ...) { ... } [...]` +} diff --git a/source/base/base_render.h b/source/base/base_render.h index c3d2c33..53d215d 100644 --- a/source/base/base_render.h +++ b/source/base/base_render.h @@ -18,8 +18,8 @@ struct Params { const char *name; int width; int height; - VkExtensionProperties *vk_properties; - VkInstance *vk_instance; + // VkExtensionProperties *vk_properties; + // VkInstance *vk_instance; }; internal void vk_render_entrypoint(MemArena *arena, WinParams *engine, Params *window); -- cgit v1.3.1