Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-07-01 04:00:52 +03:00
parent bdb9d472de
commit 470c248bcf
11 changed files with 626 additions and 11 deletions

153
src/LunarWM.cppm Normal file
View File

@@ -0,0 +1,153 @@
module;
#include <memory>
#include <poll.h>
#include <print>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <wayland-server.h>
export module LunarWM.LunarWM;
import LunarWM.wl.Subcompositor;
import LunarWM.wl.Shm;
namespace LunarWM {
export struct LunarWM {
LunarWM();
~LunarWM();
void run();
void terminate();
private:
struct {
wl_display *display = nullptr;
wl_event_loop *event_loop = nullptr;
std::string socket;
std::unique_ptr<Shm> shm;
wl_global *subcompositor = nullptr;
} m_wayland;
struct {
EGLDisplay display = EGL_NO_DISPLAY;
EGLConfig config;
EGLContext context;
} m_egl;
bool m_running = true;
};
LunarWM::LunarWM() {
{ // Wayland
m_wayland.display = wl_display_create();
if (!m_wayland.display)
throw std::runtime_error("Failed to create wayland display");
auto const socket = wl_display_add_socket_auto(m_wayland.display);
if (!socket)
throw std::runtime_error("Failed to add socket");
m_wayland.socket = socket;
setenv("WAYLAND_DISPLAY", m_wayland.socket.c_str(), 1);
m_wayland.event_loop = wl_display_get_event_loop(m_wayland.display);
if (!m_wayland.event_loop)
throw std::runtime_error("Failed to get display event loop");
}
{ // EGL
m_egl.display = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA,
EGL_DEFAULT_DISPLAY, nullptr);
bool ret = eglInitialize(m_egl.display, nullptr, nullptr);
if (ret != EGL_TRUE)
throw std::runtime_error("eglInitialize failed");
// clang-format off
EGLint attribs[] {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
// clang-format on
EGLint num_configs;
ret =
eglChooseConfig(m_egl.display, attribs, &m_egl.config, 1, &num_configs);
if (!num_configs || ret != EGL_TRUE)
throw std::runtime_error("eglChooseConfig failed");
ret = eglBindAPI(EGL_OPENGL_ES_API);
if (ret != EGL_TRUE)
throw std::runtime_error("eglBindAPI failed");
// clang-format off
EGLint ctx_attribs[] {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE,
};
// clang-format on
m_egl.context =
eglCreateContext(m_egl.display, m_egl.config, nullptr, ctx_attribs);
if (m_egl.context == EGL_NO_CONTEXT)
throw std::runtime_error("eglCreateContext failed");
EGLint pb_attribs[]{EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface pb =
eglCreatePbufferSurface(m_egl.display, m_egl.config, pb_attribs);
if (pb == EGL_NO_SURFACE)
throw std::runtime_error("eglCreatePbufferSurface failed");
if (eglMakeCurrent(m_egl.display, pb, pb, m_egl.context) != EGL_TRUE)
throw std::runtime_error("eglMakeCurrent failed");
std::println("GL ES version: {}",
reinterpret_cast<const char *>(glGetString(GL_VERSION)));
}
{ // Wayland part 2: Electric boogaloo
m_wayland.shm = std::make_unique<Shm>(m_wayland.display);
m_wayland.subcompositor = subcompositor_create(m_wayland.display);
if (!m_wayland.subcompositor)
throw std::runtime_error("Failed to create subcompositor");
}
}
LunarWM::~LunarWM() {
{ // Wayland second initialization block
if (m_wayland.subcompositor)
wl_global_destroy(m_wayland.subcompositor);
if (m_wayland.shm)
m_wayland.shm.reset();
}
{ // EGL
if (m_egl.display != EGL_NO_DISPLAY)
eglDestroyContext(m_egl.display, m_egl.context);
}
{ // Wayland
if (m_wayland.display)
wl_display_destroy(m_wayland.display);
}
std::println("bai bai~!");
}
void LunarWM::run() {
std::println("Running wayland compositor on WAYLAND_DISPLAY={}.",
m_wayland.socket);
while (m_running) {
if (wl_event_loop_dispatch(m_wayland.event_loop, 0) < 0) {
break;
}
wl_display_flush_clients(m_wayland.display);
}
}
void LunarWM::terminate() { m_running = false; }
} // namespace LunarWM