wip: x11 -> wayland transition
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
2c5b59eba6
commit
abe2c6e1e1
1 changed files with 244 additions and 2 deletions
|
|
@ -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 ®istry, 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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue