rework stereo mode
This commit is contained in:
@@ -24,6 +24,7 @@ use wgui::gfx::WGfx;
|
|||||||
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
use wlx_common::overlays::{BackendAttrib, BackendAttribValue};
|
||||||
|
|
||||||
use crate::backend::input::{HoverResult, PointerHit};
|
use crate::backend::input::{HoverResult, PointerHit};
|
||||||
|
use crate::graphics::ExtentExt;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::subsystem::hid::WheelDelta;
|
use crate::subsystem::hid::WheelDelta;
|
||||||
use crate::windowing::Z_ORDER_LINES;
|
use crate::windowing::Z_ORDER_LINES;
|
||||||
@@ -200,7 +201,7 @@ impl OverlayBackend for LineBackend {
|
|||||||
}
|
}
|
||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
Some(FrameMeta {
|
Some(FrameMeta {
|
||||||
extent: self.view.image().extent(),
|
extent: self.view.extent_u32arr(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use vulkano::{
|
|||||||
};
|
};
|
||||||
use wgui::gfx::WGfx;
|
use wgui::gfx::WGfx;
|
||||||
|
|
||||||
use crate::{state::AppState, windowing::window::OverlayWindowData};
|
use crate::{graphics::ExtentExt, state::AppState, windowing::window::OverlayWindowData};
|
||||||
|
|
||||||
use super::helpers::Affine3AConvert;
|
use super::helpers::Affine3AConvert;
|
||||||
|
|
||||||
@@ -65,10 +65,10 @@ impl OverlayWindowData<OpenVrOverlayData> {
|
|||||||
pub(super) fn ensure_staging_image(
|
pub(super) fn ensure_staging_image(
|
||||||
&mut self,
|
&mut self,
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
extent: [u32; 3],
|
extent: [u32; 2],
|
||||||
) -> anyhow::Result<Arc<ImageView>> {
|
) -> anyhow::Result<Arc<ImageView>> {
|
||||||
if let Some(image_view) = self.data.image_view.as_ref()
|
if let Some(image_view) = self.data.image_view.as_ref()
|
||||||
&& image_view.image().extent() == extent
|
&& image_view.extent_u32arr() == extent
|
||||||
{
|
{
|
||||||
return Ok(image_view.clone());
|
return Ok(image_view.clone());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ impl LinePool {
|
|||||||
&Default::default(),
|
&Default::default(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let srd = create_swapchain(xr, app.gfx.clone(), [1, 1, 1], SwapchainOpts::new())?;
|
let srd = create_swapchain(xr, app.gfx.clone(), [1, 1], 1, SwapchainOpts::new())?;
|
||||||
self.lines.insert(
|
self.lines.insert(
|
||||||
id,
|
id,
|
||||||
LineContainer {
|
LineContainer {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use input::OpenXrInputSource;
|
|||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
use skybox::create_skybox;
|
use skybox::create_skybox;
|
||||||
use vulkano::{Handle, VulkanObject};
|
use vulkano::{Handle, VulkanObject};
|
||||||
use wlx_common::overlays::ToastTopic;
|
use wlx_common::overlays::{StereoMode, ToastTopic};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FRAME_COUNTER, RUNNING,
|
FRAME_COUNTER, RUNNING,
|
||||||
@@ -391,7 +391,8 @@ pub fn openxr_run(show_by_default: bool, headless: bool) -> Result<(), BackendEr
|
|||||||
if should_render {
|
if should_render {
|
||||||
log::trace!("{}: render new frame", o.config.name);
|
log::trace!("{}: render new frame", o.config.name);
|
||||||
let meta = o.config.backend.frame_meta().unwrap(); // want panic
|
let meta = o.config.backend.frame_meta().unwrap(); // want panic
|
||||||
let wsi = o.ensure_swapchain_acquire(&app, &xr_state, meta.extent)?;
|
let stereo = !matches!(meta.stereo, StereoMode::None);
|
||||||
|
let wsi = o.ensure_swapchain_acquire(&app, &xr_state, meta.extent, stereo)?;
|
||||||
let tgt = RenderTarget { views: wsi.views };
|
let tgt = RenderTarget { views: wsi.views };
|
||||||
let mut rdr = RenderResources::new(app.gfx.clone(), tgt, &meta, alpha)?;
|
let mut rdr = RenderResources::new(app.gfx.clone(), tgt, &meta, alpha)?;
|
||||||
o.render(&mut app, &mut rdr)?;
|
o.render(&mut app, &mut rdr)?;
|
||||||
|
|||||||
@@ -25,10 +25,14 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
&'a mut self,
|
&'a mut self,
|
||||||
app: &AppState,
|
app: &AppState,
|
||||||
xr: &'a XrState,
|
xr: &'a XrState,
|
||||||
extent: [u32; 3],
|
extent: [u32; 2],
|
||||||
|
stereo: bool,
|
||||||
) -> anyhow::Result<WlxSwapchainImage> {
|
) -> anyhow::Result<WlxSwapchainImage> {
|
||||||
|
let array_size = if stereo { 2 } else { 1 };
|
||||||
|
|
||||||
if let Some(swapchain) = self.data.swapchain.as_mut()
|
if let Some(swapchain) = self.data.swapchain.as_mut()
|
||||||
&& swapchain.extent == extent
|
&& swapchain.extent == extent
|
||||||
|
&& swapchain.array_size == array_size
|
||||||
{
|
{
|
||||||
return swapchain.acquire_wait_image();
|
return swapchain.acquire_wait_image();
|
||||||
}
|
}
|
||||||
@@ -38,9 +42,15 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
self.config.name,
|
self.config.name,
|
||||||
extent[0],
|
extent[0],
|
||||||
extent[1],
|
extent[1],
|
||||||
extent[2],
|
array_size,
|
||||||
);
|
);
|
||||||
let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, SwapchainOpts::new())?;
|
let mut swapchain = create_swapchain(
|
||||||
|
xr,
|
||||||
|
app.gfx.clone(),
|
||||||
|
extent,
|
||||||
|
array_size,
|
||||||
|
SwapchainOpts::new(),
|
||||||
|
)?;
|
||||||
let tgt = swapchain.acquire_wait_image()?;
|
let tgt = swapchain.acquire_wait_image()?;
|
||||||
self.data.swapchain = Some(swapchain);
|
self.data.swapchain = Some(swapchain);
|
||||||
Ok(tgt)
|
Ok(tgt)
|
||||||
@@ -65,7 +75,7 @@ impl OverlayWindowData<OpenXrOverlayData> {
|
|||||||
// overlays without active_state don't get queued for present
|
// overlays without active_state don't get queued for present
|
||||||
let state = self.config.active_state.as_ref().unwrap();
|
let state = self.config.active_state.as_ref().unwrap();
|
||||||
|
|
||||||
let sub_images: SmallVec<[_; 2]> = if swapchain.extent[2] > 1 {
|
let sub_images: SmallVec<[_; 2]> = if swapchain.array_size > 1 {
|
||||||
smallvec![
|
smallvec![
|
||||||
(swapchain.get_subimage(0), EyeVisibility::LEFT),
|
(swapchain.get_subimage(0), EyeVisibility::LEFT),
|
||||||
(swapchain.get_subimage(1), EyeVisibility::RIGHT),
|
(swapchain.get_subimage(1), EyeVisibility::RIGHT),
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ impl Skybox {
|
|||||||
}
|
}
|
||||||
let opts = SwapchainOpts::new().immutable();
|
let opts = SwapchainOpts::new().immutable();
|
||||||
|
|
||||||
let extent = self.view.image().extent();
|
let extent = self.view.extent_u32arr();
|
||||||
let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, opts)?;
|
let mut swapchain = create_swapchain(xr, app.gfx.clone(), extent, 1, opts)?;
|
||||||
let tgt = swapchain
|
let tgt = swapchain
|
||||||
.acquire_wait_image()?
|
.acquire_wait_image()?
|
||||||
.views
|
.views
|
||||||
@@ -141,11 +141,12 @@ impl Skybox {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let extent = [1024, 1024, 1];
|
let extent = [1024, 1024];
|
||||||
let mut swapchain = create_swapchain(
|
let mut swapchain = create_swapchain(
|
||||||
xr,
|
xr,
|
||||||
app.gfx.clone(),
|
app.gfx.clone(),
|
||||||
extent,
|
extent,
|
||||||
|
1,
|
||||||
SwapchainOpts::new().immutable(),
|
SwapchainOpts::new().immutable(),
|
||||||
)?;
|
)?;
|
||||||
let pipeline = app.gfx.create_pipeline(
|
let pipeline = app.gfx.create_pipeline(
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ impl SwapchainOpts {
|
|||||||
pub(super) fn create_swapchain(
|
pub(super) fn create_swapchain(
|
||||||
xr: &XrState,
|
xr: &XrState,
|
||||||
gfx: Arc<WGfx>,
|
gfx: Arc<WGfx>,
|
||||||
extent: [u32; 3],
|
extent: [u32; 2],
|
||||||
|
array_size: u32,
|
||||||
opts: SwapchainOpts,
|
opts: SwapchainOpts,
|
||||||
) -> anyhow::Result<WlxSwapchain> {
|
) -> anyhow::Result<WlxSwapchain> {
|
||||||
let create_flags = if opts.immutable {
|
let create_flags = if opts.immutable {
|
||||||
@@ -52,7 +53,7 @@ pub(super) fn create_swapchain(
|
|||||||
width: extent[0],
|
width: extent[0],
|
||||||
height: extent[1],
|
height: extent[1],
|
||||||
face_count: 1,
|
face_count: 1,
|
||||||
array_size: extent[2],
|
array_size,
|
||||||
mip_count: 1,
|
mip_count: 1,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ pub(super) fn create_swapchain(
|
|||||||
ImageCreateInfo {
|
ImageCreateInfo {
|
||||||
format: gfx.surface_format as _,
|
format: gfx.surface_format as _,
|
||||||
extent: [extent[0], extent[1], 1],
|
extent: [extent[0], extent[1], 1],
|
||||||
array_layers: extent[2],
|
array_layers: array_size,
|
||||||
usage: ImageUsage::COLOR_ATTACHMENT,
|
usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -78,7 +79,7 @@ pub(super) fn create_swapchain(
|
|||||||
// SAFETY: OpenXR guarantees that the image is a swapchain image, thus has memory backing it.
|
// SAFETY: OpenXR guarantees that the image is a swapchain image, thus has memory backing it.
|
||||||
let image = Arc::new(unsafe { raw_image.assume_bound() });
|
let image = Arc::new(unsafe { raw_image.assume_bound() });
|
||||||
let mut wsi = WlxSwapchainImage::default();
|
let mut wsi = WlxSwapchainImage::default();
|
||||||
for d in 0..extent[2] {
|
for d in 0..array_size {
|
||||||
let mut create_info = ImageViewCreateInfo::from_image(&image);
|
let mut create_info = ImageViewCreateInfo::from_image(&image);
|
||||||
create_info.subresource_range.array_layers = d..d + 1;
|
create_info.subresource_range.array_layers = d..d + 1;
|
||||||
wsi.views.push(ImageView::new(image.clone(), create_info)?);
|
wsi.views.push(ImageView::new(image.clone(), create_info)?);
|
||||||
@@ -93,6 +94,7 @@ pub(super) fn create_swapchain(
|
|||||||
swapchain,
|
swapchain,
|
||||||
images,
|
images,
|
||||||
extent,
|
extent,
|
||||||
|
array_size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +107,8 @@ pub(super) struct WlxSwapchain {
|
|||||||
acquired: bool,
|
acquired: bool,
|
||||||
pub(super) ever_acquired: bool,
|
pub(super) ever_acquired: bool,
|
||||||
pub(super) swapchain: xr::Swapchain<xr::Vulkan>,
|
pub(super) swapchain: xr::Swapchain<xr::Vulkan>,
|
||||||
pub(super) extent: [u32; 3],
|
pub(super) extent: [u32; 2],
|
||||||
|
pub(super) array_size: u32,
|
||||||
pub(super) images: SmallVec<[WlxSwapchainImage; 4]>,
|
pub(super) images: SmallVec<[WlxSwapchainImage; 4]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use button::setup_custom_button;
|
use button::setup_custom_button;
|
||||||
@@ -353,7 +353,6 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||||||
extent: [
|
extent: [
|
||||||
self.max_size.x.min(self.layout.content_size.x) as _,
|
self.max_size.x.min(self.layout.content_size.x) as _,
|
||||||
self.max_size.y.min(self.layout.content_size.y) as _,
|
self.max_size.y.min(self.layout.content_size.y) as _,
|
||||||
1,
|
|
||||||
],
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ impl OverlayBackend for DashFrontend {
|
|||||||
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
fn frame_meta(&mut self) -> Option<FrameMeta> {
|
||||||
Some(FrameMeta {
|
Some(FrameMeta {
|
||||||
clear: WGfxClearMode::Clear([0., 0., 0., 0.]),
|
clear: WGfxClearMode::Clear([0., 0., 0., 0.]),
|
||||||
extent: [DASH_RES_U32A[0], DASH_RES_U32A[1], 1],
|
extent: [DASH_RES_U32A[0], DASH_RES_U32A[1]],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use crate::{
|
|||||||
XrBackend,
|
XrBackend,
|
||||||
input::{HoverResult, PointerHit, PointerMode},
|
input::{HoverResult, PointerHit, PointerMode},
|
||||||
},
|
},
|
||||||
graphics::ExtentExt,
|
|
||||||
overlays::screen::capture::MyFirstDmaExporter,
|
overlays::screen::capture::MyFirstDmaExporter,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
|
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
|
||||||
@@ -208,31 +207,22 @@ impl OverlayBackend for ScreenBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(frame) = self.capture.receive() {
|
if let Some(frame) = self.capture.receive() {
|
||||||
let mut meta = frame.get_frame_meta(&app.session.config);
|
let stereo = self.stereo.unwrap_or(StereoMode::None);
|
||||||
|
let meta = frame.get_frame_meta(&app.session.config, stereo);
|
||||||
|
|
||||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||||
meta.extent[2] = pipeline.get_depth();
|
if self.meta.is_some_and(|old| old.extent != meta.extent) {
|
||||||
if self
|
|
||||||
.meta
|
|
||||||
.is_some_and(|old| old.extent[..2] != meta.extent[..2])
|
|
||||||
{
|
|
||||||
pipeline.set_extent(
|
pipeline.set_extent(
|
||||||
app,
|
app,
|
||||||
[meta.extent[0] as _, meta.extent[1] as _],
|
[meta.extent[0] as _, meta.extent[1] as _],
|
||||||
[0., 0.],
|
[0., 0.],
|
||||||
)?;
|
)?;
|
||||||
self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
|
self.interaction_transform = Some(ui_transform(meta.extent));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let pipeline = ScreenPipeline::new(
|
let pipeline = ScreenPipeline::new(&meta, app, stereo, [0., 0.])?;
|
||||||
&meta,
|
|
||||||
app,
|
|
||||||
self.stereo.unwrap_or(StereoMode::None),
|
|
||||||
[0., 0.],
|
|
||||||
)?;
|
|
||||||
meta.extent[2] = pipeline.get_depth();
|
|
||||||
self.pipeline = Some(pipeline);
|
self.pipeline = Some(pipeline);
|
||||||
self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
|
self.interaction_transform = Some(ui_transform(meta.extent));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.meta = Some(meta);
|
self.meta = Some(meta);
|
||||||
@@ -344,14 +334,14 @@ impl OverlayBackend for ScreenBackend {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_attrib(&mut self, app: &mut AppState, value: BackendAttribValue) -> bool {
|
fn set_attrib(&mut self, _app: &mut AppState, value: BackendAttribValue) -> bool {
|
||||||
match value {
|
match value {
|
||||||
BackendAttribValue::Stereo(new) => {
|
BackendAttribValue::Stereo(new) => {
|
||||||
if let Some(stereo) = self.stereo.as_mut() {
|
if let Some(stereo) = self.stereo.as_mut() {
|
||||||
log::debug!("{}: stereo: {stereo:?} → {new:?}", self.name);
|
log::debug!("{}: stereo: {stereo:?} → {new:?}", self.name);
|
||||||
*stereo = new;
|
*stereo = new;
|
||||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||||
pipeline.set_stereo(app, new).unwrap(); // only panics if gfx is dead
|
pipeline.ensure_stereo(new);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -101,20 +101,21 @@ impl ScreenPipeline {
|
|||||||
buf_alpha,
|
buf_alpha,
|
||||||
stereo,
|
stereo,
|
||||||
};
|
};
|
||||||
me.set_stereo(app, stereo)?;
|
me.ensure_stereo(stereo);
|
||||||
Ok(me)
|
Ok(me)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_stereo(&mut self, app: &mut AppState, stereo: StereoMode) -> anyhow::Result<()> {
|
pub fn ensure_stereo(&mut self, stereo: StereoMode) {
|
||||||
|
if self.stereo == stereo {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.stereo = stereo;
|
self.stereo = stereo;
|
||||||
|
self.pass.clear(); // ensure_depth will repopulate
|
||||||
|
}
|
||||||
|
|
||||||
let depth = if matches!(stereo, StereoMode::None) {
|
fn ensure_depth(&mut self, app: &mut AppState, depth: usize) -> anyhow::Result<()> {
|
||||||
1
|
while self.pass.len() < depth {
|
||||||
} else {
|
|
||||||
2
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.pass.len() < depth {
|
|
||||||
self.pass.push(Self::create_pass(
|
self.pass.push(Self::create_pass(
|
||||||
app,
|
app,
|
||||||
self.pipeline.clone(),
|
self.pipeline.clone(),
|
||||||
@@ -124,21 +125,17 @@ impl ScreenPipeline {
|
|||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.pass.len() > depth {
|
while self.pass.len() > depth {
|
||||||
self.pass.pop();
|
self.pass.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (eye, current) in self.pass.iter_mut().enumerate() {
|
for (eye, current) in self.pass.iter_mut().enumerate() {
|
||||||
let verts = stereo_mode_to_verts(stereo, eye);
|
let verts = stereo_mode_to_verts(self.stereo, eye);
|
||||||
current.buf_vert.write()?.copy_from_slice(&verts);
|
current.buf_vert.write()?.copy_from_slice(&verts);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_depth(&self) -> u32 {
|
|
||||||
self.pass.len() as _
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_extent(
|
pub fn set_extent(
|
||||||
&mut self,
|
&mut self,
|
||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
@@ -147,18 +144,7 @@ impl ScreenPipeline {
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.extentf = extentf;
|
self.extentf = extentf;
|
||||||
self.offsetf = offsetf;
|
self.offsetf = offsetf;
|
||||||
|
self.pass.clear();
|
||||||
for (eye, pass) in self.pass.iter_mut().enumerate() {
|
|
||||||
*pass = Self::create_pass(
|
|
||||||
app,
|
|
||||||
self.pipeline.clone(),
|
|
||||||
extentf,
|
|
||||||
offsetf,
|
|
||||||
self.buf_alpha.clone(),
|
|
||||||
)?;
|
|
||||||
let verts = stereo_mode_to_verts(self.stereo, eye);
|
|
||||||
pass.buf_vert.write()?.copy_from_slice(&verts);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.mouse = Self::create_mouse_pass(
|
self.mouse = Self::create_mouse_pass(
|
||||||
app,
|
app,
|
||||||
@@ -251,6 +237,8 @@ impl ScreenPipeline {
|
|||||||
app: &mut AppState,
|
app: &mut AppState,
|
||||||
rdr: &mut RenderResources,
|
rdr: &mut RenderResources,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
self.ensure_depth(app, rdr.cmd_bufs.len())?;
|
||||||
|
|
||||||
self.buf_alpha.write()?[0] = rdr.alpha;
|
self.buf_alpha.write()?[0] = rdr.alpha;
|
||||||
|
|
||||||
for (eye, cmd_buf) in rdr.cmd_bufs.iter_mut().enumerate() {
|
for (eye, cmd_buf) in rdr.cmd_bufs.iter_mut().enumerate() {
|
||||||
@@ -503,12 +491,13 @@ pub(super) struct WlxCaptureOut {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WlxCaptureOut {
|
impl WlxCaptureOut {
|
||||||
pub(super) fn get_frame_meta(&self, config: &GeneralConfig) -> FrameMeta {
|
pub(super) fn get_frame_meta(&self, config: &GeneralConfig, stereo: StereoMode) -> FrameMeta {
|
||||||
FrameMeta {
|
FrameMeta {
|
||||||
clear: WGfxClearMode::DontCare,
|
clear: WGfxClearMode::DontCare,
|
||||||
extent: extent_from_format(self.format, config),
|
extent: extent_from_format(self.format, config),
|
||||||
transform: affine_from_format(&self.format),
|
transform: affine_from_format(&self.format),
|
||||||
format: self.image.format(),
|
format: self.image.format(),
|
||||||
|
stereo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -721,7 +710,7 @@ const fn receive_callback_dummy(_: &DummyDrmExporter, frame: WlxFrame) -> Option
|
|||||||
Some(frame)
|
Some(frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 3] {
|
fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 2] {
|
||||||
// screens above a certain resolution will have severe aliasing
|
// screens above a certain resolution will have severe aliasing
|
||||||
let height_limit = if config.screen_render_down {
|
let height_limit = if config.screen_render_down {
|
||||||
u32::from(config.screen_max_height.min(2560))
|
u32::from(config.screen_max_height.min(2560))
|
||||||
@@ -731,7 +720,7 @@ fn extent_from_format(fmt: FrameFormat, config: &GeneralConfig) -> [u32; 3] {
|
|||||||
|
|
||||||
let h = fmt.height.min(height_limit);
|
let h = fmt.height.min(height_limit);
|
||||||
let w = (fmt.width as f32 / fmt.height as f32 * h as f32) as u32;
|
let w = (fmt.width as f32 / fmt.height as f32 * h as f32) as u32;
|
||||||
[w, h, 1]
|
[w, h]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn affine_from_format(format: &FrameFormat) -> Affine3A {
|
fn affine_from_format(format: &FrameFormat) -> Affine3A {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub struct MirrorBackend {
|
|||||||
name: Arc<str>,
|
name: Arc<str>,
|
||||||
renderer: Option<ScreenBackend>,
|
renderer: Option<ScreenBackend>,
|
||||||
selector: Option<PinnedSelectorFuture>,
|
selector: Option<PinnedSelectorFuture>,
|
||||||
last_extent: [u32; 3],
|
last_extent: [u32; 2],
|
||||||
interaction_transform: Option<Affine2>,
|
interaction_transform: Option<Affine2>,
|
||||||
}
|
}
|
||||||
impl MirrorBackend {
|
impl MirrorBackend {
|
||||||
@@ -59,7 +59,7 @@ impl MirrorBackend {
|
|||||||
name,
|
name,
|
||||||
renderer: None,
|
renderer: None,
|
||||||
selector: Some(selector),
|
selector: Some(selector),
|
||||||
last_extent: [0; 3],
|
last_extent: [0; 2],
|
||||||
interaction_transform: None,
|
interaction_transform: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ impl OverlayBackend for MirrorBackend {
|
|||||||
let extent = meta.extent;
|
let extent = meta.extent;
|
||||||
if self.last_extent != extent {
|
if self.last_extent != extent {
|
||||||
self.last_extent = extent;
|
self.last_extent = extent;
|
||||||
self.interaction_transform = Some(ui_transform([extent[0], extent[1]]));
|
self.interaction_transform = Some(ui_transform(extent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ pub struct WvrWindowBackend {
|
|||||||
stereo: Option<StereoMode>,
|
stereo: Option<StereoMode>,
|
||||||
cur_image: Option<Arc<ImageView>>,
|
cur_image: Option<Arc<ImageView>>,
|
||||||
panel: GuiPanel<WindowHandle>,
|
panel: GuiPanel<WindowHandle>,
|
||||||
inner_extent: [u32; 3],
|
inner_extent: [u32; 2],
|
||||||
mouse_transform: Affine2,
|
mouse_transform: Affine2,
|
||||||
uv_range: RangeInclusive<f32>,
|
uv_range: RangeInclusive<f32>,
|
||||||
panel_hovered: bool,
|
panel_hovered: bool,
|
||||||
@@ -208,7 +208,7 @@ impl WvrWindowBackend {
|
|||||||
None
|
None
|
||||||
},
|
},
|
||||||
cur_image: None,
|
cur_image: None,
|
||||||
inner_extent: [0, 0, 1],
|
inner_extent: [0, 0],
|
||||||
panel,
|
panel,
|
||||||
mouse_transform: Affine2::ZERO,
|
mouse_transform: Affine2::ZERO,
|
||||||
uv_range: 0.0..=1.0,
|
uv_range: 0.0..=1.0,
|
||||||
@@ -217,7 +217,7 @@ impl WvrWindowBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply_extent(&mut self, app: &mut AppState, meta: &FrameMeta) -> anyhow::Result<()> {
|
fn apply_extent(&mut self, app: &mut AppState, meta: &FrameMeta) -> anyhow::Result<()> {
|
||||||
self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
|
self.interaction_transform = Some(ui_transform(meta.extent));
|
||||||
|
|
||||||
let scale = vec2(
|
let scale = vec2(
|
||||||
((meta.extent[0] + BORDER_SIZE * 2) as f32) / (meta.extent[0] as f32),
|
((meta.extent[0] + BORDER_SIZE * 2) as f32) / (meta.extent[0] as f32),
|
||||||
@@ -300,7 +300,7 @@ impl OverlayBackend for WvrWindowBackend {
|
|||||||
with_states(toplevel.wl_surface(), |states| {
|
with_states(toplevel.wl_surface(), |states| {
|
||||||
if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) {
|
if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) {
|
||||||
let mut meta = FrameMeta {
|
let mut meta = FrameMeta {
|
||||||
extent: surf.image.image().extent(),
|
extent: surf.image.extent_u32arr(),
|
||||||
format: surf.image.format(),
|
format: surf.image.format(),
|
||||||
clear: WGfxClearMode::Clear([0.0, 0.0, 0.0, 0.0]),
|
clear: WGfxClearMode::Clear([0.0, 0.0, 0.0, 0.0]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -310,8 +310,7 @@ impl OverlayBackend for WvrWindowBackend {
|
|||||||
meta.extent[1] += BORDER_SIZE * 2 + BAR_SIZE;
|
meta.extent[1] += BORDER_SIZE * 2 + BAR_SIZE;
|
||||||
|
|
||||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||||
meta.extent[2] = pipeline.get_depth();
|
if self.inner_extent != inner_extent {
|
||||||
if self.inner_extent[..2] != inner_extent[..2] {
|
|
||||||
pipeline.set_extent(
|
pipeline.set_extent(
|
||||||
app,
|
app,
|
||||||
[inner_extent[0] as _, inner_extent[1] as _],
|
[inner_extent[0] as _, inner_extent[1] as _],
|
||||||
@@ -327,7 +326,6 @@ impl OverlayBackend for WvrWindowBackend {
|
|||||||
self.stereo.unwrap_or(StereoMode::None),
|
self.stereo.unwrap_or(StereoMode::None),
|
||||||
[BORDER_SIZE as _, (BAR_SIZE + BORDER_SIZE) as _],
|
[BORDER_SIZE as _, (BAR_SIZE + BORDER_SIZE) as _],
|
||||||
)?;
|
)?;
|
||||||
meta.extent[2] = pipeline.get_depth();
|
|
||||||
self.apply_extent(app, &meta)?;
|
self.apply_extent(app, &meta)?;
|
||||||
self.pipeline = Some(pipeline);
|
self.pipeline = Some(pipeline);
|
||||||
}
|
}
|
||||||
@@ -388,7 +386,8 @@ impl OverlayBackend for WvrWindowBackend {
|
|||||||
.render(image, self.mouse.as_ref(), app, rdr)?;
|
.render(image, self.mouse.as_ref(), app, rdr)?;
|
||||||
|
|
||||||
for (popup_img, point) in &self.popups {
|
for (popup_img, point) in &self.popups {
|
||||||
let extentf = self.meta.as_ref().unwrap().extent.extent_f32();
|
let meta = self.meta.as_ref().unwrap();
|
||||||
|
let extentf = [meta.extent[0] as f32, meta.extent[1] as f32];
|
||||||
let popup_extentf = popup_img.extent_f32();
|
let popup_extentf = popup_img.extent_f32();
|
||||||
let mut buf_vert = app
|
let mut buf_vert = app
|
||||||
.gfx
|
.gfx
|
||||||
@@ -551,14 +550,14 @@ impl OverlayBackend for WvrWindowBackend {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_attrib(&mut self, app: &mut AppState, value: BackendAttribValue) -> bool {
|
fn set_attrib(&mut self, _app: &mut AppState, value: BackendAttribValue) -> bool {
|
||||||
match value {
|
match value {
|
||||||
BackendAttribValue::Stereo(new) => {
|
BackendAttribValue::Stereo(new) => {
|
||||||
if let Some(stereo) = self.stereo.as_mut() {
|
if let Some(stereo) = self.stereo.as_mut() {
|
||||||
log::debug!("{}: stereo: {stereo:?} → {new:?}", self.name);
|
log::debug!("{}: stereo: {stereo:?} → {new:?}", self.name);
|
||||||
*stereo = new;
|
*stereo = new;
|
||||||
if let Some(pipeline) = self.pipeline.as_mut() {
|
if let Some(pipeline) = self.pipeline.as_mut() {
|
||||||
pipeline.set_stereo(app, new).unwrap(); // only panics if gfx is dead
|
pipeline.ensure_stereo(new);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use wgui::gfx::{
|
|||||||
cmd::{GfxCommandBuffer, WGfxClearMode},
|
cmd::{GfxCommandBuffer, WGfxClearMode},
|
||||||
};
|
};
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
overlays::{BackendAttrib, BackendAttribValue},
|
overlays::{BackendAttrib, BackendAttribValue, StereoMode},
|
||||||
windowing::Positioning,
|
windowing::Positioning,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ use crate::{
|
|||||||
input::{HoverResult, PointerHit},
|
input::{HoverResult, PointerHit},
|
||||||
task::ModifyPanelCommand,
|
task::ModifyPanelCommand,
|
||||||
},
|
},
|
||||||
graphics::{ExtentExt, RenderResult},
|
graphics::RenderResult,
|
||||||
overlays::wayvr::WvrCommand,
|
overlays::wayvr::WvrCommand,
|
||||||
state::AppState,
|
state::AppState,
|
||||||
subsystem::hid::WheelDelta,
|
subsystem::hid::WheelDelta,
|
||||||
@@ -25,10 +25,11 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
pub struct FrameMeta {
|
pub struct FrameMeta {
|
||||||
pub extent: [u32; 3],
|
pub extent: [u32; 2],
|
||||||
pub transform: Affine3A,
|
pub transform: Affine3A,
|
||||||
pub format: Format,
|
pub format: Format,
|
||||||
pub clear: WGfxClearMode,
|
pub clear: WGfxClearMode,
|
||||||
|
pub stereo: StereoMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -70,7 +71,7 @@ impl RenderResources {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
cmd_bufs,
|
cmd_bufs,
|
||||||
alpha,
|
alpha,
|
||||||
extent: meta.extent.extent_u32arr(),
|
extent: meta.extent,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub enum BackendAttribValue {
|
|||||||
Icon(Arc<str>),
|
Icon(Arc<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum StereoMode {
|
pub enum StereoMode {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
|
|||||||
Reference in New Issue
Block a user