Manage to get first frame of clients rendering
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
302
src/LunarWM.cppm
302
src/LunarWM.cppm
@@ -7,6 +7,7 @@ module;
|
|||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
#include <GLES3/gl3.h>
|
#include <GLES3/gl3.h>
|
||||||
|
#include <GLES3/gl31.h>
|
||||||
#include <openxr/openxr.h>
|
#include <openxr/openxr.h>
|
||||||
#include <openxr/openxr_platform.h>
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
@@ -800,28 +801,91 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Toplevel {
|
struct Toplevel {
|
||||||
Toplevel(LunarWM *server, wlr_xdg_toplevel *xdg_toplevel)
|
Toplevel(Toplevel const &) = delete;
|
||||||
: server(server)
|
Toplevel &operator=(Toplevel const &) = delete;
|
||||||
, xdg_toplevel(xdg_toplevel)
|
Toplevel(Toplevel &&) = delete;
|
||||||
|
Toplevel &operator=(Toplevel &&) = delete;
|
||||||
|
|
||||||
|
Toplevel(LunarWM *srv, wlr_xdg_toplevel *xdg)
|
||||||
|
: server(srv)
|
||||||
|
, xdg_toplevel(xdg)
|
||||||
{
|
{
|
||||||
surface = wlr_surface_from_resource(xdg_toplevel->resource);
|
surface = xdg->base->surface;
|
||||||
texture = wlr_surface_get_texture(surface);
|
assert(surface);
|
||||||
gles_texture = gles2_get_texture(texture);
|
|
||||||
rl_texture.width = texture->width;
|
commit.notify = [](wl_listener *l, void *) {
|
||||||
rl_texture.height = texture->height;
|
auto tl = wl_container_of(
|
||||||
|
l, static_cast<Toplevel *>(nullptr), commit);
|
||||||
|
|
||||||
|
if (tl->xdg_toplevel->base->initial_commit) {
|
||||||
|
wlr_xdg_toplevel_set_size(tl->xdg_toplevel, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
wl_signal_add(&surface->events.commit, &commit);
|
||||||
|
|
||||||
|
destroy.notify = [](wl_listener *l, void *) {
|
||||||
|
auto tl = wl_container_of(l, (Toplevel*)nullptr, destroy);
|
||||||
|
|
||||||
|
auto &vec = tl->server->m_wayland.toplevels;
|
||||||
|
vec.erase(std::remove_if(vec.begin(), vec.end(),
|
||||||
|
[tl](auto &p){ return p.get() == tl; }), vec.end());
|
||||||
|
};
|
||||||
|
wl_signal_add(&surface->events.destroy, &destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator Texture2D &() { return rl_texture; }
|
void update() {
|
||||||
|
|
||||||
|
texture = wlr_surface_get_texture(surface);
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
wlr_gles2_texture_get_attribs(texture, &attribs);
|
||||||
|
char const *texture_target = "unknown";
|
||||||
|
if (attribs.target == GL_TEXTURE_EXTERNAL_OES) {
|
||||||
|
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);
|
||||||
|
SetTextureWrap(rl_texture, TEXTURE_WRAP_CLAMP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~Toplevel() {
|
||||||
|
wl_list_remove(&commit.link);
|
||||||
|
wl_list_remove(&destroy.link);
|
||||||
|
}
|
||||||
|
|
||||||
LunarWM *server {};
|
LunarWM *server {};
|
||||||
|
|
||||||
|
wl_listener commit {};
|
||||||
|
wl_listener destroy {};
|
||||||
|
|
||||||
wlr_xdg_toplevel *xdg_toplevel {};
|
wlr_xdg_toplevel *xdg_toplevel {};
|
||||||
wlr_surface *surface {};
|
wlr_surface *surface {};
|
||||||
wlr_texture *texture {};
|
wlr_texture *texture {};
|
||||||
|
wlr_gles2_texture_attribs attribs {};
|
||||||
wlr_gles2_texture *gles_texture {};
|
wlr_gles2_texture *gles_texture {};
|
||||||
Texture2D rl_texture {};
|
Texture2D rl_texture {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Output {
|
||||||
|
struct LunarWM *server {};
|
||||||
|
struct wlr_output *output {};
|
||||||
|
struct wl_listener frame {};
|
||||||
|
struct wl_listener destroy {};
|
||||||
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
wl_display *display {};
|
wl_display *display {};
|
||||||
wl_event_loop *event_loop {};
|
wl_event_loop *event_loop {};
|
||||||
@@ -849,7 +913,10 @@ private:
|
|||||||
|
|
||||||
wlr_cursor *cursor {};
|
wlr_cursor *cursor {};
|
||||||
|
|
||||||
std::vector<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 {
|
||||||
@@ -1180,12 +1247,23 @@ void LunarWM::init_wayland()
|
|||||||
|
|
||||||
m_wayland.xdg_shell = wlr_xdg_shell_create(m_wayland.display, 3);
|
m_wayland.xdg_shell = wlr_xdg_shell_create(m_wayland.display, 3);
|
||||||
|
|
||||||
m_wayland.new_xdg_toplevel_listener.notify
|
m_wayland.new_xdg_toplevel_listener.notify = [](wl_listener *listener,
|
||||||
= [](wl_listener *listener, void *data) {
|
void *data) {
|
||||||
LunarWM *server
|
LunarWM *server
|
||||||
= wl_container_of(listener, static_cast<LunarWM *>(nullptr),
|
= wl_container_of(listener, static_cast<LunarWM *>(nullptr),
|
||||||
m_wayland.new_xdg_toplevel_listener);
|
m_wayland.new_xdg_toplevel_listener);
|
||||||
};
|
auto toplevel = reinterpret_cast<wlr_xdg_toplevel *>(data);
|
||||||
|
|
||||||
|
if (toplevel->title) {
|
||||||
|
wlr_log(WLR_INFO, "Got XDG toplevel title: %s", toplevel->title);
|
||||||
|
}
|
||||||
|
if (toplevel->app_id) {
|
||||||
|
wlr_log(WLR_INFO, "Got XDG toplevel app ID: %s", toplevel->app_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
server->m_wayland.toplevels.emplace_back(
|
||||||
|
std::make_unique<Toplevel>(server, toplevel));
|
||||||
|
};
|
||||||
wl_signal_add(&m_wayland.xdg_shell->events.new_toplevel,
|
wl_signal_add(&m_wayland.xdg_shell->events.new_toplevel,
|
||||||
&m_wayland.new_xdg_toplevel_listener);
|
&m_wayland.new_xdg_toplevel_listener);
|
||||||
|
|
||||||
@@ -1193,12 +1271,57 @@ void LunarWM::init_wayland()
|
|||||||
void *data) {
|
void *data) {
|
||||||
LunarWM *server = wl_container_of(listener,
|
LunarWM *server = wl_container_of(listener,
|
||||||
static_cast<LunarWM *>(nullptr), m_wayland.new_xdg_popup_listener);
|
static_cast<LunarWM *>(nullptr), m_wayland.new_xdg_popup_listener);
|
||||||
auto toplevel = reinterpret_cast<wlr_xdg_toplevel *>(data);
|
|
||||||
|
|
||||||
Toplevel tl(server, toplevel);
|
|
||||||
};
|
};
|
||||||
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()
|
||||||
@@ -1785,37 +1908,37 @@ void LunarWM::poll_events_xr()
|
|||||||
|
|
||||||
bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
|
bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
|
||||||
{
|
{
|
||||||
uint32_t const view_count = (uint32_t)m_xr.view_configuration_views.size();
|
// locate views -----------------------------------------------------------
|
||||||
|
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 };
|
||||||
uint32_t located = 0;
|
std::uint32_t located = 0;
|
||||||
if (xrLocateViews(m_xr.session, &locInfo, &viewState, view_count, &located,
|
if (xrLocateViews(m_xr.session, &locInfo, &viewState,
|
||||||
views.data())
|
view_count, &located, views.data()) != XR_SUCCESS
|
||||||
!= 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// acquire swapchain images ----------------------------------------------
|
||||||
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, 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)
|
if (xrAcquireSwapchainImage(sc, &ai, &idx) != XR_SUCCESS) return false;
|
||||||
return false;
|
XrSwapchainImageWaitInfo wi{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t colIdx = 0, depIdx = 0;
|
std::uint32_t colIdx = 0, depIdx = 0;
|
||||||
if (!acquire_wait(color_sc.swapchain, colIdx)
|
if (!acquire_wait(color_sc.swapchain, colIdx)
|
||||||
|| !acquire_wait(depth_sc.swapchain, depIdx)) {
|
|| !acquire_wait(depth_sc.swapchain, depIdx)) {
|
||||||
wlr_log(WLR_ERROR, "Swap-chain acquire failed");
|
wlr_log(WLR_ERROR, "Swap-chain acquire failed");
|
||||||
@@ -1825,78 +1948,89 @@ bool LunarWM::render_layer(RenderLayerInfo &info, float dt)
|
|||||||
GLuint color_tex = m_xr.get_swapchain_image(color_sc.swapchain, colIdx);
|
GLuint color_tex = m_xr.get_swapchain_image(color_sc.swapchain, colIdx);
|
||||||
GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx);
|
GLuint depth_tex = m_xr.get_swapchain_image(depth_sc.swapchain, depIdx);
|
||||||
|
|
||||||
if (!m_renderer.fbo)
|
// build 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));
|
||||||
|
|
||||||
uint32_t const eyeW
|
std::uint32_t eyeW = m_xr.view_configuration_views[0].recommendedImageRectWidth;
|
||||||
= m_xr.view_configuration_views[0].recommendedImageRectWidth;
|
std::uint32_t eyeH = m_xr.view_configuration_views[0].recommendedImageRectHeight;
|
||||||
uint32_t const eyeH
|
|
||||||
= m_xr.view_configuration_views[0].recommendedImageRectHeight;
|
|
||||||
|
|
||||||
m_renderer.tmp_rt = { m_renderer.fbo,
|
m_renderer.tmp_rt = {
|
||||||
|
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 }
|
||||||
|
};
|
||||||
|
|
||||||
Matrix projL = xr_projection_matrix(views[0].fov);
|
// head-space view matrix (matches rlOpenXR) ------------------------------
|
||||||
Matrix projR = xr_projection_matrix(views[1].fov);
|
XrSpaceLocation headLoc{ XR_TYPE_SPACE_LOCATION };
|
||||||
Matrix viewL = MatrixInvert(xr_matrix(views[0].pose));
|
xrLocateSpace(m_xr.view_space, m_xr.local_space,
|
||||||
Matrix viewR = MatrixInvert(xr_matrix(views[1].pose));
|
info.predicted_display_time, &headLoc);
|
||||||
|
Matrix headView = MatrixInvert(xr_matrix(headLoc.pose));
|
||||||
|
|
||||||
|
// per-eye projection + view-offset ---------------------------------------
|
||||||
|
Matrix projR = xr_projection_matrix(views[1].fov);
|
||||||
|
Matrix projL = xr_projection_matrix(views[0].fov);
|
||||||
|
Matrix viewOffR = MatrixMultiply(xr_matrix(views[1].pose), headView);
|
||||||
|
Matrix viewOffL = MatrixMultiply(xr_matrix(views[0].pose), headView);
|
||||||
|
|
||||||
|
// draw -------------------------------------------------------------------
|
||||||
BeginTextureMode(m_renderer.tmp_rt);
|
BeginTextureMode(m_renderer.tmp_rt);
|
||||||
|
|
||||||
rlEnableStereoRender();
|
rlEnableStereoRender();
|
||||||
rlSetMatrixProjectionStereo(projL, projR);
|
rlSetMatrixProjectionStereo(projL, projR); // right, left (yes)
|
||||||
rlSetMatrixViewOffsetStereo(viewL, viewR);
|
rlSetMatrixViewOffsetStereo(viewOffL, viewOffR);
|
||||||
|
|
||||||
glViewport(0, 0, (GLsizei)(eyeW * view_count), (GLsizei)eyeH);
|
glViewport(0, 0, (GLsizei)(eyeW * view_count), (GLsizei)eyeH);
|
||||||
ClearBackground(RAYWHITE);
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
m_renderer.update_camera(*this, m_renderer.camera, info);
|
||||||
|
|
||||||
BeginMode3D(m_renderer.camera);
|
BeginMode3D(m_renderer.camera);
|
||||||
{
|
{
|
||||||
this->render_3d(dt);
|
render_3d(dt);
|
||||||
}
|
}
|
||||||
EndMode3D();
|
EndMode3D();
|
||||||
|
|
||||||
rlDisableStereoRender();
|
rlDisableStereoRender();
|
||||||
EndTextureMode();
|
EndTextureMode();
|
||||||
|
|
||||||
XrSwapchainImageReleaseInfo ri { XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
|
// release swapchain images ----------------------------------------------
|
||||||
|
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);
|
||||||
|
|
||||||
info.layer_projection_views.resize(
|
// fill projection layer --------------------------------------------------
|
||||||
view_count, { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW });
|
info.layer_projection_views.resize(view_count,
|
||||||
|
{ XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW });
|
||||||
for (uint32_t i = 0; i < view_count; ++i) {
|
|
||||||
int32_t const xOff = (int32_t)i * (int32_t)eyeW;
|
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < view_count; ++i) {
|
||||||
|
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
|
pv.subImage.imageRect.offset = { xOff, 0 };
|
||||||
= { { xOff, 0 }, { (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.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
info.layer_projection = {
|
||||||
info.layer_projection.space = m_xr.local_space;
|
.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION,
|
||||||
info.layer_projection.viewCount = view_count;
|
.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT |
|
||||||
info.layer_projection.views = info.layer_projection_views.data();
|
XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT,
|
||||||
info.layer_projection.layerFlags
|
.space = m_xr.local_space,
|
||||||
= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT
|
.viewCount = view_count,
|
||||||
| XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
|
.views = info.layer_projection_views.data(),
|
||||||
|
};
|
||||||
|
|
||||||
info.layers.clear();
|
info.layers.clear();
|
||||||
info.layers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader *>(
|
info.layers.push_back(
|
||||||
&info.layer_projection));
|
reinterpret_cast<XrCompositionLayerBaseHeader*>(&info.layer_projection));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1905,7 +2039,7 @@ LunarWM::~LunarWM()
|
|||||||
{
|
{
|
||||||
assert(m_initialized);
|
assert(m_initialized);
|
||||||
|
|
||||||
if (m_xr.local_space == XR_NULL_HANDLE) {
|
if (m_xr.local_space != XR_NULL_HANDLE) {
|
||||||
xrDestroySpace(m_xr.local_space);
|
xrDestroySpace(m_xr.local_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1935,16 +2069,16 @@ LunarWM::~LunarWM()
|
|||||||
wl_list_remove(&m_wayland.keyboards);
|
wl_list_remove(&m_wayland.keyboards);
|
||||||
|
|
||||||
wl_display_destroy_clients(m_wayland.display);
|
wl_display_destroy_clients(m_wayland.display);
|
||||||
if (!m_wayland.allocator) {
|
if (m_wayland.allocator) {
|
||||||
wlr_allocator_destroy(m_wayland.allocator);
|
wlr_allocator_destroy(m_wayland.allocator);
|
||||||
}
|
}
|
||||||
if (!m_wayland.renderer) {
|
if (m_wayland.renderer) {
|
||||||
wlr_renderer_destroy(m_wayland.renderer);
|
wlr_renderer_destroy(m_wayland.renderer);
|
||||||
}
|
}
|
||||||
if (!m_wayland.backend) {
|
if (m_wayland.backend) {
|
||||||
wlr_backend_destroy(m_wayland.backend);
|
wlr_backend_destroy(m_wayland.backend);
|
||||||
}
|
}
|
||||||
if (!m_wayland.display) {
|
if (m_wayland.display) {
|
||||||
wl_display_destroy(m_wayland.display);
|
wl_display_destroy(m_wayland.display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2047,17 +2181,11 @@ void LunarWM::run()
|
|||||||
|
|
||||||
void LunarWM::render_3d(float dt)
|
void LunarWM::render_3d(float dt)
|
||||||
{
|
{
|
||||||
static float animT { 0.0f };
|
|
||||||
animT += dt;
|
|
||||||
|
|
||||||
DrawGrid(10, 1);
|
DrawGrid(10, 1);
|
||||||
|
|
||||||
Vector3 forward = Vector3Normalize(
|
for (auto const &tl : m_wayland.toplevels) {
|
||||||
Vector3Subtract(m_renderer.camera.target, m_renderer.camera.position));
|
DrawBillboard(m_renderer.camera, tl->rl_texture, { -2, 1, -2 }, 1, WHITE);
|
||||||
float distance = 5.0f + sinf(animT) * 3.0f;
|
}
|
||||||
Vector3 spherePos = Vector3Add(
|
|
||||||
m_renderer.camera.position, Vector3Scale(forward, distance));
|
|
||||||
DrawSphere(spherePos, 0.5f, YELLOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LunarWM::terminate()
|
void LunarWM::terminate()
|
||||||
|
|||||||
Reference in New Issue
Block a user