bevy_mod_openxr/openxr/
layer_builder.rs1use std::mem;
2
3use bevy::ecs::world::World;
4use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrSpace};
5use openxr::{sys, CompositionLayerFlags, Fovf, Posef, Rect2Di};
6
7use crate::graphics::graphics_match;
8use crate::resources::*;
9use crate::spaces::OxrSpaceExt as _;
10
11pub trait LayerProvider {
12 fn get<'a>(&'a self, world: &'a World) -> Option<Box<dyn CompositionLayer<'a> + 'a>>;
13}
14
15pub struct ProjectionLayer;
16
17pub struct PassthroughLayer;
18
19impl LayerProvider for ProjectionLayer {
20 fn get<'a>(&self, world: &'a World) -> Option<Box<dyn CompositionLayer<'a> + 'a>> {
21 let stage = world.get_resource::<XrPrimaryReferenceSpace>()?;
22 let openxr_views = world.get_resource::<OxrViews>()?;
23 let swapchain = world.get_resource::<OxrSwapchain>()?;
24 let graphics_info = world.get_resource::<OxrCurrentSessionConfig>()?;
25 let rect = openxr::Rect2Di {
26 offset: openxr::Offset2Di { x: 0, y: 0 },
27 extent: openxr::Extent2Di {
28 width: graphics_info.resolution.x as _,
29 height: graphics_info.resolution.y as _,
30 },
31 };
32
33 if openxr_views.len() < 2 {
34 return None;
35 }
36
37 Some(Box::new(
38 CompositionLayerProjection::new()
39 .layer_flags(CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA)
40 .space(stage)
41 .views(&[
42 CompositionLayerProjectionView::new()
43 .pose(openxr_views.0[0].pose)
44 .fov(openxr_views.0[0].fov)
45 .sub_image(
46 SwapchainSubImage::new()
47 .swapchain(swapchain)
48 .image_array_index(0)
49 .image_rect(rect),
50 ),
51 CompositionLayerProjectionView::new()
52 .pose(openxr_views.0[1].pose)
53 .fov(openxr_views.0[1].fov)
54 .sub_image(
55 SwapchainSubImage::new()
56 .swapchain(swapchain)
57 .image_array_index(1)
58 .image_rect(rect),
59 ),
60 ]),
61 ))
62 }
63}
64
65impl LayerProvider for PassthroughLayer {
66 fn get(&self, world: &World) -> Option<Box<dyn CompositionLayer>> {
67 Some(Box::new(
68 CompositionLayerPassthrough::new()
69 .layer_handle(world.get_resource::<OxrPassthroughLayer>()?)
70 .layer_flags(CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA),
71 ))
72 }
73}
74
75#[derive(Copy, Clone)]
76pub struct SwapchainSubImage<'a> {
77 inner: sys::SwapchainSubImage,
78 swapchain: Option<&'a OxrSwapchain>,
79}
80
81impl<'a> SwapchainSubImage<'a> {
82 #[inline]
83 pub fn new() -> Self {
84 Self {
85 inner: sys::SwapchainSubImage {
86 ..unsafe { mem::zeroed() }
87 },
88 swapchain: None,
89 }
90 }
91 #[inline]
92 pub fn into_raw(self) -> sys::SwapchainSubImage {
93 self.inner
94 }
95 #[inline]
96 pub fn as_raw(&self) -> &sys::SwapchainSubImage {
97 &self.inner
98 }
99 #[inline]
100 pub fn swapchain(mut self, value: &'a OxrSwapchain) -> Self {
101 graphics_match!(
102 &value.0;
103 swap => self.inner.swapchain = swap.as_raw()
104 );
105 self.swapchain = Some(value);
106 self
107 }
108 #[inline]
109 pub fn image_rect(mut self, value: Rect2Di) -> Self {
110 self.inner.image_rect = value;
111 self
112 }
113 #[inline]
114 pub fn image_array_index(mut self, value: u32) -> Self {
115 self.inner.image_array_index = value;
116 self
117 }
118}
119
120impl Default for SwapchainSubImage<'_> {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126#[derive(Copy, Clone)]
127pub struct CompositionLayerProjectionView<'a> {
128 inner: sys::CompositionLayerProjectionView,
129 swapchain: Option<&'a OxrSwapchain>,
130}
131
132impl<'a> CompositionLayerProjectionView<'a> {
133 #[inline]
134 pub fn new() -> Self {
135 Self {
136 inner: sys::CompositionLayerProjectionView {
137 ty: sys::StructureType::COMPOSITION_LAYER_PROJECTION_VIEW,
138 ..unsafe { mem::zeroed() }
139 },
140 swapchain: None,
141 }
142 }
143 #[inline]
144 pub fn into_raw(self) -> sys::CompositionLayerProjectionView {
145 self.inner
146 }
147 #[inline]
148 pub fn as_raw(&self) -> &sys::CompositionLayerProjectionView {
149 &self.inner
150 }
151 #[inline]
152 pub fn pose(mut self, value: Posef) -> Self {
153 self.inner.pose = value;
154 self
155 }
156 #[inline]
157 pub fn fov(mut self, value: Fovf) -> Self {
158 self.inner.fov = value;
159 self
160 }
161 #[inline]
162 pub fn sub_image(mut self, value: SwapchainSubImage<'a>) -> Self {
163 self.inner.sub_image = value.inner;
164 self.swapchain = value.swapchain;
165 self
166 }
167}
168impl Default for CompositionLayerProjectionView<'_> {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173pub unsafe trait CompositionLayer<'a> {
178 fn swapchain(&self) -> Option<&'a OxrSwapchain>;
179 fn header(&self) -> &sys::CompositionLayerBaseHeader;
180}
181#[derive(Clone)]
182pub struct CompositionLayerProjection<'a> {
183 inner: sys::CompositionLayerProjection,
184 swapchain: Option<&'a OxrSwapchain>,
185 views: Vec<sys::CompositionLayerProjectionView>,
186}
187impl<'a> CompositionLayerProjection<'a> {
188 #[inline]
189 pub fn new() -> Self {
190 Self {
191 inner: sys::CompositionLayerProjection {
192 ty: sys::StructureType::COMPOSITION_LAYER_PROJECTION,
193 ..unsafe { mem::zeroed() }
194 },
195 swapchain: None,
196 views: Vec::new(),
197 }
198 }
199 #[inline]
200 pub fn into_raw(self) -> sys::CompositionLayerProjection {
201 self.inner
202 }
203 #[inline]
204 pub fn as_raw(&self) -> &sys::CompositionLayerProjection {
205 &self.inner
206 }
207 #[inline]
208 pub fn layer_flags(mut self, value: CompositionLayerFlags) -> Self {
209 self.inner.layer_flags = value;
210 self
211 }
212 #[inline]
213 pub fn space(mut self, value: &XrSpace) -> Self {
214 self.inner.space = value.as_raw_openxr_space();
215 self
216 }
217 #[inline]
218 pub fn views(mut self, value: &[CompositionLayerProjectionView<'a>]) -> Self {
219 self.views = value.iter().map(|view| view.inner).collect();
220 self.inner.views = self.views.as_slice().as_ptr() as *const _ as _;
221 self.inner.view_count = self.views.len() as u32;
222 self
223 }
224}
225unsafe impl<'a> CompositionLayer<'a> for CompositionLayerProjection<'a> {
226 fn swapchain(&self) -> Option<&'a OxrSwapchain> {
227 self.swapchain
228 }
229
230 fn header(&self) -> &sys::CompositionLayerBaseHeader {
231 unsafe { mem::transmute(&self.inner) }
232 }
233}
234impl Default for CompositionLayerProjection<'_> {
235 fn default() -> Self {
236 Self::new()
237 }
238}
239pub struct CompositionLayerPassthrough {
240 inner: sys::CompositionLayerPassthroughFB,
241}
242impl Default for CompositionLayerPassthrough {
243 fn default() -> Self {
244 Self::new()
245 }
246}
247
248impl CompositionLayerPassthrough {
249 #[inline]
250 pub const fn new() -> Self {
251 Self {
252 inner: openxr::sys::CompositionLayerPassthroughFB {
253 ty: openxr::sys::CompositionLayerPassthroughFB::TYPE,
254 ..unsafe { mem::zeroed() }
255 },
256 }
257 }
258 #[inline]
259 pub fn layer_handle(mut self, layer_handle: &OxrPassthroughLayer) -> Self {
260 self.inner.layer_handle = *layer_handle.inner();
261 self
262 }
263 #[inline]
264 pub fn layer_flags(mut self, value: CompositionLayerFlags) -> Self {
265 self.inner.flags = value;
266 self
267 }
268}
269unsafe impl<'a> CompositionLayer<'a> for CompositionLayerPassthrough {
270 fn swapchain(&self) -> Option<&'a OxrSwapchain> {
271 None
272 }
273
274 fn header(&self) -> &sys::CompositionLayerBaseHeader {
275 unsafe { mem::transmute(&self.inner) }
276 }
277}