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/compositor.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'renderer/src/compositor.rs') diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index c23a814c..058fa36d 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -1,4 +1,5 @@ use crate::core::Color; +use crate::custom; use crate::graphics::compositor::{Information, SurfaceError, Window}; use crate::graphics::{Error, Viewport}; use crate::{Renderer, Settings}; @@ -10,12 +11,14 @@ pub enum Compositor { TinySkia(iced_tiny_skia::window::Compositor), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::window::Compositor), + Custom(Box), } pub enum Surface { TinySkia(iced_tiny_skia::window::Surface), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::window::Surface<'static>), + Custom(Box), } impl crate::graphics::Compositor for Compositor { @@ -56,6 +59,9 @@ impl crate::graphics::Compositor for Compositor { Compositor::Wgpu(compositor) => { Renderer::Wgpu(compositor.create_renderer()) } + Compositor::Custom(compositor) => { + Renderer::Custom(compositor.create_renderer()) + } } } @@ -73,6 +79,9 @@ impl crate::graphics::Compositor for Compositor { Self::Wgpu(compositor) => { Surface::Wgpu(compositor.create_surface(window, width, height)) } + Self::Custom(compositor) => Surface::Custom( + compositor.create_surface(Box::new(window), width, height), + ), } } @@ -90,6 +99,9 @@ impl crate::graphics::Compositor for Compositor { (Self::Wgpu(compositor), Surface::Wgpu(surface)) => { compositor.configure_surface(surface, width, height); } + (Self::Custom(compositor), Surface::Custom(surface)) => { + compositor.configure_surface(surface, width, height); + } #[allow(unreachable_patterns)] _ => panic!( "The provided surface is not compatible with the compositor." @@ -102,6 +114,7 @@ impl crate::graphics::Compositor for Compositor { Self::TinySkia(compositor) => compositor.fetch_information(), #[cfg(feature = "wgpu")] Self::Wgpu(compositor) => compositor.fetch_information(), + Self::Custom(compositor) => compositor.fetch_information(), } } @@ -144,6 +157,18 @@ impl crate::graphics::Compositor for Compositor { overlay, ) }), + + #[cfg(feature = "wgpu")] + ( + Self::Custom(compositor), + crate::Renderer::Custom(renderer), + Surface::Custom(surface), + ) => renderer.present( + surface.as_mut(), + viewport, + background_color, + compositor.as_mut(), + ), #[allow(unreachable_patterns)] _ => panic!( "The provided renderer or surface are not compatible \ -- 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/compositor.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'renderer/src/compositor.rs') diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 058fa36d..012ad3c0 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -1,5 +1,4 @@ use crate::core::Color; -use crate::custom; use crate::graphics::compositor::{Information, SurfaceError, Window}; use crate::graphics::{Error, Viewport}; use crate::{Renderer, Settings}; @@ -11,14 +10,16 @@ pub enum Compositor { TinySkia(iced_tiny_skia::window::Compositor), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::window::Compositor), - Custom(Box), + #[cfg(feature = "custom")] + Custom(Box), } pub enum Surface { TinySkia(iced_tiny_skia::window::Surface), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::window::Surface<'static>), - Custom(Box), + #[cfg(feature = "custom")] + Custom(Box), } impl crate::graphics::Compositor for Compositor { @@ -59,6 +60,7 @@ impl crate::graphics::Compositor for Compositor { Compositor::Wgpu(compositor) => { Renderer::Wgpu(compositor.create_renderer()) } + #[cfg(feature = "custom")] Compositor::Custom(compositor) => { Renderer::Custom(compositor.create_renderer()) } @@ -79,6 +81,7 @@ impl crate::graphics::Compositor for Compositor { Self::Wgpu(compositor) => { Surface::Wgpu(compositor.create_surface(window, width, height)) } + #[cfg(feature = "custom")] Self::Custom(compositor) => Surface::Custom( compositor.create_surface(Box::new(window), width, height), ), @@ -99,6 +102,7 @@ impl crate::graphics::Compositor for Compositor { (Self::Wgpu(compositor), Surface::Wgpu(surface)) => { compositor.configure_surface(surface, width, height); } + #[cfg(feature = "custom")] (Self::Custom(compositor), Surface::Custom(surface)) => { compositor.configure_surface(surface, width, height); } @@ -114,6 +118,7 @@ impl crate::graphics::Compositor for Compositor { Self::TinySkia(compositor) => compositor.fetch_information(), #[cfg(feature = "wgpu")] Self::Wgpu(compositor) => compositor.fetch_information(), + #[cfg(feature = "custom")] Self::Custom(compositor) => compositor.fetch_information(), } } @@ -158,7 +163,7 @@ impl crate::graphics::Compositor for Compositor { ) }), - #[cfg(feature = "wgpu")] + #[cfg(feature = "custom")] ( Self::Custom(compositor), crate::Renderer::Custom(renderer), -- cgit From 7e4ae8450e1f28c15717ca5ca9748981af9c9541 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 06:03:31 +0100 Subject: Use `&mut dyn Surface` instead of `&mut Box` --- renderer/src/compositor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'renderer/src/compositor.rs') diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 012ad3c0..3d0b3ad0 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -104,7 +104,7 @@ impl crate::graphics::Compositor for Compositor { } #[cfg(feature = "custom")] (Self::Custom(compositor), Surface::Custom(surface)) => { - compositor.configure_surface(surface, width, height); + compositor.configure_surface(surface.as_mut(), width, height); } #[allow(unreachable_patterns)] _ => panic!( -- 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/compositor.rs | 299 --------------------------------------------- 1 file changed, 299 deletions(-) (limited to 'renderer/src/compositor.rs') diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 3d0b3ad0..8b137891 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -1,300 +1 @@ -use crate::core::Color; -use crate::graphics::compositor::{Information, SurfaceError, Window}; -use crate::graphics::{Error, Viewport}; -use crate::{Renderer, Settings}; -use std::env; -use std::future::Future; - -pub enum Compositor { - TinySkia(iced_tiny_skia::window::Compositor), - #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Compositor), - #[cfg(feature = "custom")] - Custom(Box), -} - -pub enum Surface { - TinySkia(iced_tiny_skia::window::Surface), - #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Surface<'static>), - #[cfg(feature = "custom")] - Custom(Box), -} - -impl crate::graphics::Compositor for Compositor { - type Settings = Settings; - type Renderer = Renderer; - type Surface = Surface; - - fn new( - settings: Self::Settings, - compatible_window: W, - ) -> impl Future> { - let candidates = - Candidate::list_from_env().unwrap_or(Candidate::default_list()); - - async move { - let mut error = Error::GraphicsAdapterNotFound; - - for candidate in candidates { - match candidate.build(settings, compatible_window.clone()).await - { - Ok(compositor) => return Ok(compositor), - Err(new_error) => { - error = new_error; - } - } - } - - Err(error) - } - } - - fn create_renderer(&self) -> Self::Renderer { - match self { - Compositor::TinySkia(compositor) => { - Renderer::TinySkia(compositor.create_renderer()) - } - #[cfg(feature = "wgpu")] - Compositor::Wgpu(compositor) => { - Renderer::Wgpu(compositor.create_renderer()) - } - #[cfg(feature = "custom")] - Compositor::Custom(compositor) => { - Renderer::Custom(compositor.create_renderer()) - } - } - } - - fn create_surface( - &mut self, - window: W, - width: u32, - height: u32, - ) -> Surface { - match self { - Self::TinySkia(compositor) => Surface::TinySkia( - compositor.create_surface(window, width, height), - ), - #[cfg(feature = "wgpu")] - Self::Wgpu(compositor) => { - Surface::Wgpu(compositor.create_surface(window, width, height)) - } - #[cfg(feature = "custom")] - Self::Custom(compositor) => Surface::Custom( - compositor.create_surface(Box::new(window), width, height), - ), - } - } - - fn configure_surface( - &mut self, - surface: &mut Surface, - width: u32, - height: u32, - ) { - match (self, surface) { - (Self::TinySkia(compositor), Surface::TinySkia(surface)) => { - compositor.configure_surface(surface, width, height); - } - #[cfg(feature = "wgpu")] - (Self::Wgpu(compositor), Surface::Wgpu(surface)) => { - compositor.configure_surface(surface, width, height); - } - #[cfg(feature = "custom")] - (Self::Custom(compositor), Surface::Custom(surface)) => { - compositor.configure_surface(surface.as_mut(), width, height); - } - #[allow(unreachable_patterns)] - _ => panic!( - "The provided surface is not compatible with the compositor." - ), - } - } - - fn fetch_information(&self) -> Information { - match self { - Self::TinySkia(compositor) => compositor.fetch_information(), - #[cfg(feature = "wgpu")] - Self::Wgpu(compositor) => compositor.fetch_information(), - #[cfg(feature = "custom")] - Self::Custom(compositor) => compositor.fetch_information(), - } - } - - fn present>( - &mut self, - renderer: &mut Self::Renderer, - surface: &mut Self::Surface, - viewport: &Viewport, - background_color: Color, - overlay: &[T], - ) -> Result<(), SurfaceError> { - match (self, renderer, surface) { - ( - Self::TinySkia(_compositor), - crate::Renderer::TinySkia(renderer), - Surface::TinySkia(surface), - ) => renderer.with_primitives(|backend, primitives| { - iced_tiny_skia::window::compositor::present( - backend, - surface, - primitives, - viewport, - background_color, - overlay, - ) - }), - #[cfg(feature = "wgpu")] - ( - Self::Wgpu(compositor), - crate::Renderer::Wgpu(renderer), - Surface::Wgpu(surface), - ) => renderer.with_primitives(|backend, primitives| { - iced_wgpu::window::compositor::present( - compositor, - backend, - surface, - primitives, - viewport, - background_color, - overlay, - ) - }), - - #[cfg(feature = "custom")] - ( - Self::Custom(compositor), - crate::Renderer::Custom(renderer), - Surface::Custom(surface), - ) => renderer.present( - surface.as_mut(), - viewport, - background_color, - compositor.as_mut(), - ), - #[allow(unreachable_patterns)] - _ => panic!( - "The provided renderer or surface are not compatible \ - with the compositor." - ), - } - } - - fn screenshot>( - &mut self, - renderer: &mut Self::Renderer, - surface: &mut Self::Surface, - viewport: &Viewport, - background_color: Color, - overlay: &[T], - ) -> Vec { - match (self, renderer, surface) { - ( - Self::TinySkia(_compositor), - Renderer::TinySkia(renderer), - Surface::TinySkia(surface), - ) => renderer.with_primitives(|backend, primitives| { - iced_tiny_skia::window::compositor::screenshot( - surface, - backend, - primitives, - viewport, - background_color, - overlay, - ) - }), - #[cfg(feature = "wgpu")] - ( - Self::Wgpu(compositor), - Renderer::Wgpu(renderer), - Surface::Wgpu(_), - ) => renderer.with_primitives(|backend, primitives| { - iced_wgpu::window::compositor::screenshot( - compositor, - backend, - primitives, - viewport, - background_color, - overlay, - ) - }), - #[allow(unreachable_patterns)] - _ => panic!( - "The provided renderer or backend are not compatible \ - with the compositor." - ), - } - } -} - -enum Candidate { - Wgpu, - TinySkia, -} - -impl Candidate { - fn default_list() -> Vec { - vec![ - #[cfg(feature = "wgpu")] - Self::Wgpu, - Self::TinySkia, - ] - } - - fn list_from_env() -> Option> { - let backends = env::var("ICED_BACKEND").ok()?; - - Some( - backends - .split(',') - .map(str::trim) - .map(|backend| match backend { - "wgpu" => Self::Wgpu, - "tiny-skia" => Self::TinySkia, - _ => panic!("unknown backend value: \"{backend}\""), - }) - .collect(), - ) - } - - async fn build( - self, - settings: Settings, - _compatible_window: W, - ) -> Result { - match self { - Self::TinySkia => { - let compositor = iced_tiny_skia::window::compositor::new( - iced_tiny_skia::Settings { - default_font: settings.default_font, - default_text_size: settings.default_text_size, - }, - _compatible_window, - ); - - Ok(Compositor::TinySkia(compositor)) - } - #[cfg(feature = "wgpu")] - Self::Wgpu => { - let compositor = 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, - ) - .await?; - - Ok(Compositor::Wgpu(compositor)) - } - #[cfg(not(feature = "wgpu"))] - Self::Wgpu => { - panic!("`wgpu` feature was not enabled in `iced_renderer`") - } - } - } -} -- cgit