Introduce iced_renderer subcrate featuring runtime renderer fallback

This commit is contained in:
Héctor Ramón Jiménez 2023-02-24 23:24:48 +01:00
parent 368cadd25a
commit 5100b5d0a1
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
16 changed files with 371 additions and 72 deletions

View file

@ -1,4 +1,5 @@
//! Display rendering results on windows.
mod compositor;
pub mod compositor;
pub use compositor::Compositor;
pub use wgpu::Surface;

View file

@ -1,8 +1,9 @@
use crate::{Backend, Color, Error, Renderer, Settings, Viewport};
//! Connect a window with a renderer.
use crate::{Backend, Color, Error, Primitive, Renderer, Settings, Viewport};
use futures::stream::{self, StreamExt};
use iced_graphics::compositor;
use iced_graphics::window::compositor;
use iced_native::futures;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
@ -112,6 +113,77 @@ impl<Theme> Compositor<Theme> {
}
}
/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and
/// window.
pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>(
settings: Settings,
compatible_window: Option<&W>,
) -> Result<(Compositor<Theme>, Backend), Error> {
let compositor = futures::executor::block_on(Compositor::request(
settings,
compatible_window,
))
.ok_or(Error::GraphicsAdapterNotFound)?;
let backend = compositor.create_backend();
Ok((compositor, backend))
}
/// Presents the given primitives with the given [`Compositor`] and [`Backend`].
pub fn present<Theme, T: AsRef<str>>(
compositor: &mut Compositor<Theme>,
backend: &mut Backend,
surface: &mut wgpu::Surface,
primitives: &[Primitive],
viewport: &Viewport,
background_color: Color,
overlay: &[T],
) -> Result<(), compositor::SurfaceError> {
match surface.get_current_texture() {
Ok(frame) => {
let mut encoder = compositor.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor {
label: Some("iced_wgpu encoder"),
},
);
let view = &frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
backend.present(
&compositor.device,
&compositor.queue,
&mut encoder,
Some(background_color),
view,
primitives,
viewport,
overlay,
);
// Submit work
let _submission = compositor.queue.submit(Some(encoder.finish()));
frame.present();
Ok(())
}
Err(error) => match error {
wgpu::SurfaceError::Timeout => {
Err(compositor::SurfaceError::Timeout)
}
wgpu::SurfaceError::Outdated => {
Err(compositor::SurfaceError::Outdated)
}
wgpu::SurfaceError::Lost => Err(compositor::SurfaceError::Lost),
wgpu::SurfaceError::OutOfMemory => {
Err(compositor::SurfaceError::OutOfMemory)
}
},
}
}
impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
type Settings = Settings;
type Renderer = Renderer<Theme>;
@ -121,13 +193,7 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
settings: Self::Settings,
compatible_window: Option<&W>,
) -> Result<(Self, Self::Renderer), Error> {
let compositor = futures::executor::block_on(Self::request(
settings,
compatible_window,
))
.ok_or(Error::GraphicsAdapterNotFound)?;
let backend = compositor.create_backend();
let (compositor, backend) = new(settings, compatible_window)?;
Ok((compositor, Renderer::new(backend)))
}
@ -178,49 +244,16 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
background_color: Color,
overlay: &[T],
) -> Result<(), compositor::SurfaceError> {
match surface.get_current_texture() {
Ok(frame) => {
let mut encoder = self.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor {
label: Some("iced_wgpu encoder"),
},
);
let view = &frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
renderer.with_primitives(|backend, primitives| {
backend.present(
&self.device,
&self.queue,
&mut encoder,
Some(background_color),
view,
primitives,
viewport,
overlay,
);
});
// Submit work
let _submission = self.queue.submit(Some(encoder.finish()));
frame.present();
Ok(())
}
Err(error) => match error {
wgpu::SurfaceError::Timeout => {
Err(compositor::SurfaceError::Timeout)
}
wgpu::SurfaceError::Outdated => {
Err(compositor::SurfaceError::Outdated)
}
wgpu::SurfaceError::Lost => Err(compositor::SurfaceError::Lost),
wgpu::SurfaceError::OutOfMemory => {
Err(compositor::SurfaceError::OutOfMemory)
}
},
}
renderer.with_primitives(|backend, primitives| {
present(
self,
backend,
surface,
primitives,
viewport,
background_color,
overlay,
)
})
}
}