Files
bevy_oxr/crates/bevy_openxr/src/openxr/session.rs
2024-07-03 19:37:40 -05:00

118 lines
4.5 KiB
Rust

use std::ffi::c_void;
use crate::next_chain::{OxrNextChain, OxrNextChainStructBase, OxrNextChainStructProvider};
use crate::resources::{OxrPassthrough, OxrPassthroughLayer, OxrSwapchain};
use crate::types::{Result, SwapchainCreateInfo};
use bevy::prelude::*;
use openxr::AnyGraphics;
use crate::graphics::{graphics_match, GraphicsExt, GraphicsType, GraphicsWrap};
/// Graphics agnostic wrapper around [openxr::Session].
///
/// See [`openxr::Session`] for other available methods.
#[derive(Resource, Deref, Clone)]
pub struct OxrSession(
/// A session handle with [`AnyGraphics`].
/// Having this here allows the majority of [`Session`](openxr::Session)'s methods to work without having to rewrite them.
#[deref]
pub(crate) openxr::Session<AnyGraphics>,
/// A [`GraphicsWrap`] with [`openxr::Session<G>`] as the inner type.
/// This is so that we can still operate on functions that don't take [`AnyGraphics`] as the generic.
pub(crate) GraphicsWrap<Self>,
);
impl GraphicsType for OxrSession {
type Inner<G: GraphicsExt> = openxr::Session<G>;
}
impl<G: GraphicsExt> From<openxr::Session<G>> for OxrSession {
fn from(session: openxr::Session<G>) -> Self {
Self::from_inner(session)
}
}
impl OxrSession {
/// Creates a new [`OxrSession`] from an [`openxr::Session`].
/// In the majority of cases, you should use [`create_session`](OxrInstance::create_session) instead.
pub fn from_inner<G: GraphicsExt>(session: openxr::Session<G>) -> Self {
Self(session.clone().into_any_graphics(), G::wrap(session))
}
/// Returns [`GraphicsWrap`] with [`openxr::Session<G>`] as the inner type.
///
/// This can be useful if you need access to the original [`openxr::Session`] with the graphics API still specified.
pub fn typed_session(&self) -> &GraphicsWrap<Self> {
&self.1
}
/// Enumerates all available swapchain formats and converts them to wgpu's [`TextureFormat`](wgpu::TextureFormat).
///
/// Calls [`enumerate_swapchain_formats`](openxr::Session::enumerate_swapchain_formats) internally.
pub fn enumerate_swapchain_formats(&self) -> Result<Vec<wgpu::TextureFormat>> {
graphics_match!(
&self.1;
session => Ok(session.enumerate_swapchain_formats()?.into_iter().filter_map(Api::into_wgpu_format).collect())
)
}
/// Creates an [OxrSwapchain].
///
/// Calls [`create_swapchain`](openxr::Session::create_swapchain) internally.
pub fn create_swapchain(&self, info: SwapchainCreateInfo) -> Result<OxrSwapchain> {
Ok(OxrSwapchain(graphics_match!(
&self.1;
session => session.create_swapchain(&info.try_into()?)? => OxrSwapchain
)))
}
/// Creates a passthrough.
///
/// Requires [`XR_FB_passthrough`](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_FB_passthrough).
///
/// Calls [`create_passthrough`](openxr::Session::create_passthrough) internally.
pub fn create_passthrough(&self, flags: openxr::PassthroughFlagsFB) -> Result<OxrPassthrough> {
Ok(OxrPassthrough(
graphics_match! {
&self.1;
session => session.create_passthrough(flags)?
},
flags,
))
}
/// Creates a passthrough layer that can be used to make a [`CompositionLayerPassthrough`](crate::layer_builder::CompositionLayerPassthrough) for frame submission.
///
/// Requires [`XR_FB_passthrough`](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_FB_passthrough).
///
/// Calls [`create_passthrough_layer`](openxr::Session::create_passthrough_layer) internally.
pub fn create_passthrough_layer(
&self,
passthrough: &OxrPassthrough,
purpose: openxr::PassthroughLayerPurposeFB,
) -> Result<OxrPassthroughLayer> {
Ok(OxrPassthroughLayer(graphics_match! {
&self.1;
session => session.create_passthrough_layer(&passthrough.0, passthrough.1, purpose)?
}))
}
}
pub trait OxrSessionCreateNextProvider: OxrNextChainStructProvider {}
/// NonSend Resource
#[derive(Default)]
pub struct OxrSessionCreateNextChain(OxrNextChain);
impl OxrSessionCreateNextChain {
pub fn push<T: OxrSessionCreateNextProvider>(&mut self, info_struct: T) {
self.0.push(info_struct)
}
pub fn chain(&self) -> Option<&OxrNextChainStructBase> {
self.0.chain()
}
pub fn chain_pointer(&self) -> *const c_void {
self.0.chain_pointer()
}
}