From ed429d6a3063b39df5db764ee61f357aff8074e5 Mon Sep 17 00:00:00 2001 From: Slendi Date: Tue, 30 Sep 2025 15:26:30 +0300 Subject: [PATCH] Get window up and running Signed-off-by: Slendi --- flake.lock | 6 +- src/LunarWM_core.c | 211 ++++++++++++++++++++++-------------------- src/LunarWM_types.h | 16 ++++ src/LunarWM_wayland.c | 164 ++++++++++++++++++++++++++++++++ src/LunarWM_xr.c | 12 +-- wlroots-lunar | 2 +- 6 files changed, 300 insertions(+), 111 deletions(-) diff --git a/flake.lock b/flake.lock index ebda95c..cf291a1 100644 --- a/flake.lock +++ b/flake.lock @@ -97,11 +97,11 @@ ] }, "locked": { - "lastModified": 1759180376, - "narHash": "sha256-DaQNW/lQH5HA78Cz/Daoi3G6TmMEbAc2DePkMR9VMFY=", + "lastModified": 1759215258, + "narHash": "sha256-Y7aXk0Zxu+X2BbO5MLkCvClrPsKfZ2sm34N2n7tXx4I=", "owner": "slendidev", "repo": "wlroots-lunar", - "rev": "d0716220ff8bb32889048a3df87b3faf6805aa81", + "rev": "a9abd5a6e4fb4e5ac6c410e1fb1ad438d3b12001", "type": "github" }, "original": { diff --git a/src/LunarWM_core.c b/src/LunarWM_core.c index afeea6a..1163e4a 100644 --- a/src/LunarWM_core.c +++ b/src/LunarWM_core.c @@ -8,7 +8,6 @@ #include "vec.h" #include -#include #include #include #include @@ -199,10 +198,10 @@ bool LunarWM_init(LunarWM *wm) config_manager_reload(wm->cman); } - if (getenv("DISPLAY") != NULL || getenv("WAYLAND_DISPLAY") != NULL) { - wlr_log(WLR_ERROR, "This compositor can only be ran in DRM mode."); - return false; - } + // if (getenv("DISPLAY") != NULL || getenv("WAYLAND_DISPLAY") != NULL) { + // wlr_log(WLR_ERROR, "This compositor can only be ran in DRM mode."); + // return false; + // } if (!LunarWM_wayland_init(wm)) { wlr_log(WLR_ERROR, "Failed to initialize wlroots"); @@ -219,8 +218,11 @@ bool LunarWM_init(LunarWM *wm) } if (!LunarWM_xr_init(wm)) { - wlr_log(WLR_ERROR, "Failed to initialize OpenXR"); - return false; + wlr_log(WLR_ERROR, "Failed to initialize OpenXR! Disabling XR..."); + wm->xr.available = false; + LunarWM_xr_cleanup(wm); + } else { + wm->xr.available = true; } wlr_log(WLR_INFO, "OpenGL ES version: %s", glGetString(GL_VERSION)); @@ -315,101 +317,110 @@ void LunarWM_run(LunarWM *wm) WindowShouldClose(); BeginDrawing(); - LunarWM_xr_poll_events(wm); + if (wm->xr.available) { + LunarWM_xr_poll_events(wm); + + if (!wm->xr.session_running) { + EndDrawing(); + continue; + } + + XrFrameState frame_state = { + .type = XR_TYPE_FRAME_STATE, + }; + XrFrameWaitInfo frame_wait_info = { + .type = XR_TYPE_FRAME_WAIT_INFO, + }; + if (xrWaitFrame(wm->xr.session, &frame_wait_info, &frame_state) + != XR_SUCCESS) { + wlr_log(WLR_ERROR, "Failed to wait for OpenXR frame"); + return; + } + + XrFrameBeginInfo frame_begin_info = { + .type = XR_TYPE_FRAME_BEGIN_INFO, + }; + XrResult res = xrBeginFrame(wm->xr.session, &frame_begin_info); + if (res != XR_FRAME_DISCARDED && res != XR_SUCCESS) { + wlr_log(WLR_ERROR, "Failed to begin the OpenXR Frame: %d", res); + return; + } + + if (wm->xr.hand_tracking_enabled) { + for (size_t i = 0; i < 2; i++) { + LunarWM_Hand *hand = &wm->xr.hands[i]; + bool const unobstructed = true; + if (!wm->xr.LocateHandJointsEXT + || hand->hand_tracker == XR_NULL_HANDLE) { + continue; + } + + XrHandJointsMotionRangeInfoEXT mri = { + .type = XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT, + }; + mri.handJointsMotionRange = unobstructed + ? XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT + : XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT; + + XrHandJointsLocateInfoEXT li = { + .type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, + .next = &mri, + .baseSpace = wm->xr.local_space, + .time = frame_state.predictedDisplayTime, + }; + + XrHandJointLocationsEXT hji = { + .type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT, + .jointCount = XR_HAND_JOINT_COUNT_EXT, + .jointLocations = hand->joint_locations, + }; + + if (wm->xr.LocateHandJointsEXT( + hand->hand_tracker, &li, &hji) + != XR_SUCCESS) { + wlr_log(WLR_ERROR, "Failed to locate hand joints"); + return; + } + } + } + + LunarWM_RenderLayerInfo render_layer_info = { + .predicted_display_time = frame_state.predictedDisplayTime, + .layer_projection.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, + }; + bool const session_active + = (wm->xr.session_state == XR_SESSION_STATE_SYNCHRONIZED) + || (wm->xr.session_state == XR_SESSION_STATE_VISIBLE) + || (wm->xr.session_state == XR_SESSION_STATE_FOCUSED); + if (session_active && (frame_state.shouldRender != 0u)) { + bool rendered + = LunarWM_render_layer(wm, &render_layer_info, dt); + if (rendered) { + render_layer_info.layers[render_layer_info.layers_count] + = (XrCompositionLayerBaseHeader *)&render_layer_info + .layer_projection; + } + } + + XrFrameEndInfo frame_end_info = { + .type = XR_TYPE_FRAME_END_INFO, + .displayTime = frame_state.predictedDisplayTime, + .environmentBlendMode = wm->xr.environment_blend_mode, + .layerCount = render_layer_info.layers_count, + .layers = (XrCompositionLayerBaseHeader const **) + render_layer_info.layers, + }; + if (xrEndFrame(wm->xr.session, &frame_end_info) != XR_SUCCESS) { + wlr_log(WLR_ERROR, "Failed to end OpenXR frame"); + return; + } + + EndDrawing(); + } else { + + ClearBackground(RED); - if (!wm->xr.session_running) { EndDrawing(); - continue; } - - XrFrameState frame_state = { - .type = XR_TYPE_FRAME_STATE, - }; - XrFrameWaitInfo frame_wait_info = { - .type = XR_TYPE_FRAME_WAIT_INFO, - }; - if (xrWaitFrame(wm->xr.session, &frame_wait_info, &frame_state) - != XR_SUCCESS) { - wlr_log(WLR_ERROR, "Failed to wait for OpenXR frame"); - return; - } - - XrFrameBeginInfo frame_begin_info = { - .type = XR_TYPE_FRAME_BEGIN_INFO, - }; - XrResult res = xrBeginFrame(wm->xr.session, &frame_begin_info); - if (res != XR_FRAME_DISCARDED && res != XR_SUCCESS) { - wlr_log(WLR_ERROR, "Failed to begin the OpenXR Frame: %d", res); - return; - } - - if (wm->xr.hand_tracking_enabled) { - for (size_t i = 0; i < 2; i++) { - LunarWM_Hand *hand = &wm->xr.hands[i]; - bool const unobstructed = true; - if (!wm->xr.LocateHandJointsEXT - || hand->hand_tracker == XR_NULL_HANDLE) { - continue; - } - - XrHandJointsMotionRangeInfoEXT mri = { - .type = XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT, - }; - mri.handJointsMotionRange = unobstructed - ? XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT - : XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT; - - XrHandJointsLocateInfoEXT li = { - .type = XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, - .next = &mri, - .baseSpace = wm->xr.local_space, - .time = frame_state.predictedDisplayTime, - }; - - XrHandJointLocationsEXT hji = { - .type = XR_TYPE_HAND_JOINT_LOCATIONS_EXT, - .jointCount = XR_HAND_JOINT_COUNT_EXT, - .jointLocations = hand->joint_locations, - }; - - if (wm->xr.LocateHandJointsEXT(hand->hand_tracker, &li, &hji) - != XR_SUCCESS) { - wlr_log(WLR_ERROR, "Failed to locate hand joints"); - return; - } - } - } - - LunarWM_RenderLayerInfo render_layer_info = { - .predicted_display_time = frame_state.predictedDisplayTime, - .layer_projection.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, - }; - bool const session_active - = (wm->xr.session_state == XR_SESSION_STATE_SYNCHRONIZED) - || (wm->xr.session_state == XR_SESSION_STATE_VISIBLE) - || (wm->xr.session_state == XR_SESSION_STATE_FOCUSED); - if (session_active && (frame_state.shouldRender != 0u)) { - bool rendered = LunarWM_render_layer(wm, &render_layer_info, dt); - if (rendered) { - render_layer_info.layers[render_layer_info.layers_count] - = (XrCompositionLayerBaseHeader *)&render_layer_info - .layer_projection; - } - } - - XrFrameEndInfo frame_end_info = { - .type = XR_TYPE_FRAME_END_INFO, - .displayTime = frame_state.predictedDisplayTime, - .environmentBlendMode = wm->xr.environment_blend_mode, - .layerCount = render_layer_info.layers_count, - .layers - = (XrCompositionLayerBaseHeader const **)render_layer_info.layers, - }; - if (xrEndFrame(wm->xr.session, &frame_end_info) != XR_SUCCESS) { - wlr_log(WLR_ERROR, "Failed to end OpenXR frame"); - return; - } - - EndDrawing(); } } diff --git a/src/LunarWM_types.h b/src/LunarWM_types.h index 008b05f..88d9f79 100644 --- a/src/LunarWM_types.h +++ b/src/LunarWM_types.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,15 @@ typedef struct { struct wl_listener destroy; } LunarWM_Pointer; +typedef struct { + struct LunarWM *wm; + struct wlr_output *wlr_output; + + struct wl_listener frame; + struct wl_listener destroy; +} LunarWM_Output; + + typedef struct { uint32_t id; @@ -212,9 +222,15 @@ typedef struct LunarWM { LunarWM_Toplevel **v_toplevels; int current_focus; + + struct wl_listener new_output_listener; + LunarWM_Output **v_outputs; + } wayland; struct { + bool available; + XrInstance instance; XrSystemId system_id; XrSession session; diff --git a/src/LunarWM_wayland.c b/src/LunarWM_wayland.c index b2ef8b5..aa5bee5 100644 --- a/src/LunarWM_wayland.c +++ b/src/LunarWM_wayland.c @@ -3,6 +3,9 @@ #include "common.h" #include "vec.h" +#include +#include + #include #include #include @@ -15,6 +18,10 @@ #include #include +static void handle_new_output(struct wl_listener *listener, void *data); +static void handle_output_frame(struct wl_listener *listener, void *data); +static void handle_output_destroy(struct wl_listener *listener, void *data); + static inline SphericalCoord get_forward_spherical_with_nearest( Vector3 fwd, float r) { @@ -1481,12 +1488,151 @@ static void setup_xwayland(LunarWM *this) wl_signal_add(&this->wayland.xwayland->events.new_surface, &this->wayland.xwayland_new_surface); } +static void destroy_output(LunarWM_Output *output) { + if (!output) { + return; + } + + if (output->frame.link.prev || output->frame.link.next) { + wl_list_remove(&output->frame.link); + } + if (output->destroy.link.prev || output->destroy.link.next) { + wl_list_remove(&output->destroy.link); + } + + free(output); +} + +static void handle_output_destroy(struct wl_listener *listener, void *data) { + (void)data; + LunarWM_Output *output = wl_container_of(listener, output, destroy); + LunarWM *wm = output->wm; + + if (wm && wm->wayland.v_outputs) { + for (size_t i = 0; i < vector_size(wm->wayland.v_outputs); ++i) { + if (wm->wayland.v_outputs[i] == output) { + vector_remove(wm->wayland.v_outputs, i); + break; + } + } + } + + destroy_output(output); +} + +static void handle_output_frame(struct wl_listener *listener, void *data) { + (void)data; + LunarWM_Output *output = wl_container_of(listener, output, frame); + LunarWM *wm = output->wm; + struct wlr_output *wlr_output = output->wlr_output; + + if (wm->xr.available) { + wlr_output_schedule_frame(wlr_output); + return; + } + + struct wlr_output_state state; + wlr_output_state_init(&state); + + struct wlr_render_pass *pass + = wlr_output_begin_render_pass(wlr_output, &state, NULL); + if (pass == NULL) { + wlr_output_state_finish(&state); + wlr_output_schedule_frame(wlr_output); + wlr_log(WLR_ERROR, "Failed to begin render pass for output %s", + wlr_output->name); + return; + } + + struct wlr_box box = { + .x = 0, + .y = 0, + .width = wlr_output->width, + .height = wlr_output->height, + }; + wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ + .box = box, + .color = { + .r = 1.0f, + .g = 0.0f, + .b = 0.0f, + .a = 1.0f, + }, + }); + + if (!wlr_render_pass_submit(pass)) { + wlr_output_state_finish(&state); + wlr_output_schedule_frame(wlr_output); + wlr_log(WLR_ERROR, "Failed to submit render pass for output %s", + wlr_output->name); + return; + } + + if (!wlr_output_commit_state(wlr_output, &state)) { + wlr_log(WLR_ERROR, "Failed to commit state for output %s", + wlr_output->name); + wlr_output_state_finish(&state); + wlr_output_schedule_frame(wlr_output); + return; + } + + wlr_output_state_finish(&state); +} + +static void handle_new_output(struct wl_listener *listener, void *data) { + struct wlr_output *wlr_output = data; + LunarWM *wm = wl_container_of(listener, wm, wayland.new_output_listener); + + if (!wlr_output_init_render( + wlr_output, wm->wayland.allocator, wm->wayland.renderer)) { + wlr_log(WLR_ERROR, "Failed to init render for output %s", + wlr_output->name); + return; + } + + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_enabled(&state, true); + + struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); + if (mode != NULL) { + wlr_output_state_set_mode(&state, mode); + } + + bool committed = wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + if (!committed) { + wlr_log(WLR_ERROR, "Failed to commit init state for output %s", + wlr_output->name); + return; + } + + LunarWM_Output *output = calloc(1, sizeof(*output)); + if (!output) { + wlr_log(WLR_ERROR, "Out of memory creating output state"); + return; + } + + output->wm = wm; + output->wlr_output = wlr_output; + + output->frame.notify = handle_output_frame; + wl_signal_add(&wlr_output->events.frame, &output->frame); + output->destroy.notify = handle_output_destroy; + wl_signal_add(&wlr_output->events.destroy, &output->destroy); + + vector_add(&wm->wayland.v_outputs, output); + + wlr_output_schedule_frame(wlr_output); +} + bool LunarWM_wayland_init(LunarWM *this) { wlr_log_init(WLR_DEBUG, nullptr); this->wayland.v_toplevels = vector_create(); + this->wayland.v_outputs = vector_create(); this->wayland.display = wl_display_create(); if (this->wayland.display == nullptr) { @@ -1587,6 +1733,10 @@ bool LunarWM_wayland_init(LunarWM *this) wl_list_init(&this->wayland.keyboards); wl_list_init(&this->wayland.pointers); + this->wayland.new_output_listener.notify = handle_new_output; + wl_signal_add(&this->wayland.backend->events.new_output, + &this->wayland.new_output_listener); + this->wayland.new_input_listener.notify = new_input_listener_notify; wl_signal_add(&this->wayland.backend->events.new_input, &this->wayland.new_input_listener); @@ -1616,6 +1766,20 @@ void LunarWM_wayland_cleanup(LunarWM *this) this->wayland.custom_out_hud = NULL; } + if (this->wayland.new_output_listener.link.prev + || this->wayland.new_output_listener.link.next) { + wl_list_remove(&this->wayland.new_output_listener.link); + this->wayland.new_output_listener.notify = NULL; + } + + if (this->wayland.v_outputs) { + for (size_t i = 0; i < vector_size(this->wayland.v_outputs); ++i) { + destroy_output(this->wayland.v_outputs[i]); + } + vector_free(this->wayland.v_outputs); + this->wayland.v_outputs = NULL; + } + if (this->wayland.xwayland) { if (this->wayland.xwayland_new_surface.link.prev || this->wayland.xwayland_new_surface.link.next) { diff --git a/src/LunarWM_xr.c b/src/LunarWM_xr.c index f5d9693..70c8238 100644 --- a/src/LunarWM_xr.c +++ b/src/LunarWM_xr.c @@ -389,13 +389,13 @@ bool LunarWM_xr_init(LunarWM *this) } } - auto const swapchain_format_depth = GL_DEPTH_COMPONENT16; - auto const swapchain_format_color = GL_SRGB8_ALPHA8; + auto const swapchain_format_depth = GL_DEPTH_COMPONENT24; + auto const swapchain_format_color = GL_RGBA8; { bool found = false; for (size_t i = 0; i < a_swapchain_formats_count; i++) { - if (a_swapchain_formats[i] == GL_SRGB8_ALPHA8) { + if (a_swapchain_formats[i] == swapchain_format_color) { found = true; break; } @@ -434,8 +434,7 @@ bool LunarWM_xr_init(LunarWM *this) .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, .next = nullptr, .createFlags = 0, - .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT - | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, + .usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, .format = swapchain_format_color, .sampleCount = vcv->recommendedSwapchainSampleCount, .width = buf_w, @@ -458,8 +457,7 @@ bool LunarWM_xr_init(LunarWM *this) .type = XR_TYPE_SWAPCHAIN_CREATE_INFO, .next = nullptr, .createFlags = 0, - .usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT - | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .format = swapchain_format_depth, .sampleCount = vcv->recommendedSwapchainSampleCount, .width = buf_w, diff --git a/wlroots-lunar b/wlroots-lunar index d071622..a9abd5a 160000 --- a/wlroots-lunar +++ b/wlroots-lunar @@ -1 +1 @@ -Subproject commit d0716220ff8bb32889048a3df87b3faf6805aa81 +Subproject commit a9abd5a6e4fb4e5ac6c410e1fb1ad438d3b12001