summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-02-24 23:24:48 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-02-24 23:24:48 +0100
commit5100b5d0a1f654ec1254b7765ceadfb9091d6939 (patch)
treeac33dc79803af7040659380c0c94440b29e93e77
parent368cadd25a8b57ee5c41e45d1abe8d1dfb194c69 (diff)
downloadiced-5100b5d0a1f654ec1254b7765ceadfb9091d6939.tar.gz
iced-5100b5d0a1f654ec1254b7765ceadfb9091d6939.tar.bz2
iced-5100b5d0a1f654ec1254b7765ceadfb9091d6939.zip
Introduce `iced_renderer` subcrate featuring runtime renderer fallback
-rw-r--r--Cargo.toml14
-rw-r--r--graphics/src/lib.rs2
-rw-r--r--graphics/src/renderer.rs7
-rw-r--r--graphics/src/window/gl_compositor.rs2
-rw-r--r--renderer/Cargo.toml26
-rw-r--r--renderer/src/backend.rs94
-rw-r--r--renderer/src/lib.rs17
-rw-r--r--renderer/src/settings.rs30
-rw-r--r--renderer/src/window.rs3
-rw-r--r--renderer/src/window/compositor.rs96
-rw-r--r--src/application.rs4
-rw-r--r--src/lib.rs2
-rw-r--r--wgpu/src/window.rs3
-rw-r--r--wgpu/src/window/compositor.rs139
-rw-r--r--winit/src/application.rs2
-rw-r--r--winit/src/system.rs2
16 files changed, 371 insertions, 72 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 551e12ac..d999febe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,9 +13,9 @@ categories = ["gui"]
[features]
# Enables the `Image` widget
-image = ["iced_wgpu/image", "image_rs"]
+image = ["iced_renderer/image", "image_rs"]
# Enables the `Svg` widget
-svg = ["iced_wgpu/svg"]
+svg = ["iced_renderer/svg"]
# Enables the `Canvas` widget
canvas = ["iced_graphics/canvas"]
# Enables the `QRCode` widget
@@ -35,7 +35,7 @@ system = ["iced_winit/system"]
# Enables chrome traces
chrome-trace = [
"iced_winit/chrome-trace",
- "iced_wgpu/tracing",
+ "iced_renderer/tracing",
]
[badges]
@@ -48,6 +48,7 @@ members = [
"graphics",
"lazy",
"native",
+ "renderer",
"style",
"wgpu",
"winit",
@@ -59,6 +60,7 @@ iced_core = { version = "0.8", path = "core" }
iced_futures = { version = "0.6", path = "futures" }
iced_native = { version = "0.9", path = "native" }
iced_graphics = { version = "0.7", path = "graphics" }
+iced_renderer = { version = "0.1", path = "renderer" }
iced_winit = { version = "0.8", path = "winit", features = ["application"] }
thiserror = "1.0"
@@ -67,12 +69,6 @@ version = "0.24"
package = "image"
optional = true
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-iced_wgpu = { version = "0.9", path = "wgpu" }
-
-[target.'cfg(target_arch = "wasm32")'.dependencies]
-iced_wgpu = { version = "0.9", path = "wgpu", features = ["webgl"] }
-
[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
features = ["image", "svg", "canvas", "qr_code"]
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index 41bef2c3..bbbdfa0e 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -46,9 +46,9 @@ pub use primitive::Primitive;
pub use renderer::Renderer;
pub use transformation::Transformation;
pub use viewport::Viewport;
-pub use window::compositor;
pub use iced_native::alignment;
+pub use iced_native::text;
pub use iced_native::{
Alignment, Background, Color, Font, Point, Rectangle, Size, Vector,
};
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs
index b052c094..859ebc04 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -43,8 +43,11 @@ impl<B: Backend, T> Renderer<B, T> {
/// Runs the given closure with the [`Backend`] and the recorded primitives
/// of the [`Renderer`].
- pub fn with_primitives(&mut self, f: impl FnOnce(&mut B, &[Primitive])) {
- f(&mut self.backend, &self.primitives);
+ pub fn with_primitives<O>(
+ &mut self,
+ f: impl FnOnce(&mut B, &[Primitive]) -> O,
+ ) -> O {
+ f(&mut self.backend, &self.primitives)
}
}
diff --git a/graphics/src/window/gl_compositor.rs b/graphics/src/window/gl_compositor.rs
index a45a7ca1..3e6dfd9e 100644
--- a/graphics/src/window/gl_compositor.rs
+++ b/graphics/src/window/gl_compositor.rs
@@ -1,6 +1,6 @@
//! A compositor is responsible for initializing a renderer and managing window
//! surfaces.
-use crate::compositor::Information;
+use crate::window::compositor::Information;
use crate::{Color, Error, Size, Viewport};
use core::ffi::c_void;
diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml
new file mode 100644
index 00000000..2a179f3a
--- /dev/null
+++ b/renderer/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "iced_renderer"
+version = "0.1.0"
+edition = "2021"
+
+[features]
+image = ["iced_wgpu/image"]
+svg = ["iced_wgpu/svg"]
+tracing = ["iced_wgpu/tracing"]
+
+[dependencies]
+raw-window-handle = "0.5"
+
+[dependencies.iced_native]
+version = "0.9"
+path = "../native"
+
+[dependencies.iced_graphics]
+version = "0.7"
+path = "../graphics"
+
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+iced_wgpu = { version = "0.9", path = "../wgpu" }
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+iced_wgpu = { version = "0.9", path = "../wgpu", features = ["webgl"] }
diff --git a/renderer/src/backend.rs b/renderer/src/backend.rs
new file mode 100644
index 00000000..a9a09593
--- /dev/null
+++ b/renderer/src/backend.rs
@@ -0,0 +1,94 @@
+use crate::{Font, Point, Size};
+
+use iced_graphics::backend;
+use iced_graphics::text;
+
+use std::borrow::Cow;
+
+pub enum Backend {
+ Wgpu(iced_wgpu::Backend),
+}
+
+impl iced_graphics::Backend for Backend {}
+
+impl backend::Text for Backend {
+ const ICON_FONT: Font = Font::Name("Iced-Icons");
+ const CHECKMARK_ICON: char = '\u{f00c}';
+ const ARROW_DOWN_ICON: char = '\u{e800}';
+
+ fn default_font(&self) -> Font {
+ match self {
+ Self::Wgpu(backend) => backend.default_font(),
+ }
+ }
+
+ fn default_size(&self) -> f32 {
+ match self {
+ Self::Wgpu(backend) => backend.default_size(),
+ }
+ }
+
+ fn measure(
+ &self,
+ contents: &str,
+ size: f32,
+ font: Font,
+ bounds: Size,
+ ) -> (f32, f32) {
+ match self {
+ Self::Wgpu(backend) => {
+ backend.measure(contents, size, font, bounds)
+ }
+ }
+ }
+
+ fn hit_test(
+ &self,
+ contents: &str,
+ size: f32,
+ font: Font,
+ bounds: Size,
+ position: Point,
+ nearest_only: bool,
+ ) -> Option<text::Hit> {
+ match self {
+ Self::Wgpu(backend) => backend.hit_test(
+ contents,
+ size,
+ font,
+ bounds,
+ position,
+ nearest_only,
+ ),
+ }
+ }
+
+ fn load_font(&mut self, font: Cow<'static, [u8]>) {
+ match self {
+ Self::Wgpu(backend) => {
+ backend.load_font(font);
+ }
+ }
+ }
+}
+
+#[cfg(feature = "image")]
+impl backend::Image for Backend {
+ fn dimensions(&self, handle: &iced_native::image::Handle) -> Size<u32> {
+ match self {
+ Self::Wgpu(backend) => backend.dimensions(handle),
+ }
+ }
+}
+
+#[cfg(feature = "svg")]
+impl backend::Svg for Backend {
+ fn viewport_dimensions(
+ &self,
+ handle: &iced_native::svg::Handle,
+ ) -> Size<u32> {
+ match self {
+ Self::Wgpu(backend) => backend.viewport_dimensions(handle),
+ }
+ }
+}
diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs
new file mode 100644
index 00000000..d0ba6793
--- /dev/null
+++ b/renderer/src/lib.rs
@@ -0,0 +1,17 @@
+pub mod window;
+
+mod backend;
+mod settings;
+
+pub use backend::Backend;
+pub use settings::Settings;
+
+pub use iced_graphics::{
+ Antialiasing, Color, Error, Font, Point, Size, Viewport,
+};
+
+/// The default graphics renderer for [`iced`].
+///
+/// [`iced`]: https://github.com/iced-rs/iced
+pub type Renderer<Theme = iced_native::Theme> =
+ iced_graphics::Renderer<Backend, Theme>;
diff --git a/renderer/src/settings.rs b/renderer/src/settings.rs
new file mode 100644
index 00000000..c4dc248b
--- /dev/null
+++ b/renderer/src/settings.rs
@@ -0,0 +1,30 @@
+use crate::{Antialiasing, Font};
+
+/// The settings of a [`Backend`].
+///
+/// [`Backend`]: crate::Backend
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct Settings {
+ /// The default [`Font`] to use.
+ pub default_font: Font,
+
+ /// The default size of text.
+ ///
+ /// By default, it will be set to `16.0`.
+ pub default_text_size: f32,
+
+ /// The antialiasing strategy that will be used for triangle primitives.
+ ///
+ /// By default, it is `None`.
+ pub antialiasing: Option<Antialiasing>,
+}
+
+impl Default for Settings {
+ fn default() -> Settings {
+ Settings {
+ default_font: Font::SansSerif,
+ default_text_size: 16.0,
+ antialiasing: None,
+ }
+ }
+}
diff --git a/renderer/src/window.rs b/renderer/src/window.rs
new file mode 100644
index 00000000..a7c8911b
--- /dev/null
+++ b/renderer/src/window.rs
@@ -0,0 +1,3 @@
+mod compositor;
+
+pub use compositor::Compositor;
diff --git a/renderer/src/window/compositor.rs b/renderer/src/window/compositor.rs
new file mode 100644
index 00000000..ad78d8bf
--- /dev/null
+++ b/renderer/src/window/compositor.rs
@@ -0,0 +1,96 @@
+use crate::{Backend, Color, Error, Renderer, Settings, Viewport};
+
+use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
+
+pub use iced_graphics::window::compositor::{Information, SurfaceError};
+
+pub enum Compositor<Theme> {
+ Wgpu(iced_wgpu::window::Compositor<Theme>),
+}
+
+pub enum Surface {
+ Wgpu(iced_wgpu::window::Surface),
+}
+
+impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
+ type Settings = Settings;
+ type Renderer = Renderer<Theme>;
+ type Surface = Surface;
+
+ fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
+ settings: Self::Settings,
+ compatible_window: Option<&W>,
+ ) -> Result<(Self, Self::Renderer), Error> {
+ let (compositor, backend) = iced_wgpu::window::compositor::new(
+ iced_wgpu::Settings {
+ default_font: settings.default_font,
+ default_text_size: settings.default_text_size,
+ antialiasing: settings.antialiasing,
+ ..iced_wgpu::Settings::from_env()
+ },
+ compatible_window,
+ )?;
+
+ Ok((
+ Self::Wgpu(compositor),
+ Renderer::new(Backend::Wgpu(backend)),
+ ))
+ }
+
+ fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>(
+ &mut self,
+ window: &W,
+ ) -> Surface {
+ match self {
+ Self::Wgpu(compositor) => {
+ Surface::Wgpu(compositor.create_surface(window))
+ }
+ }
+ }
+
+ fn configure_surface(
+ &mut self,
+ surface: &mut Surface,
+ width: u32,
+ height: u32,
+ ) {
+ match (self, surface) {
+ (Self::Wgpu(compositor), Surface::Wgpu(surface)) => {
+ compositor.configure_surface(surface, width, height);
+ }
+ }
+ }
+
+ fn fetch_information(&self) -> Information {
+ match self {
+ Self::Wgpu(compositor) => compositor.fetch_information(),
+ }
+ }
+
+ fn present<T: AsRef<str>>(
+ &mut self,
+ renderer: &mut Self::Renderer,
+ surface: &mut Self::Surface,
+ viewport: &Viewport,
+ background_color: Color,
+ overlay: &[T],
+ ) -> Result<(), SurfaceError> {
+ renderer.with_primitives(|backend, primitives| {
+ match (self, backend, surface) {
+ (
+ Self::Wgpu(compositor),
+ Backend::Wgpu(backend),
+ Surface::Wgpu(surface),
+ ) => iced_wgpu::window::compositor::present(
+ compositor,
+ backend,
+ surface,
+ primitives,
+ viewport,
+ background_color,
+ overlay,
+ ),
+ }
+ })
+ }
+}
diff --git a/src/application.rs b/src/application.rs
index 9a1c1855..b9871556 100644
--- a/src/application.rs
+++ b/src/application.rs
@@ -198,11 +198,11 @@ pub trait Application: Sized {
default_font: settings.default_font,
default_text_size: settings.default_text_size,
antialiasing: if settings.antialiasing {
- Some(crate::renderer::settings::Antialiasing::MSAAx4)
+ Some(crate::renderer::Antialiasing::MSAAx4)
} else {
None
},
- ..crate::renderer::Settings::from_env()
+ ..crate::renderer::Settings::default()
};
Ok(crate::runtime::application::run::<
diff --git a/src/lib.rs b/src/lib.rs
index 31ec4f48..bb162f2d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -182,7 +182,7 @@ pub mod touch;
pub mod widget;
pub mod window;
-use iced_wgpu as renderer;
+use iced_renderer as renderer;
use iced_winit as runtime;
pub use iced_native::theme;
diff --git a/wgpu/src/window.rs b/wgpu/src/window.rs
index aac5fb9e..9545a14e 100644
--- a/wgpu/src/window.rs
+++ b/wgpu/src/window.rs
@@ -1,4 +1,5 @@
//! Display rendering results on windows.
-mod compositor;
+pub mod compositor;
pub use compositor::Compositor;
+pub use wgpu::Surface;
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 365cb603..7406bfb8 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -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,
+ )
+ })
}
}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 889becad..1bfce3a1 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -17,8 +17,8 @@ use crate::{
use iced_futures::futures;
use iced_futures::futures::channel::mpsc;
-use iced_graphics::compositor;
use iced_graphics::window;
+use iced_graphics::window::compositor;
use iced_native::program::Program;
use iced_native::time::Instant;
use iced_native::user_interface::{self, UserInterface};
diff --git a/winit/src/system.rs b/winit/src/system.rs
index 619086b8..8a7b2a11 100644
--- a/winit/src/system.rs
+++ b/winit/src/system.rs
@@ -2,7 +2,7 @@
use crate::command::{self, Command};
pub use iced_native::system::*;
-use iced_graphics::compositor;
+use iced_graphics::window::compositor;
/// Query for available system information.
pub fn fetch_information<Message>(