Get windows to render propely

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-07-10 07:11:56 +03:00
parent c1e331ca7e
commit c21397cef5

View File

@@ -821,49 +821,62 @@ private:
wlr_xdg_toplevel_set_size(tl->xdg_toplevel, 0, 0); wlr_xdg_toplevel_set_size(tl->xdg_toplevel, 0, 0);
return; return;
} }
tl->update();
}; };
wl_signal_add(&surface->events.commit, &commit); wl_signal_add(&surface->events.commit, &commit);
destroy.notify = [](wl_listener *l, void *) { destroy.notify = [](wl_listener *l, void *) {
auto tl = wl_container_of(l, (Toplevel*)nullptr, destroy); auto tl = wl_container_of(l, (Toplevel *)nullptr, destroy);
auto &vec = tl->server->m_wayland.toplevels; auto &vec = tl->server->m_wayland.toplevels;
vec.erase(std::remove_if(vec.begin(), vec.end(), vec.erase(std::remove_if(vec.begin(), vec.end(),
[tl](auto &p){ return p.get() == tl; }), vec.end()); [tl](auto &p) { return p.get() == tl; }),
vec.end());
}; };
wl_signal_add(&surface->events.destroy, &destroy); wl_signal_add(&surface->events.destroy, &destroy);
} }
void update() { void update()
{
texture = wlr_surface_get_texture(surface);
struct wlr_client_buffer *cl_buf = surface->buffer;
if (!texture || !cl_buf) {
return;
}
texture = wlr_surface_get_texture(surface); if (locked_buffer && locked_buffer != &cl_buf->base) {
if (!texture) wlr_buffer_unlock(locked_buffer);
return; locked_buffer = nullptr;
wlr_gles2_texture_get_attribs(texture, &attribs); }
char const *texture_target = "unknown"; if (locked_buffer == nullptr) {
if (attribs.target == GL_TEXTURE_EXTERNAL_OES) { locked_buffer = wlr_buffer_lock(&cl_buf->base);
texture_target = "GL_TEXTURE_EXTERNAL_OES"; }
} else if (attribs.target == GL_TEXTURE_2D) {
texture_target = "GL_TEXTURE_2D";
}
gles_texture = gles2_get_texture(texture);
if (!gles_texture) {
return;
}
rl_texture.id = attribs.tex;
rl_texture.width = texture->width;
rl_texture.height = texture->height;
rl_texture.mipmaps = 1;
rl_texture.format = gles_texture->has_alpha ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 : PIXELFORMAT_UNCOMPRESSED_R8G8B8;
SetTextureFilter(rl_texture, TEXTURE_FILTER_BILINEAR); wlr_gles2_texture_get_attribs(texture, &attribs);
SetTextureWrap(rl_texture, TEXTURE_WRAP_CLAMP); gles_texture = gles2_get_texture(texture);
if (!gles_texture) {
return;
}
rl_texture.id = attribs.tex;
rl_texture.width = texture->width;
rl_texture.height = texture->height;
rl_texture.mipmaps = 1;
rl_texture.format = gles_texture->has_alpha
? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
: PIXELFORMAT_UNCOMPRESSED_R8G8B8;
SetTextureFilter(rl_texture, TEXTURE_FILTER_BILINEAR);
SetTextureWrap(rl_texture, TEXTURE_WRAP_CLAMP);
} }
~Toplevel() { ~Toplevel()
{
wl_list_remove(&commit.link); wl_list_remove(&commit.link);
wl_list_remove(&destroy.link); wl_list_remove(&destroy.link);
if (locked_buffer) {
wlr_buffer_unlock(locked_buffer);
}
} }
LunarWM *server {}; LunarWM *server {};
@@ -874,6 +887,8 @@ private:
wlr_xdg_toplevel *xdg_toplevel {}; wlr_xdg_toplevel *xdg_toplevel {};
wlr_surface *surface {}; wlr_surface *surface {};
wlr_texture *texture {}; wlr_texture *texture {};
wlr_buffer *locked_buffer {};
wlr_gles2_texture_attribs attribs {}; wlr_gles2_texture_attribs attribs {};
wlr_gles2_texture *gles_texture {}; wlr_gles2_texture *gles_texture {};
Texture2D rl_texture {}; Texture2D rl_texture {};
@@ -915,8 +930,6 @@ private:
std::vector<std::unique_ptr<Toplevel>> toplevels; std::vector<std::unique_ptr<Toplevel>> toplevels;
// Output stuff to update buffers
struct wl_listener new_output_listener {};
} m_wayland; } m_wayland;
struct { struct {
@@ -1274,54 +1287,6 @@ void LunarWM::init_wayland()
}; };
wl_signal_add(&m_wayland.xdg_shell->events.new_popup, wl_signal_add(&m_wayland.xdg_shell->events.new_popup,
&m_wayland.new_xdg_popup_listener); &m_wayland.new_xdg_popup_listener);
// Output stuff
wl_signal_add(&m_wayland.backend->events.new_output, &m_wayland.new_output_listener);
m_wayland.new_output_listener.notify = [](wl_listener *listener, void *data) {
wlr_output *output = reinterpret_cast<wlr_output *>(data);
LunarWM *sample =
wl_container_of(listener, static_cast<LunarWM *>(nullptr), m_wayland.new_output_listener);
wlr_output_init_render(output, sample->m_wayland.allocator, sample->m_wayland.renderer);
auto my_output = new Output;
my_output->output = output;
my_output->server = sample;
wl_signal_add(&output->events.frame, &my_output->frame);
my_output->frame.notify = [](struct wl_listener *listener, void *data) {
Output *sample_output =
wl_container_of(listener, static_cast<Output *>(nullptr), frame);
LunarWM *sample = sample_output->server;
wlr_output *wlr_output = sample_output->output;
struct wlr_output_state state;
wlr_output_state_init(&state);
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL);
wlr_render_pass_submit(pass);
wlr_output_commit_state(wlr_output, &state);
wlr_output_state_finish(&state);
};
wl_signal_add(&output->events.destroy, &my_output->destroy);
my_output->destroy.notify = [](struct wl_listener *listener, void *data) {
struct Output *sample_output =
wl_container_of(listener, static_cast<Output *>(nullptr), destroy);
wlr_log(WLR_DEBUG, "Output removed");
wl_list_remove(&sample_output->frame.link);
wl_list_remove(&sample_output->destroy.link);
free(sample_output);
};
wlr_output_state state;
wlr_output_state_init(&state);
wlr_output_state_set_enabled(&state, true);
wlr_output_mode *mode = wlr_output_preferred_mode(output);
if (mode != NULL) {
wlr_output_state_set_mode(&state, mode);
}
wlr_output_commit_state(output, &state);
wlr_output_state_finish(&state);
};
} }
void LunarWM::init_xr() void LunarWM::init_xr()
@@ -1909,18 +1874,20 @@ void LunarWM::poll_events_xr()
bool LunarWM::render_layer(RenderLayerInfo &info, float dt) bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
{ {
// locate views ----------------------------------------------------------- // locate views -----------------------------------------------------------
std::uint32_t view_count = (std::uint32_t)m_xr.view_configuration_views.size(); std::uint32_t view_count
= (std::uint32_t)m_xr.view_configuration_views.size();
std::vector<XrView> views(view_count, { XR_TYPE_VIEW }); std::vector<XrView> views(view_count, { XR_TYPE_VIEW });
XrViewLocateInfo locInfo{ XR_TYPE_VIEW_LOCATE_INFO }; XrViewLocateInfo locInfo { XR_TYPE_VIEW_LOCATE_INFO };
locInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; locInfo.viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
locInfo.displayTime = info.predicted_display_time; locInfo.displayTime = info.predicted_display_time;
locInfo.space = m_xr.local_space; locInfo.space = m_xr.local_space;
XrViewState viewState{ XR_TYPE_VIEW_STATE }; XrViewState viewState { XR_TYPE_VIEW_STATE };
std::uint32_t located = 0; std::uint32_t located = 0;
if (xrLocateViews(m_xr.session, &locInfo, &viewState, if (xrLocateViews(m_xr.session, &locInfo, &viewState, view_count, &located,
view_count, &located, views.data()) != XR_SUCCESS views.data())
!= XR_SUCCESS
|| located != view_count) { || located != view_count) {
wlr_log(WLR_ERROR, "Failed to locate views"); wlr_log(WLR_ERROR, "Failed to locate views");
return false; return false;
@@ -1930,10 +1897,11 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
auto &color_sc = m_xr.swapchains.color[0]; auto &color_sc = m_xr.swapchains.color[0];
auto &depth_sc = m_xr.swapchains.depth[0]; auto &depth_sc = m_xr.swapchains.depth[0];
auto acquire_wait = [](XrSwapchain sc, std::uint32_t &idx)->bool { auto acquire_wait = [](XrSwapchain sc, std::uint32_t &idx) -> bool {
XrSwapchainImageAcquireInfo ai{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO }; XrSwapchainImageAcquireInfo ai { XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
if (xrAcquireSwapchainImage(sc, &ai, &idx) != XR_SUCCESS) return false; if (xrAcquireSwapchainImage(sc, &ai, &idx) != XR_SUCCESS)
XrSwapchainImageWaitInfo wi{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO }; return false;
XrSwapchainImageWaitInfo wi { XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
wi.timeout = XR_INFINITE_DURATION; wi.timeout = XR_INFINITE_DURATION;
return xrWaitSwapchainImage(sc, &wi) == XR_SUCCESS; return xrWaitSwapchainImage(sc, &wi) == XR_SUCCESS;
}; };
@@ -1949,44 +1917,45 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx); GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx);
// build FBO -------------------------------------------------------------- // build FBO --------------------------------------------------------------
if (!m_renderer.fbo) glGenFramebuffers(1, &m_renderer.fbo); if (!m_renderer.fbo)
glGenFramebuffers(1, &m_renderer.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_renderer.fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_renderer.fbo);
rlFramebufferAttach(m_renderer.fbo, color_tex, RL_ATTACHMENT_COLOR_CHANNEL0, rlFramebufferAttach(m_renderer.fbo, color_tex, RL_ATTACHMENT_COLOR_CHANNEL0,
RL_ATTACHMENT_TEXTURE2D, 0); RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(m_renderer.fbo, depth_tex, RL_ATTACHMENT_DEPTH, rlFramebufferAttach(m_renderer.fbo, depth_tex, RL_ATTACHMENT_DEPTH,
RL_ATTACHMENT_TEXTURE2D, 0); RL_ATTACHMENT_TEXTURE2D, 0);
assert(rlFramebufferComplete(m_renderer.fbo)); assert(rlFramebufferComplete(m_renderer.fbo));
std::uint32_t eyeW = m_xr.view_configuration_views[0].recommendedImageRectWidth; std::uint32_t eyeW
std::uint32_t eyeH = m_xr.view_configuration_views[0].recommendedImageRectHeight; = m_xr.view_configuration_views[0].recommendedImageRectWidth;
std::uint32_t eyeH
= m_xr.view_configuration_views[0].recommendedImageRectHeight;
m_renderer.tmp_rt = { m_renderer.tmp_rt = { m_renderer.fbo,
m_renderer.fbo,
{ color_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 }, { color_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 },
{ depth_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 } { depth_tex, (int)(eyeW * view_count), (int)eyeH, 1, -1 } };
};
// head-space view matrix (matches rlOpenXR) ------------------------------ // head-space view matrix (matches rlOpenXR) ------------------------------
XrSpaceLocation headLoc{ XR_TYPE_SPACE_LOCATION }; XrSpaceLocation headLoc { XR_TYPE_SPACE_LOCATION };
xrLocateSpace(m_xr.view_space, m_xr.local_space, xrLocateSpace(m_xr.view_space, m_xr.local_space,
info.predicted_display_time, &headLoc); info.predicted_display_time, &headLoc);
Matrix headView = MatrixInvert(xr_matrix(headLoc.pose)); Matrix headView = MatrixInvert(xr_matrix(headLoc.pose));
// per-eye projection + view-offset --------------------------------------- // per-eye projection + view-offset ---------------------------------------
Matrix projR = xr_projection_matrix(views[1].fov); Matrix projR = xr_projection_matrix(views[1].fov);
Matrix projL = xr_projection_matrix(views[0].fov); Matrix projL = xr_projection_matrix(views[0].fov);
Matrix viewOffR = MatrixMultiply(xr_matrix(views[1].pose), headView); Matrix viewOffR = MatrixMultiply(xr_matrix(views[1].pose), headView);
Matrix viewOffL = MatrixMultiply(xr_matrix(views[0].pose), headView); Matrix viewOffL = MatrixMultiply(xr_matrix(views[0].pose), headView);
// draw ------------------------------------------------------------------- // draw -------------------------------------------------------------------
BeginTextureMode(m_renderer.tmp_rt); BeginTextureMode(m_renderer.tmp_rt);
rlEnableStereoRender(); rlEnableStereoRender();
rlSetMatrixProjectionStereo(projL, projR); // right, left (yes) rlSetMatrixProjectionStereo(projL, projR); // right, left (yes)
rlSetMatrixViewOffsetStereo(viewOffL, viewOffR); rlSetMatrixViewOffsetStereo(viewOffL, viewOffR);
glViewport(0, 0, (GLsizei)(eyeW * view_count), (GLsizei)eyeH); glViewport(0, 0, (GLsizei)(eyeW * view_count), (GLsizei)eyeH);
ClearBackground(RAYWHITE); ClearBackground({ 0, 0, 10, 255 });
m_renderer.update_camera(*this, m_renderer.camera, info); m_renderer.update_camera(*this, m_renderer.camera, info);
@@ -2000,37 +1969,37 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
EndTextureMode(); EndTextureMode();
// release swapchain images ---------------------------------------------- // release swapchain images ----------------------------------------------
XrSwapchainImageReleaseInfo ri{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO }; XrSwapchainImageReleaseInfo ri { XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
xrReleaseSwapchainImage(color_sc.swapchain, &ri); xrReleaseSwapchainImage(color_sc.swapchain, &ri);
xrReleaseSwapchainImage(depth_sc.swapchain, &ri); xrReleaseSwapchainImage(depth_sc.swapchain, &ri);
// fill projection layer -------------------------------------------------- // fill projection layer --------------------------------------------------
info.layer_projection_views.resize(view_count, info.layer_projection_views.resize(
{ XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW }); view_count, { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW });
for (std::uint32_t i = 0; i < view_count; ++i) { for (std::uint32_t i = 0; i < view_count; ++i) {
int32_t xOff = (int32_t)i * (int32_t)eyeW; int32_t xOff = (int32_t)i * (int32_t)eyeW;
auto &pv = info.layer_projection_views[i]; auto &pv = info.layer_projection_views[i];
pv.pose = views[i].pose; pv.pose = views[i].pose;
pv.fov = views[i].fov; pv.fov = views[i].fov;
pv.subImage.swapchain = color_sc.swapchain; pv.subImage.swapchain = color_sc.swapchain;
pv.subImage.imageRect.offset = { xOff, 0 }; pv.subImage.imageRect.offset = { xOff, 0 };
pv.subImage.imageRect.extent = { (int32_t)eyeW, (int32_t)eyeH }; pv.subImage.imageRect.extent = { (int32_t)eyeW, (int32_t)eyeH };
pv.subImage.imageArrayIndex = 0; pv.subImage.imageArrayIndex = 0;
} }
info.layer_projection = { info.layer_projection = {
.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION, .type = XR_TYPE_COMPOSITION_LAYER_PROJECTION,
.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | .layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, | XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT,
.space = m_xr.local_space, .space = m_xr.local_space,
.viewCount = view_count, .viewCount = view_count,
.views = info.layer_projection_views.data(), .views = info.layer_projection_views.data(),
}; };
info.layers.clear(); info.layers.clear();
info.layers.push_back( info.layers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader *>(
reinterpret_cast<XrCompositionLayerBaseHeader*>(&info.layer_projection)); &info.layer_projection));
return true; return true;
} }
@@ -2176,15 +2145,36 @@ void LunarWM::run()
== EGL_FALSE) { == EGL_FALSE) {
throw std::runtime_error("Failed to eglMakeCurrent"); throw std::runtime_error("Failed to eglMakeCurrent");
} }
struct timespec n;
clock_gettime(CLOCK_MONOTONIC, &n);
for (auto const &tl : m_wayland.toplevels) {
if (tl->surface) {
wlr_surface_send_frame_done(tl->surface, &n);
}
}
} }
} }
static void DrawBillboardNoShear(Camera3D const &cam, Texture2D tex,
Vector3 pos, float scale = 1.0f, Color tint = WHITE)
{
Rectangle src = { 0, 0, (float)tex.width, (float)tex.height };
Vector2 size = { scale * fabsf(src.width / src.height), scale };
Vector2 origin = { size.x * 0.5f, size.y * 0.5f };
DrawBillboardPro(cam, tex, src, pos, cam.up, size, origin, 0.0f, tint);
}
void LunarWM::render_3d(float dt) void LunarWM::render_3d(float dt)
{ {
DrawGrid(10, 1); DrawGrid(10, 1);
for (auto const &tl : m_wayland.toplevels) { for (auto const &tl : m_wayland.toplevels) {
DrawBillboard(m_renderer.camera, tl->rl_texture, { -2, 1, -2 }, 1, WHITE); tl->update();
DrawBillboardNoShear(
m_renderer.camera, tl->rl_texture, { 0, 1, -1.4f }, 1.0f);
} }
} }