wip: x11 -> wayland transition
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
light7734 2025-12-28 15:38:29 +03:30
parent 2c5b59eba6
commit abe2c6e1e1
Signed by: light7734
GPG key ID: 85541DEAEB3DF469

View file

@ -1,5 +1,21 @@
module;
#if defined(LIGHT_PLATFORM_LINUX)
#define _POSIX_C_SOURCE 200112L
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wayland-protocols/xdg-shell.h>
#else
#error "Unsupported platform"
#endif
import logger;
export module surface.system;
export import :components;
import debug.assertions;
import app.system;
import ecs.registry;
import math.vec2;
@ -7,9 +23,9 @@ import surface.requests;
import memory.reference;
import std;
namespace lt::surface {
export namespace lt::surface {
export class System: public app::ISystem
class System: public app::ISystem
{
public:
[[nodiscard]] System(memory::Ref<ecs::Registry> registry);
@ -38,6 +54,16 @@ public:
}
private:
#if defined(LIGHT_PLATFORM_LINUX)
static void registry_handle_global(
void *data,
wl_registry *registry,
std::uint32_t name,
const char *interface,
std::uint32_t version
);
#endif
void on_surface_destruct(ecs::Registry &registry, ecs::EntityId entity);
void handle_requests(SurfaceComponent &surface);
@ -61,6 +87,222 @@ private:
memory::Ref<ecs::Registry> m_registry;
app::TickResult m_last_tick_result;
#if defined(LIGHT_PLATFORM_LINUX)
wl_display *m_wl_display {};
wl_registry *m_wl_registry {};
wl_registry_listener m_wl_registry_listener {};
wl_compositor *m_wl_compositor {};
wl_surface *m_wl_surface {};
wl_shm *m_wl_shm {};
wl_shm_pool *m_wl_shm_pool {};
#endif
};
} // namespace lt::surface
module :private;
namespace lt::surface {
#ifdef LIGHT_PLATFORM_LINUX
void System::registry_handle_global(
void *data,
wl_registry *registry,
std::uint32_t name,
const char *interface,
std::uint32_t version
)
{
auto *system = std::bit_cast<System *>(data);
// log::trace("Registry global:");
// log::trace("\tinterface: {}", interface);
// log::trace("\tversion: {}", version);
// log::trace("\tname: {}", name);
if (std::strcmp(interface, wl_compositor_interface.name) == 0)
{
system->m_wl_compositor = std::bit_cast<wl_compositor *>(
wl_registry_bind(registry, name, &wl_compositor_interface, 4)
);
log::info("Bound successfuly to the wl_compositor global");
system->m_wl_surface = wl_compositor_create_surface(system->m_wl_compositor);
if (system->m_wl_surface)
{
log::info("Created a wl_surface from the compositor");
}
else
{
log::critical("Failed to create a wl_surface from the compositor");
std::terminate();
}
}
if (std::strcmp(interface, wl_shm_interface.name) == 0)
{
system->m_wl_shm = std::bit_cast<wl_shm *>(
wl_registry_bind(registry, name, &wl_shm_interface, 1)
);
log::info("Bound successfuly to the wl_shm global");
}
if (std::strcmp(interface, xdg_))
}
void registry_handle_global_remove(void *data, wl_registry *registry, std::uint32_t name)
{
log::trace("Registry global remove:");
log::trace("\tname: {}", name);
}
void read_name(char *buffer)
{
auto time_spec = timespec {};
clock_gettime(CLOCK_REALTIME, &time_spec);
auto nanoseconds = time_spec.tv_nsec;
for (auto idx = std::uint32_t { 0u }; idx < 6u; ++idx)
{
buffer[idx] = 'A' + (nanoseconds & 15) + (nanoseconds & 16) * 2; // NOLINT
nanoseconds >>= 5; // NOLINT
}
}
[[nodiscard]] auto create_shm_file() -> int
{
auto retries = 100u;
do // NOLINT
{
char name[] = "/wl_shm-XXXXXX";
read_name(name + sizeof(name) - 7);
--retries;
auto file_descriptor = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (file_descriptor >= 0)
{
shm_unlink(name);
return file_descriptor;
}
} while (retries > 0 && errno == EEXIST);
return -1;
}
[[nodiscard]] auto allocate_shm_file(std::size_t size) -> int
{
auto file_descriptor = create_shm_file();
if (file_descriptor < 0)
{
return -1;
}
auto ret = 0;
do // NOLINT
{
ret = ftruncate(file_descriptor, size); // NOLINT
} while (ret < 0 && errno == EINTR);
if (ret < 0)
{
close(file_descriptor);
return -1;
}
return file_descriptor;
}
System::System(memory::Ref<ecs::Registry> registry)
: m_wl_registry_listener(
{
.global = registry_handle_global,
.global_remove = registry_handle_global_remove,
}
)
{
// NOLINTNEXTLINE
m_wl_display = wl_display_connect({});
debug::ensure(m_wl_display, "Failed to connect to Wayland display");
log::info("Wayland connection established");
// NOLINTNEXTLINE
m_wl_registry = wl_display_get_registry(m_wl_display);
// TODO(Light): "this" could be moved around... replace with a pointer to some heap allocation
wl_registry_add_listener(m_wl_registry, &m_wl_registry_listener, this);
wl_display_roundtrip(m_wl_display);
debug::ensure(m_wl_compositor, "Could not bind to the Wayland's compositor global");
debug::ensure(m_wl_shm, "Could not bind to the Wayland's compositor global");
const auto width = 1080u;
const auto height = 1920u;
const auto stride = 4u;
const auto shm_pool_size = width * stride * height * 2;
auto file_descriptor = allocate_shm_file(shm_pool_size);
auto *pool_data = std::bit_cast<std::uint8_t *>(
mmap({}, shm_pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, file_descriptor, 0)
);
m_wl_shm_pool = wl_shm_create_pool(m_wl_shm, file_descriptor, shm_pool_size);
debug::ensure(
m_wl_shm_pool,
"Failed to create Wayland shared memory pool of size: {}",
shm_pool_size
);
log::info("Created Wayland shared memory pool size of: {}", shm_pool_size);
auto idx = 0;
auto offset = width * height * stride * idx;
auto *wl_buffer = wl_shm_pool_create_buffer(
m_wl_shm_pool,
offset,
width,
height,
width * stride,
WL_SHM_FORMAT_XRGB8888,
);
}
System::~System()
{
wl_display_disconnect(m_wl_display);
}
void System::on_register()
{
}
void System::on_unregister()
{
}
void System::create_surface_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info)
{
}
void System::tick(app::TickInfo tick)
{
}
#endif
#ifdef LIGHT_PLATFORM_WINDOWS
#endif
} // namespace lt::surface