From 188db4da48954b95a3fe79bcd22689ffc3a661e0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 05:52:48 +0100 Subject: Draft support for dynamic custom renderer injection --- renderer/src/lib.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 9 deletions(-) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 757c264d..70741356 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -5,6 +5,7 @@ pub use iced_wgpu as wgpu; pub mod compositor; +pub mod custom; #[cfg(feature = "geometry")] pub mod geometry; @@ -38,6 +39,7 @@ pub enum Renderer { TinySkia(iced_tiny_skia::Renderer), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::Renderer), + Custom(Box), } macro_rules! delegate { @@ -46,6 +48,7 @@ macro_rules! delegate { Self::TinySkia($name) => $body, #[cfg(feature = "wgpu")] Self::Wgpu($name) => $body, + Self::Custom($name) => $body, } }; } @@ -62,6 +65,9 @@ impl Renderer { iced_wgpu::primitive::Custom::Mesh(mesh), )); } + Self::Custom(renderer) => { + renderer.draw_mesh(mesh); + } } } } @@ -96,6 +102,18 @@ impl core::Renderer for Renderer { _ => unreachable!(), } } + Self::Custom(renderer) => { + renderer.start_layer(); + + f(self); + + match self { + Self::Custom(renderer) => { + renderer.end_layer(bounds); + } + _ => unreachable!(), + } + } } } @@ -132,6 +150,18 @@ impl core::Renderer for Renderer { _ => unreachable!(), } } + Self::Custom(renderer) => { + renderer.start_transformation(); + + f(self); + + match self { + Self::Custom(renderer) => { + renderer.end_transformation(transformation); + } + _ => unreachable!(), + } + } } } @@ -140,7 +170,7 @@ impl core::Renderer for Renderer { quad: renderer::Quad, background: impl Into, ) { - delegate!(self, renderer, renderer.fill_quad(quad, background)); + delegate!(self, renderer, renderer.fill_quad(quad, background.into())); } fn clear(&mut self) { @@ -216,36 +246,43 @@ impl text::Renderer for Renderer { impl crate::core::image::Renderer for Renderer { type Handle = crate::core::image::Handle; - fn dimensions( + fn measure_image( &self, handle: &crate::core::image::Handle, ) -> core::Size { - delegate!(self, renderer, renderer.dimensions(handle)) + delegate!(self, renderer, renderer.measure_image(handle)) } - fn draw( + fn draw_image( &mut self, handle: crate::core::image::Handle, filter_method: crate::core::image::FilterMethod, bounds: Rectangle, ) { - delegate!(self, renderer, renderer.draw(handle, filter_method, bounds)); + delegate!( + self, + renderer, + renderer.draw_image(handle, filter_method, bounds) + ); } } #[cfg(feature = "svg")] impl crate::core::svg::Renderer for Renderer { - fn dimensions(&self, handle: &crate::core::svg::Handle) -> core::Size { - delegate!(self, renderer, renderer.dimensions(handle)) + fn measure_svg( + &self, + handle: &crate::core::svg::Handle, + ) -> core::Size { + delegate!(self, renderer, renderer.measure_svg(handle)) } - fn draw( + fn draw_svg( &mut self, handle: crate::core::svg::Handle, color: Option, bounds: Rectangle, ) { - delegate!(self, renderer, renderer.draw(handle, color, bounds)); + delegate!(self, renderer, renderer.draw_svg(handle, color, bounds)); } } @@ -263,6 +300,7 @@ impl crate::graphics::geometry::Renderer for Renderer { } #[cfg(feature = "wgpu")] crate::Geometry::Wgpu(_) => unreachable!(), + crate::Geometry::Custom(_) => unreachable!(), } } } @@ -274,6 +312,19 @@ impl crate::graphics::geometry::Renderer for Renderer { renderer.draw_primitive(primitive); } crate::Geometry::TinySkia(_) => unreachable!(), + crate::Geometry::Custom(_) => unreachable!(), + } + } + } + Self::Custom(renderer) => { + for layer in layers { + match layer { + crate::Geometry::Custom(geometry) => { + renderer.draw_geometry(geometry); + } + crate::Geometry::TinySkia(_) => unreachable!(), + #[cfg(feature = "wgpu")] + crate::Geometry::Wgpu(_) => unreachable!(), } } } @@ -297,6 +348,11 @@ impl iced_wgpu::primitive::pipeline::Renderer for Renderer { Self::Wgpu(renderer) => { renderer.draw_pipeline_primitive(bounds, primitive); } + Self::Custom(_renderer) => { + log::warn!( + "Custom shader primitive is unavailable with custom renderer." + ); + } } } } -- cgit From 9171df1e356530410a7ceadadd78fd3dcf150dfd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 06:00:55 +0100 Subject: Gate `Custom` variants in `iced_renderer` behind `custom` feature --- renderer/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 70741356..67096115 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -39,6 +39,7 @@ pub enum Renderer { TinySkia(iced_tiny_skia::Renderer), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::Renderer), + #[cfg(feature = "custom")] Custom(Box), } @@ -48,6 +49,7 @@ macro_rules! delegate { Self::TinySkia($name) => $body, #[cfg(feature = "wgpu")] Self::Wgpu($name) => $body, + #[cfg(feature = "custom")] Self::Custom($name) => $body, } }; @@ -65,6 +67,7 @@ impl Renderer { iced_wgpu::primitive::Custom::Mesh(mesh), )); } + #[cfg(feature = "custom")] Self::Custom(renderer) => { renderer.draw_mesh(mesh); } @@ -102,6 +105,7 @@ impl core::Renderer for Renderer { _ => unreachable!(), } } + #[cfg(feature = "custom")] Self::Custom(renderer) => { renderer.start_layer(); @@ -150,6 +154,7 @@ impl core::Renderer for Renderer { _ => unreachable!(), } } + #[cfg(feature = "custom")] Self::Custom(renderer) => { renderer.start_transformation(); @@ -300,6 +305,7 @@ impl crate::graphics::geometry::Renderer for Renderer { } #[cfg(feature = "wgpu")] crate::Geometry::Wgpu(_) => unreachable!(), + #[cfg(feature = "custom")] crate::Geometry::Custom(_) => unreachable!(), } } @@ -312,10 +318,12 @@ impl crate::graphics::geometry::Renderer for Renderer { renderer.draw_primitive(primitive); } crate::Geometry::TinySkia(_) => unreachable!(), + #[cfg(feature = "custom")] crate::Geometry::Custom(_) => unreachable!(), } } } + #[cfg(feature = "custom")] Self::Custom(renderer) => { for layer in layers { match layer { @@ -348,6 +356,7 @@ impl iced_wgpu::primitive::pipeline::Renderer for Renderer { Self::Wgpu(renderer) => { renderer.draw_pipeline_primitive(bounds, primitive); } + #[cfg(feature = "custom")] Self::Custom(_renderer) => { log::warn!( "Custom shader primitive is unavailable with custom renderer." -- cgit From 3645d34d6a1ba1247238e830e9eefd52d9e5b986 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 22:27:17 +0100 Subject: Implement composable, type-safe renderer fallback --- renderer/src/lib.rs | 368 ++++------------------------------------------------ 1 file changed, 23 insertions(+), 345 deletions(-) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 67096115..f8aa1157 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -4,364 +4,42 @@ #[cfg(feature = "wgpu")] pub use iced_wgpu as wgpu; -pub mod compositor; -pub mod custom; - -#[cfg(feature = "geometry")] -pub mod geometry; +pub mod fallback; mod settings; pub use iced_graphics as graphics; pub use iced_graphics::core; -pub use compositor::Compositor; -pub use settings::Settings; - #[cfg(feature = "geometry")] -pub use geometry::Geometry; - -use crate::core::renderer; -use crate::core::text::{self, Text}; -use crate::core::{ - Background, Color, Font, Pixels, Point, Rectangle, Transformation, -}; -use crate::graphics::text::Editor; -use crate::graphics::text::Paragraph; -use crate::graphics::Mesh; +pub use iced_graphics::geometry; -use std::borrow::Cow; +pub use settings::Settings; /// The default graphics renderer for [`iced`]. /// /// [`iced`]: https://github.com/iced-rs/iced -pub enum Renderer { - TinySkia(iced_tiny_skia::Renderer), - #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::Renderer), - #[cfg(feature = "custom")] - Custom(Box), -} - -macro_rules! delegate { - ($renderer:expr, $name:ident, $body:expr) => { - match $renderer { - Self::TinySkia($name) => $body, - #[cfg(feature = "wgpu")] - Self::Wgpu($name) => $body, - #[cfg(feature = "custom")] - Self::Custom($name) => $body, - } - }; -} - -impl Renderer { - pub fn draw_mesh(&mut self, mesh: Mesh) { - match self { - Self::TinySkia(_) => { - log::warn!("Unsupported mesh primitive: {mesh:?}"); - } - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - renderer.draw_primitive(iced_wgpu::Primitive::Custom( - iced_wgpu::primitive::Custom::Mesh(mesh), - )); - } - #[cfg(feature = "custom")] - Self::Custom(renderer) => { - renderer.draw_mesh(mesh); - } - } - } -} - -impl core::Renderer for Renderer { - fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) { - match self { - Self::TinySkia(renderer) => { - let primitives = renderer.start_layer(); - - f(self); - - match self { - Self::TinySkia(renderer) => { - renderer.end_layer(primitives, bounds); - } - #[cfg(feature = "wgpu")] - _ => unreachable!(), - } - } - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - let primitives = renderer.start_layer(); - - f(self); - - match self { - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - renderer.end_layer(primitives, bounds); - } - _ => unreachable!(), - } - } - #[cfg(feature = "custom")] - Self::Custom(renderer) => { - renderer.start_layer(); - - f(self); - - match self { - Self::Custom(renderer) => { - renderer.end_layer(bounds); - } - _ => unreachable!(), - } - } - } - } - - fn with_transformation( - &mut self, - transformation: Transformation, - f: impl FnOnce(&mut Self), - ) { - match self { - Self::TinySkia(renderer) => { - let primitives = renderer.start_transformation(); - - f(self); - - match self { - Self::TinySkia(renderer) => { - renderer.end_transformation(primitives, transformation); - } - #[cfg(feature = "wgpu")] - _ => unreachable!(), - } - } - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - let primitives = renderer.start_transformation(); - - f(self); - - match self { - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - renderer.end_transformation(primitives, transformation); - } - _ => unreachable!(), - } - } - #[cfg(feature = "custom")] - Self::Custom(renderer) => { - renderer.start_transformation(); - - f(self); - - match self { - Self::Custom(renderer) => { - renderer.end_transformation(transformation); - } - _ => unreachable!(), - } - } - } - } - - fn fill_quad( - &mut self, - quad: renderer::Quad, - background: impl Into, - ) { - delegate!(self, renderer, renderer.fill_quad(quad, background.into())); - } - - fn clear(&mut self) { - delegate!(self, renderer, renderer.clear()); - } -} +#[cfg(not(feature = "wgpu"))] +pub type Renderer = iced_tiny_skia::Renderer; -impl text::Renderer for Renderer { - type Font = Font; - type Paragraph = Paragraph; - type Editor = Editor; - - const ICON_FONT: Font = iced_tiny_skia::Renderer::ICON_FONT; - const CHECKMARK_ICON: char = iced_tiny_skia::Renderer::CHECKMARK_ICON; - const ARROW_DOWN_ICON: char = iced_tiny_skia::Renderer::ARROW_DOWN_ICON; - - fn default_font(&self) -> Self::Font { - delegate!(self, renderer, renderer.default_font()) - } - - fn default_size(&self) -> Pixels { - delegate!(self, renderer, renderer.default_size()) - } - - fn load_font(&mut self, bytes: Cow<'static, [u8]>) { - delegate!(self, renderer, renderer.load_font(bytes)); - } - - fn fill_paragraph( - &mut self, - paragraph: &Self::Paragraph, - position: Point, - color: Color, - clip_bounds: Rectangle, - ) { - delegate!( - self, - renderer, - renderer.fill_paragraph(paragraph, position, color, clip_bounds) - ); - } - - fn fill_editor( - &mut self, - editor: &Self::Editor, - position: Point, - color: Color, - clip_bounds: Rectangle, - ) { - delegate!( - self, - renderer, - renderer.fill_editor(editor, position, color, clip_bounds) - ); - } - - fn fill_text( - &mut self, - text: Text<'_, Self::Font>, - position: Point, - color: Color, - clip_bounds: Rectangle, - ) { - delegate!( - self, - renderer, - renderer.fill_text(text, position, color, clip_bounds) - ); - } -} - -#[cfg(feature = "image")] -impl crate::core::image::Renderer for Renderer { - type Handle = crate::core::image::Handle; - - fn measure_image( - &self, - handle: &crate::core::image::Handle, - ) -> core::Size { - delegate!(self, renderer, renderer.measure_image(handle)) - } - - fn draw_image( - &mut self, - handle: crate::core::image::Handle, - filter_method: crate::core::image::FilterMethod, - bounds: Rectangle, - ) { - delegate!( - self, - renderer, - renderer.draw_image(handle, filter_method, bounds) - ); - } -} - -#[cfg(feature = "svg")] -impl crate::core::svg::Renderer for Renderer { - fn measure_svg( - &self, - handle: &crate::core::svg::Handle, - ) -> core::Size { - delegate!(self, renderer, renderer.measure_svg(handle)) - } - - fn draw_svg( - &mut self, - handle: crate::core::svg::Handle, - color: Option, - bounds: Rectangle, - ) { - delegate!(self, renderer, renderer.draw_svg(handle, color, bounds)); - } -} - -#[cfg(feature = "geometry")] -impl crate::graphics::geometry::Renderer for Renderer { - type Geometry = crate::Geometry; +/// The default graphics renderer for [`iced`]. +/// +/// [`iced`]: https://github.com/iced-rs/iced +#[cfg(feature = "wgpu")] +pub type Renderer = + fallback::Renderer; - fn draw(&mut self, layers: Vec) { - match self { - Self::TinySkia(renderer) => { - for layer in layers { - match layer { - crate::Geometry::TinySkia(primitive) => { - renderer.draw_primitive(primitive); - } - #[cfg(feature = "wgpu")] - crate::Geometry::Wgpu(_) => unreachable!(), - #[cfg(feature = "custom")] - crate::Geometry::Custom(_) => unreachable!(), - } - } - } - #[cfg(feature = "wgpu")] - Self::Wgpu(renderer) => { - for layer in layers { - match layer { - crate::Geometry::Wgpu(primitive) => { - renderer.draw_primitive(primitive); - } - crate::Geometry::TinySkia(_) => unreachable!(), - #[cfg(feature = "custom")] - crate::Geometry::Custom(_) => unreachable!(), - } - } - } - #[cfg(feature = "custom")] - Self::Custom(renderer) => { - for layer in layers { - match layer { - crate::Geometry::Custom(geometry) => { - renderer.draw_geometry(geometry); - } - crate::Geometry::TinySkia(_) => unreachable!(), - #[cfg(feature = "wgpu")] - crate::Geometry::Wgpu(_) => unreachable!(), - } - } - } - } - } -} +/// The default graphics compositor for [`iced`]. +/// +/// [`iced`]: https://github.com/iced-rs/iced +#[cfg(not(feature = "wgpu"))] +pub type Compositor = iced_tiny_skia::window::Compositor; +/// The default graphics renderer for [`iced`]. +/// +/// [`iced`]: https://github.com/iced-rs/iced #[cfg(feature = "wgpu")] -impl iced_wgpu::primitive::pipeline::Renderer for Renderer { - fn draw_pipeline_primitive( - &mut self, - bounds: Rectangle, - primitive: impl wgpu::primitive::pipeline::Primitive, - ) { - match self { - Self::TinySkia(_renderer) => { - log::warn!( - "Custom shader primitive is unavailable with tiny-skia." - ); - } - Self::Wgpu(renderer) => { - renderer.draw_pipeline_primitive(bounds, primitive); - } - #[cfg(feature = "custom")] - Self::Custom(_renderer) => { - log::warn!( - "Custom shader primitive is unavailable with custom renderer." - ); - } - } - } -} +pub type Compositor = fallback::Compositor< + iced_wgpu::window::Compositor, + iced_tiny_skia::window::Compositor, +>; -- cgit From 1f13a91361258a1607c71f4840a26a6437f88612 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 Mar 2024 05:27:31 +0100 Subject: Make `iced_tiny_skia` optional with a `tiny-skia` feature --- renderer/src/lib.rs | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index f8aa1157..199b431e 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -19,27 +19,40 @@ pub use settings::Settings; /// The default graphics renderer for [`iced`]. /// /// [`iced`]: https://github.com/iced-rs/iced -#[cfg(not(feature = "wgpu"))] -pub type Renderer = iced_tiny_skia::Renderer; - -/// The default graphics renderer for [`iced`]. -/// -/// [`iced`]: https://github.com/iced-rs/iced -#[cfg(feature = "wgpu")] -pub type Renderer = - fallback::Renderer; +pub type Renderer = renderer::Renderer; /// The default graphics compositor for [`iced`]. /// /// [`iced`]: https://github.com/iced-rs/iced -#[cfg(not(feature = "wgpu"))] -pub type Compositor = iced_tiny_skia::window::Compositor; - -/// The default graphics renderer for [`iced`]. -/// -/// [`iced`]: https://github.com/iced-rs/iced -#[cfg(feature = "wgpu")] -pub type Compositor = fallback::Compositor< - iced_wgpu::window::Compositor, - iced_tiny_skia::window::Compositor, ->; +pub type Compositor = renderer::Compositor; + +#[cfg(all(feature = "wgpu", feature = "tiny-skia"))] +mod renderer { + pub type Renderer = crate::fallback::Renderer< + iced_wgpu::Renderer, + iced_tiny_skia::Renderer, + >; + + pub type Compositor = crate::fallback::Compositor< + iced_wgpu::window::Compositor, + iced_tiny_skia::window::Compositor, + >; +} + +#[cfg(all(feature = "wgpu", not(feature = "tiny-skia")))] +mod renderer { + pub type Renderer = iced_wgpu::Renderer; + pub type Compositor = iced_wgpu::window::Compositor; +} + +#[cfg(all(not(feature = "wgpu"), feature = "tiny-skia"))] +mod renderer { + pub type Renderer = iced_tiny_skia::Renderer; + pub type Compositor = iced_tiny_skia::window::Compositor; +} + +#[cfg(not(any(feature = "wgpu", feature = "tiny-skia")))] +mod renderer { + pub type Renderer = (); + pub type Compositor = (); +} -- cgit From 5137d655e6bbd29581fc1469d0385515113f2999 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 Mar 2024 07:09:51 +0100 Subject: Allow custom renderers in `Program` and `Application` --- renderer/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 199b431e..7c48995d 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -6,16 +6,12 @@ pub use iced_wgpu as wgpu; pub mod fallback; -mod settings; - pub use iced_graphics as graphics; pub use iced_graphics::core; #[cfg(feature = "geometry")] pub use iced_graphics::geometry; -pub use settings::Settings; - /// The default graphics renderer for [`iced`]. /// /// [`iced`]: https://github.com/iced-rs/iced -- cgit From 5cd98f069dea8720bca7748d6c12fa410cbe79b5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 7 Apr 2024 12:42:12 +0200 Subject: Use built-in `[lints]` table in `Cargo.toml` --- renderer/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 7c48995d..056da5ed 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -1,5 +1,4 @@ -#![forbid(rust_2018_idioms)] -#![deny(unsafe_code, unused_results, rustdoc::broken_intra_doc_links)] +//! The official renderer for iced. #![cfg_attr(docsrs, feature(doc_auto_cfg))] #[cfg(feature = "wgpu")] pub use iced_wgpu as wgpu; -- cgit From 468794d918eb06c1dbebb33c32b10017ad335f05 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 22 May 2024 12:36:04 +0200 Subject: Produce a compile error in `iced_renderer` when no backend is enabled --- renderer/src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'renderer/src/lib.rs') diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index 056da5ed..220542e1 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -48,6 +48,13 @@ mod renderer { #[cfg(not(any(feature = "wgpu", feature = "tiny-skia")))] mod renderer { + #[cfg(not(debug_assertions))] + compile_error!( + "Cannot compile `iced_renderer` in release mode \ + without a renderer feature enabled. \ + Enable either the `wgpu` or `tiny-skia` feature, or both." + ); + pub type Renderer = (); pub type Compositor = (); } -- cgit