even more error handling
This commit is contained in:
@@ -55,11 +55,11 @@ where
|
||||
crate::overlays::screen::get_screens_x11(&app.session)?
|
||||
};
|
||||
|
||||
let mut watch = create_watch::<T>(&app, &screens);
|
||||
let mut watch = create_watch::<T>(&app, &screens)?;
|
||||
watch.state.want_visible = true;
|
||||
overlays.insert(watch.state.id, watch);
|
||||
|
||||
let mut keyboard = create_keyboard(&app);
|
||||
let mut keyboard = create_keyboard(&app)?;
|
||||
keyboard.state.show_hide = true;
|
||||
keyboard.state.want_visible = false;
|
||||
overlays.insert(keyboard.state.id, keyboard);
|
||||
|
||||
@@ -25,26 +25,26 @@ pub(super) struct LinePool {
|
||||
}
|
||||
|
||||
impl LinePool {
|
||||
pub fn new(graphics: Arc<WlxGraphics>) -> Self {
|
||||
let mut command_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||
pub fn new(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
|
||||
let mut command_buffer =
|
||||
graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
||||
|
||||
let buf = vec![255; 16];
|
||||
|
||||
let texture = command_buffer.texture2d(2, 2, Format::R8G8B8A8_UNORM, &buf);
|
||||
command_buffer.build_and_execute_now();
|
||||
let texture = command_buffer.texture2d(2, 2, Format::R8G8B8A8_UNORM, &buf)?;
|
||||
command_buffer.build_and_execute_now()?;
|
||||
|
||||
graphics
|
||||
.transition_layout(
|
||||
texture.clone(),
|
||||
ImageLayout::ShaderReadOnlyOptimal,
|
||||
ImageLayout::TransferSrcOptimal,
|
||||
)
|
||||
.wait(None)
|
||||
.unwrap();
|
||||
)?
|
||||
.wait(None)?;
|
||||
|
||||
let view = ImageView::new_default(texture).unwrap();
|
||||
let view = ImageView::new_default(texture)?;
|
||||
|
||||
LinePool {
|
||||
Ok(LinePool {
|
||||
lines: IdMap::new(),
|
||||
view,
|
||||
colors: [
|
||||
@@ -54,7 +54,7 @@ impl LinePool {
|
||||
Vec4::new(0.375, 0., 0.5, 1.),
|
||||
Vec4::new(1., 0., 0., 1.),
|
||||
],
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn allocate(&mut self) -> usize {
|
||||
@@ -140,9 +140,13 @@ impl LinePool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||
pub fn update(
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<()> {
|
||||
for data in self.lines.values_mut() {
|
||||
data.after_input(overlay, app);
|
||||
data.after_input(overlay, app)?;
|
||||
if data.state.want_visible {
|
||||
if data.state.dirty {
|
||||
data.upload_texture(overlay, &app.graphics);
|
||||
@@ -153,6 +157,7 @@ impl LinePool {
|
||||
data.upload_color(overlay);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,10 +166,18 @@ struct StaticRenderer {
|
||||
}
|
||||
|
||||
impl OverlayRenderer for StaticRenderer {
|
||||
fn init(&mut self, _app: &mut AppState) {}
|
||||
fn pause(&mut self, _app: &mut AppState) {}
|
||||
fn resume(&mut self, _app: &mut AppState) {}
|
||||
fn render(&mut self, _app: &mut AppState) {}
|
||||
fn init(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn pause(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn resume(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn render(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn view(&mut self) -> Option<Arc<ImageView>> {
|
||||
Some(self.view.clone())
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
};
|
||||
|
||||
let mut state = {
|
||||
let graphics = WlxGraphics::new_openvr(instance_extensions, device_extensions_fn);
|
||||
let graphics = WlxGraphics::new_openvr(instance_extensions, device_extensions_fn)?;
|
||||
AppState::from_graphics(graphics)?
|
||||
};
|
||||
|
||||
@@ -119,7 +119,7 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
let mut next_device_update = Instant::now();
|
||||
let mut due_tasks = VecDeque::with_capacity(4);
|
||||
|
||||
let mut lines = LinePool::new(state.graphics.clone());
|
||||
let mut lines = LinePool::new(state.graphics.clone())?;
|
||||
let pointer_lines = [lines.allocate(), lines.allocate()];
|
||||
|
||||
'main_loop: loop {
|
||||
@@ -198,11 +198,11 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
}
|
||||
}
|
||||
|
||||
lines.update(&mut overlay_mngr, &mut state);
|
||||
lines.update(&mut overlay_mngr, &mut state)?;
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_input(&mut overlay_mngr, &mut state));
|
||||
for o in overlays.iter_mut() {
|
||||
o.after_input(&mut overlay_mngr, &mut state)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "osc")]
|
||||
if let Some(ref mut sender) = osc_sender {
|
||||
@@ -211,10 +211,11 @@ pub fn openvr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
|
||||
log::debug!("Rendering frame");
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.filter(|o| o.state.want_visible)
|
||||
.for_each(|o| o.render(&mut state));
|
||||
for o in overlays.iter_mut() {
|
||||
if o.state.want_visible {
|
||||
o.render(&mut state)?;
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("Rendering overlays");
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
) -> OverlayHandle {
|
||||
) -> anyhow::Result<OverlayHandle> {
|
||||
let key = format!("wlx-{}", self.state.name);
|
||||
log::debug!("Create overlay with key: {}", &key);
|
||||
let handle = match overlay.create_overlay(&key, &key) {
|
||||
@@ -51,7 +51,7 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
self.data.handle = Some(handle);
|
||||
self.data.color = Vec4::ONE;
|
||||
|
||||
self.init(app);
|
||||
self.init(app)?;
|
||||
|
||||
if self.data.width < f32::EPSILON {
|
||||
self.data.width = 1.0;
|
||||
@@ -63,15 +63,20 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
self.upload_curvature(overlay);
|
||||
self.upload_sort_order(overlay);
|
||||
|
||||
handle
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
pub(super) fn after_input(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||
pub(super) fn after_input(
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<()> {
|
||||
if self.state.want_visible && !self.data.visible {
|
||||
self.show_internal(overlay, app);
|
||||
self.show_internal(overlay, app)?;
|
||||
} else if !self.state.want_visible && self.data.visible {
|
||||
self.hide_internal(overlay, app);
|
||||
self.hide_internal(overlay, app)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn after_render(&mut self, overlay: &mut OverlayManager, graphics: &WlxGraphics) {
|
||||
@@ -85,29 +90,37 @@ impl OverlayData<OpenVrOverlayData> {
|
||||
}
|
||||
}
|
||||
|
||||
fn show_internal(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||
fn show_internal(
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<()> {
|
||||
let handle = match self.data.handle {
|
||||
Some(handle) => handle,
|
||||
None => self.initialize(overlay, app),
|
||||
None => self.initialize(overlay, app)?,
|
||||
};
|
||||
log::debug!("{}: show", self.state.name);
|
||||
if let Err(e) = overlay.set_visibility(handle, true) {
|
||||
log::error!("{}: Failed to show overlay: {}", self.state.name, e);
|
||||
}
|
||||
self.data.visible = true;
|
||||
self.backend.resume(app);
|
||||
self.backend.resume(app)
|
||||
}
|
||||
|
||||
fn hide_internal(&mut self, overlay: &mut OverlayManager, app: &mut AppState) {
|
||||
fn hide_internal(
|
||||
&mut self,
|
||||
overlay: &mut OverlayManager,
|
||||
app: &mut AppState,
|
||||
) -> anyhow::Result<()> {
|
||||
let Some(handle) = self.data.handle else {
|
||||
return;
|
||||
return Ok(());
|
||||
};
|
||||
log::debug!("{}: hide", self.state.name);
|
||||
if let Err(e) = overlay.set_visibility(handle, false) {
|
||||
log::error!("{}: Failed to hide overlay: {}", self.state.name, e);
|
||||
}
|
||||
self.data.visible = false;
|
||||
self.backend.pause(app);
|
||||
self.backend.pause(app)
|
||||
}
|
||||
|
||||
pub(super) fn upload_alpha(&self, overlay: &mut OverlayManager) {
|
||||
|
||||
@@ -31,8 +31,9 @@ pub(super) struct LinePool {
|
||||
}
|
||||
|
||||
impl LinePool {
|
||||
pub(super) fn new(graphics: Arc<WlxGraphics>) -> Self {
|
||||
let mut command_buffer = graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||
pub(super) fn new(graphics: Arc<WlxGraphics>) -> anyhow::Result<Self> {
|
||||
let mut command_buffer =
|
||||
graphics.create_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
||||
|
||||
// TODO customizable colors
|
||||
let colors = [
|
||||
@@ -43,20 +44,22 @@ impl LinePool {
|
||||
[0xff, 0x00, 0x00, 0xff],
|
||||
];
|
||||
|
||||
let views = colors
|
||||
let views: anyhow::Result<Vec<Arc<ImageView>>> = colors
|
||||
.into_iter()
|
||||
.map(|color| {
|
||||
let tex = command_buffer.texture2d(1, 1, Format::R8G8B8A8_UNORM, &color);
|
||||
ImageView::new_default(tex).unwrap()
|
||||
})
|
||||
.map(
|
||||
|color| match command_buffer.texture2d(1, 1, Format::R8G8B8A8_UNORM, &color) {
|
||||
Ok(tex) => ImageView::new_default(tex).map_err(|e| anyhow::anyhow!(e)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
|
||||
command_buffer.build_and_execute_now();
|
||||
command_buffer.build_and_execute_now()?;
|
||||
|
||||
LinePool {
|
||||
Ok(LinePool {
|
||||
lines: IdMap::new(),
|
||||
colors: views,
|
||||
}
|
||||
colors: views?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn allocate(
|
||||
@@ -132,7 +135,7 @@ impl LinePool {
|
||||
&'a mut self,
|
||||
xr: &'a XrState,
|
||||
command_buffer: &mut WlxCommandBuffer,
|
||||
) -> Result<Vec<xr::CompositionLayerQuad<xr::Vulkan>>, xr::sys::Result> {
|
||||
) -> anyhow::Result<Vec<xr::CompositionLayerQuad<xr::Vulkan>>> {
|
||||
let mut quads = Vec::new();
|
||||
|
||||
for line in self.lines.values_mut() {
|
||||
|
||||
@@ -55,12 +55,12 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
log::info!("Using environment blend mode: {:?}", environment_blend_mode);
|
||||
|
||||
let mut app_state = {
|
||||
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system);
|
||||
let graphics = WlxGraphics::new_openxr(xr_instance.clone(), system)?;
|
||||
AppState::from_graphics(graphics)?
|
||||
};
|
||||
|
||||
let mut overlays = OverlayContainer::<OpenXrOverlayData>::new(&mut app_state)?;
|
||||
let mut lines = LinePool::new(app_state.graphics.clone());
|
||||
let mut lines = LinePool::new(app_state.graphics.clone())?;
|
||||
|
||||
#[cfg(feature = "osc")]
|
||||
let mut osc_sender =
|
||||
@@ -211,9 +211,9 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
|
||||
watch_fade(&mut app_state, overlays.mut_by_id(watch_id).unwrap()); // want panic
|
||||
|
||||
overlays
|
||||
.iter_mut()
|
||||
.for_each(|o| o.after_input(&mut app_state));
|
||||
for o in overlays.iter_mut() {
|
||||
o.after_input(&mut app_state)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "osc")]
|
||||
if let Some(ref mut sender) = osc_sender {
|
||||
@@ -260,7 +260,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
let mut layers = vec![];
|
||||
let mut command_buffer = app_state
|
||||
.graphics
|
||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit);
|
||||
.create_command_buffer(CommandBufferUsage::OneTimeSubmit)?;
|
||||
|
||||
for o in overlays.iter_mut() {
|
||||
if !o.state.want_visible {
|
||||
@@ -268,11 +268,11 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
}
|
||||
|
||||
if !o.data.init {
|
||||
o.init(&mut app_state);
|
||||
o.init(&mut app_state)?;
|
||||
o.data.init = true;
|
||||
}
|
||||
|
||||
o.render(&mut app_state);
|
||||
o.render(&mut app_state)?;
|
||||
|
||||
let dist_sq = (app_state.input_state.hmd.translation - o.state.transform.translation)
|
||||
.length_squared();
|
||||
@@ -290,7 +290,7 @@ pub fn openxr_run(running: Arc<AtomicBool>) -> Result<(), BackendError> {
|
||||
layers.push((0.0, quad));
|
||||
}
|
||||
|
||||
command_buffer.build_and_execute_now();
|
||||
command_buffer.build_and_execute_now()?;
|
||||
|
||||
layers.sort_by(|a, b| b.0.total_cmp(&a.0));
|
||||
|
||||
|
||||
@@ -77,14 +77,15 @@ impl OverlayData<OpenXrOverlayData> {
|
||||
Ok(Some(quad))
|
||||
}
|
||||
|
||||
pub(super) fn after_input(&mut self, app: &mut AppState) {
|
||||
pub(super) fn after_input(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
if self.data.last_visible != self.state.want_visible {
|
||||
if self.state.want_visible {
|
||||
self.backend.resume(app);
|
||||
self.backend.resume(app)?;
|
||||
} else {
|
||||
self.backend.pause(app);
|
||||
self.backend.pause(app)?;
|
||||
}
|
||||
}
|
||||
self.data.last_visible = self.state.want_visible;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::bail;
|
||||
use ash::vk;
|
||||
use openxr as xr;
|
||||
|
||||
@@ -30,16 +31,17 @@ pub(super) fn create_swapchain_render_data(
|
||||
mip_count: 1,
|
||||
})?;
|
||||
|
||||
let shaders = graphics.shared_shaders.read().unwrap();
|
||||
let Ok(shaders) = graphics.shared_shaders.read() else {
|
||||
bail!("Failed to lock shared shaders for reading");
|
||||
};
|
||||
let pipeline = graphics.create_pipeline_dynamic(
|
||||
shaders.get("vert_common").unwrap().clone(),
|
||||
shaders.get("frag_srgb").unwrap().clone(),
|
||||
shaders.get("vert_common").unwrap().clone(), // want panic
|
||||
shaders.get("frag_srgb").unwrap().clone(), // want panic
|
||||
graphics.native_format,
|
||||
);
|
||||
)?;
|
||||
|
||||
let images = swapchain
|
||||
.enumerate_images()
|
||||
.unwrap()
|
||||
.enumerate_images()?
|
||||
.into_iter()
|
||||
.map(|handle| {
|
||||
let vk_image = vk::Image::from_raw(handle);
|
||||
@@ -83,29 +85,29 @@ impl SwapchainRenderData {
|
||||
command_buffer: &mut WlxCommandBuffer,
|
||||
view: Arc<ImageView>,
|
||||
alpha: f32,
|
||||
) -> Result<xr::SwapchainSubImage<xr::Vulkan>, xr::sys::Result> {
|
||||
) -> anyhow::Result<xr::SwapchainSubImage<xr::Vulkan>> {
|
||||
let idx = self.swapchain.acquire_image()? as usize;
|
||||
self.swapchain.wait_image(xr::Duration::INFINITE)?;
|
||||
|
||||
let render_target = &mut self.images[idx];
|
||||
command_buffer.begin_rendering(render_target.clone());
|
||||
command_buffer.begin_rendering(render_target.clone())?;
|
||||
|
||||
let target_extent = render_target.image().extent();
|
||||
|
||||
let set0 = self
|
||||
.pipeline
|
||||
.uniform_sampler(0, view.clone(), Filter::Linear);
|
||||
.uniform_sampler(0, view.clone(), Filter::Linear)?;
|
||||
|
||||
let set1 = self.pipeline.uniform_buffer(1, vec![alpha]);
|
||||
let set1 = self.pipeline.uniform_buffer(1, vec![alpha])?;
|
||||
|
||||
let pass = self.pipeline.create_pass(
|
||||
[target_extent[0] as _, target_extent[1] as _],
|
||||
command_buffer.graphics.quad_verts.clone(),
|
||||
command_buffer.graphics.quad_indices.clone(),
|
||||
vec![set0, set1],
|
||||
);
|
||||
command_buffer.run_ref(&pass);
|
||||
command_buffer.end_rendering();
|
||||
)?;
|
||||
command_buffer.run_ref(&pass)?;
|
||||
command_buffer.end_rendering()?;
|
||||
|
||||
self.swapchain.release_image()?;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use anyhow::Ok;
|
||||
use glam::{Affine2, Affine3A, Mat3A, Quat, Vec3, Vec3A};
|
||||
use vulkano::image::view::ImageView;
|
||||
|
||||
@@ -177,34 +178,35 @@ impl<T> OverlayData<T>
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
pub fn init(&mut self, app: &mut AppState) {
|
||||
pub fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.state.reset(app, true);
|
||||
self.backend.init(app);
|
||||
self.backend.init(app)
|
||||
}
|
||||
pub fn render(&mut self, app: &mut AppState) {
|
||||
self.backend.render(app);
|
||||
pub fn render(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.backend.render(app)
|
||||
}
|
||||
pub fn view(&mut self) -> Option<Arc<ImageView>> {
|
||||
self.backend.view()
|
||||
}
|
||||
pub fn set_visible(&mut self, app: &mut AppState, visible: bool) {
|
||||
pub fn set_visible(&mut self, app: &mut AppState, visible: bool) -> anyhow::Result<()> {
|
||||
let old_visible = self.state.want_visible;
|
||||
self.state.want_visible = visible;
|
||||
if visible != old_visible {
|
||||
if visible {
|
||||
self.backend.resume(app);
|
||||
self.backend.resume(app)?;
|
||||
} else {
|
||||
self.backend.pause(app);
|
||||
self.backend.pause(app)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait OverlayRenderer {
|
||||
fn init(&mut self, app: &mut AppState);
|
||||
fn pause(&mut self, app: &mut AppState);
|
||||
fn resume(&mut self, app: &mut AppState);
|
||||
fn render(&mut self, app: &mut AppState);
|
||||
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
||||
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
||||
fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
||||
fn render(&mut self, app: &mut AppState) -> anyhow::Result<()>;
|
||||
fn view(&mut self) -> Option<Arc<ImageView>>;
|
||||
fn extent(&self) -> [u32; 3];
|
||||
}
|
||||
@@ -212,10 +214,18 @@ pub trait OverlayRenderer {
|
||||
pub struct FallbackRenderer;
|
||||
|
||||
impl OverlayRenderer for FallbackRenderer {
|
||||
fn init(&mut self, _app: &mut AppState) {}
|
||||
fn pause(&mut self, _app: &mut AppState) {}
|
||||
fn resume(&mut self, _app: &mut AppState) {}
|
||||
fn render(&mut self, _app: &mut AppState) {}
|
||||
fn init(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn pause(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn resume(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn render(&mut self, _app: &mut AppState) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn view(&mut self) -> Option<Arc<ImageView>> {
|
||||
None
|
||||
}
|
||||
@@ -249,17 +259,17 @@ impl Default for SplitOverlayBackend {
|
||||
|
||||
impl OverlayBackend for SplitOverlayBackend {}
|
||||
impl OverlayRenderer for SplitOverlayBackend {
|
||||
fn init(&mut self, app: &mut AppState) {
|
||||
self.renderer.init(app);
|
||||
fn init(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.renderer.init(app)
|
||||
}
|
||||
fn pause(&mut self, app: &mut AppState) {
|
||||
self.renderer.pause(app);
|
||||
fn pause(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.renderer.pause(app)
|
||||
}
|
||||
fn resume(&mut self, app: &mut AppState) {
|
||||
self.renderer.resume(app);
|
||||
fn resume(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.renderer.resume(app)
|
||||
}
|
||||
fn render(&mut self, app: &mut AppState) {
|
||||
self.renderer.render(app);
|
||||
fn render(&mut self, app: &mut AppState) -> anyhow::Result<()> {
|
||||
self.renderer.render(app)
|
||||
}
|
||||
fn view(&mut self) -> Option<Arc<ImageView>> {
|
||||
self.renderer.view()
|
||||
|
||||
Reference in New Issue
Block a user