From 8c373cd497e370d356b480380482779397bdb510 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 25 Feb 2023 15:38:25 +0100 Subject: Scaffold `iced_tiny_skia` and connect it to `iced_renderer` --- tiny_skia/src/window/compositor.rs | 96 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tiny_skia/src/window/compositor.rs (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs new file mode 100644 index 00000000..053bb29b --- /dev/null +++ b/tiny_skia/src/window/compositor.rs @@ -0,0 +1,96 @@ +use crate::{Backend, Color, Error, Renderer, Settings, Viewport}; + +use iced_graphics::window::compositor::{self, Information, SurfaceError}; +use iced_graphics::Primitive; + +use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use std::marker::PhantomData; + +pub struct Compositor { + _theme: PhantomData, +} + +pub struct Surface; + +impl iced_graphics::window::Compositor for Compositor { + type Settings = Settings; + type Renderer = Renderer; + type Surface = Surface; + + fn new( + settings: Self::Settings, + _compatible_window: Option<&W>, + ) -> Result<(Self, Self::Renderer), Error> { + let (compositor, backend) = new(settings); + + Ok((compositor, Renderer::new(backend))) + } + + fn create_surface( + &mut self, + _window: &W, + ) -> Surface { + // TODO + Surface + } + + fn configure_surface( + &mut self, + _surface: &mut Surface, + _width: u32, + _height: u32, + ) { + // TODO + } + + fn fetch_information(&self) -> Information { + Information { + adapter: String::from("CPU"), + backend: String::from("tiny-skia"), + } + } + + fn present>( + &mut self, + renderer: &mut Self::Renderer, + surface: &mut Self::Surface, + viewport: &Viewport, + background_color: Color, + overlay: &[T], + ) -> Result<(), SurfaceError> { + renderer.with_primitives(|backend, primitives| { + present( + self, + backend, + surface, + primitives, + viewport, + background_color, + overlay, + ) + }) + } +} + +pub fn new(settings: Settings) -> (Compositor, Backend) { + // TODO + ( + Compositor { + _theme: PhantomData, + }, + Backend::new(settings), + ) +} + +pub fn present>( + _compositor: &mut Compositor, + _backend: &mut Backend, + _surface: &mut Surface, + _primitives: &[Primitive], + _viewport: &Viewport, + _background_color: Color, + _overlay: &[T], +) -> Result<(), compositor::SurfaceError> { + // TODO + Ok(()) +} -- cgit From 535d7a4d57e131e661587b36e41820dd6ccccc3e Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 25 Feb 2023 16:05:42 +0100 Subject: Implement basic presentation with `softbuffer` for `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 66 ++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 14 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 053bb29b..164d99c6 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -10,7 +10,11 @@ pub struct Compositor { _theme: PhantomData, } -pub struct Surface; +pub struct Surface { + window: softbuffer::GraphicsContext, + pixels: tiny_skia::Pixmap, + buffer: Vec, +} impl iced_graphics::window::Compositor for Compositor { type Settings = Settings; @@ -28,19 +32,33 @@ impl iced_graphics::window::Compositor for Compositor { fn create_surface( &mut self, - _window: &W, + window: &W, + width: u32, + height: u32, ) -> Surface { - // TODO - Surface + let window = + unsafe { softbuffer::GraphicsContext::new(window, window) } + .expect("Create softbuffer for window"); + + let pixels = tiny_skia::Pixmap::new(width, height) + .expect("Create pixmap for window"); + + Surface { + window, + pixels, + buffer: vec![0; (width * height) as usize], + } } fn configure_surface( &mut self, - _surface: &mut Surface, - _width: u32, - _height: u32, + surface: &mut Surface, + width: u32, + height: u32, ) { - // TODO + surface.pixels = tiny_skia::Pixmap::new(width, height) + .expect("Create pixmap for window"); + surface.buffer = vec![0; (width * height) as usize]; } fn fetch_information(&self) -> Information { @@ -84,13 +102,33 @@ pub fn new(settings: Settings) -> (Compositor, Backend) { pub fn present>( _compositor: &mut Compositor, - _backend: &mut Backend, - _surface: &mut Surface, - _primitives: &[Primitive], - _viewport: &Viewport, - _background_color: Color, - _overlay: &[T], + backend: &mut Backend, + surface: &mut Surface, + primitives: &[Primitive], + viewport: &Viewport, + background_color: Color, + overlay: &[T], ) -> Result<(), compositor::SurfaceError> { + backend.draw( + &mut surface.pixels, + primitives, + viewport, + background_color, + overlay, + ); + + for (i, pixel) in surface.pixels.pixels_mut().iter().enumerate() { + surface.buffer[i] = u32::from(pixel.red()) << 16 + | u32::from(pixel.green()) << 8 + | u32::from(pixel.blue()); + } + + surface.window.set_buffer( + &surface.buffer, + surface.pixels.width() as u16, + surface.pixels.height() as u16, + ); + // TODO Ok(()) } -- cgit From 445b31c6c5f16ecc9f07bd072f246e827aa5b854 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 25 Feb 2023 21:06:58 +0100 Subject: Resize `Surface::buffer` instead of reallocating in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 164d99c6..8bb52a03 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -58,7 +58,8 @@ impl iced_graphics::window::Compositor for Compositor { ) { surface.pixels = tiny_skia::Pixmap::new(width, height) .expect("Create pixmap for window"); - surface.buffer = vec![0; (width * height) as usize]; + + surface.buffer.resize((width * height) as usize, 0); } fn fetch_information(&self) -> Information { -- cgit From 744f3028f484c44899fed56d9190387569828a95 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 26 Feb 2023 00:49:27 +0100 Subject: Use `Surface::buffer` directly for drawing in `iced_tiny_skia` ... with a nice little color trick :^) --- tiny_skia/src/window/compositor.rs | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 8bb52a03..2bd5831e 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -12,7 +12,6 @@ pub struct Compositor { pub struct Surface { window: softbuffer::GraphicsContext, - pixels: tiny_skia::Pixmap, buffer: Vec, } @@ -40,13 +39,9 @@ impl iced_graphics::window::Compositor for Compositor { unsafe { softbuffer::GraphicsContext::new(window, window) } .expect("Create softbuffer for window"); - let pixels = tiny_skia::Pixmap::new(width, height) - .expect("Create pixmap for window"); - Surface { window, - pixels, - buffer: vec![0; (width * height) as usize], + buffer: vec![0; width as usize * height as usize], } } @@ -56,9 +51,6 @@ impl iced_graphics::window::Compositor for Compositor { width: u32, height: u32, ) { - surface.pixels = tiny_skia::Pixmap::new(width, height) - .expect("Create pixmap for window"); - surface.buffer.resize((width * height) as usize, 0); } @@ -110,26 +102,26 @@ pub fn present>( background_color: Color, overlay: &[T], ) -> Result<(), compositor::SurfaceError> { + let physical_size = viewport.physical_size(); + backend.draw( - &mut surface.pixels, + &mut tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut surface.buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"), primitives, viewport, background_color, overlay, ); - for (i, pixel) in surface.pixels.pixels_mut().iter().enumerate() { - surface.buffer[i] = u32::from(pixel.red()) << 16 - | u32::from(pixel.green()) << 8 - | u32::from(pixel.blue()); - } - surface.window.set_buffer( &surface.buffer, - surface.pixels.width() as u16, - surface.pixels.height() as u16, + physical_size.width as u16, + physical_size.height as u16, ); - // TODO Ok(()) } -- cgit From 5fd5d1cdf8e5354788dc40729c4565ef377d3bba Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Mar 2023 21:34:26 +0100 Subject: Implement `Canvas` support for `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 2bd5831e..08159cd8 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,7 +1,6 @@ -use crate::{Backend, Color, Error, Renderer, Settings, Viewport}; +use crate::{Backend, Color, Error, Primitive, Renderer, Settings, Viewport}; use iced_graphics::window::compositor::{self, Information, SurfaceError}; -use iced_graphics::Primitive; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; -- cgit From 868f79d22e2be82e98b06d66da3b4cbc6139d7c7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 Mar 2023 00:40:36 +0100 Subject: Reuse `ClipMask` in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 08159cd8..76f371e1 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -6,6 +6,7 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; pub struct Compositor { + clip_mask: tiny_skia::ClipMask, _theme: PhantomData, } @@ -83,9 +84,10 @@ impl iced_graphics::window::Compositor for Compositor { } pub fn new(settings: Settings) -> (Compositor, Backend) { - // TODO + // TOD ( Compositor { + clip_mask: tiny_skia::ClipMask::new(), _theme: PhantomData, }, Backend::new(settings), @@ -93,7 +95,7 @@ pub fn new(settings: Settings) -> (Compositor, Backend) { } pub fn present>( - _compositor: &mut Compositor, + compositor: &mut Compositor, backend: &mut Backend, surface: &mut Surface, primitives: &[Primitive], @@ -110,6 +112,7 @@ pub fn present>( physical_size.height, ) .expect("Create pixel map"), + &mut compositor.clip_mask, primitives, viewport, background_color, -- cgit From 3a0d34c0240f4421737a6a08761f99d6f8140d02 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 4 Mar 2023 05:37:11 +0100 Subject: Create `iced_widget` subcrate and re-organize the whole codebase --- tiny_skia/src/window/compositor.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 76f371e1..cea1cabf 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,6 +1,7 @@ -use crate::{Backend, Color, Error, Primitive, Renderer, Settings, Viewport}; - -use iced_graphics::window::compositor::{self, Information, SurfaceError}; +use crate::core::Color; +use crate::graphics::compositor::{self, Information, SurfaceError}; +use crate::graphics::{Error, Primitive, Viewport}; +use crate::{Backend, Renderer, Settings}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; @@ -15,7 +16,7 @@ pub struct Surface { buffer: Vec, } -impl iced_graphics::window::Compositor for Compositor { +impl crate::graphics::Compositor for Compositor { type Settings = Settings; type Renderer = Renderer; type Surface = Surface; -- cgit From 4ede482ab5ff6364237f5f4626784075045d5dfb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 5 Apr 2023 18:41:40 +0200 Subject: Present new frame only when damaged in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index cea1cabf..6e4bb6ef 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -106,7 +106,7 @@ pub fn present>( ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); - backend.draw( + let drawn = backend.draw( &mut tiny_skia::PixmapMut::from_bytes( bytemuck::cast_slice_mut(&mut surface.buffer), physical_size.width, @@ -120,11 +120,13 @@ pub fn present>( overlay, ); - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); + if drawn { + surface.window.set_buffer( + &surface.buffer, + physical_size.width as u16, + physical_size.height as u16, + ); + } Ok(()) } -- cgit From 92d61e5c592818745abbab245a82cb14b262ae67 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 5 Apr 2023 19:23:48 +0200 Subject: Use `softbuffer` fork with owned pixel buffer --- tiny_skia/src/window/compositor.rs | 42 +++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 6e4bb6ef..5b1e56a4 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -5,6 +5,7 @@ use crate::{Backend, Renderer, Settings}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; +use std::num::NonZeroU32; pub struct Compositor { clip_mask: tiny_skia::ClipMask, @@ -12,8 +13,7 @@ pub struct Compositor { } pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec, + window: softbuffer::Surface, } impl crate::graphics::Compositor for Compositor { @@ -36,14 +36,20 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { - let window = - unsafe { softbuffer::GraphicsContext::new(window, window) } - .expect("Create softbuffer for window"); + let platform = unsafe { softbuffer::Context::new(window) } + .expect("Create softbuffer context"); - Surface { - window, - buffer: vec![0; width as usize * height as usize], - } + let mut window = unsafe { softbuffer::Surface::new(&platform, window) } + .expect("Create softbuffer surface"); + + window + .resize( + NonZeroU32::new(width).unwrap(), + NonZeroU32::new(height).unwrap(), + ) + .expect("Resize surface"); + + Surface { window } } fn configure_surface( @@ -52,7 +58,13 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); + surface + .window + .resize( + NonZeroU32::new(width).unwrap(), + NonZeroU32::new(height).unwrap(), + ) + .expect("Resize surface"); } fn fetch_information(&self) -> Information { @@ -106,9 +118,11 @@ pub fn present>( ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); + let mut buffer = surface.window.buffer_mut().expect("Get window buffer"); + let drawn = backend.draw( &mut tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), + bytemuck::cast_slice_mut(&mut buffer), physical_size.width, physical_size.height, ) @@ -121,11 +135,7 @@ pub fn present>( ); if drawn { - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); + let _ = buffer.present(); } Ok(()) -- cgit From 940a47eafd098dce3567a95c38dc8697b0fc7115 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 5 Apr 2023 19:30:07 +0200 Subject: Revert "Use `softbuffer` fork with owned pixel buffer" This reverts commit 92d61e5c592818745abbab245a82cb14b262ae67. The owned pixel buffer zeroes the data in some platforms. `softbuffer` will need some first-class support for damage regions. --- tiny_skia/src/window/compositor.rs | 42 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 26 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 5b1e56a4..6e4bb6ef 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -5,7 +5,6 @@ use crate::{Backend, Renderer, Settings}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; -use std::num::NonZeroU32; pub struct Compositor { clip_mask: tiny_skia::ClipMask, @@ -13,7 +12,8 @@ pub struct Compositor { } pub struct Surface { - window: softbuffer::Surface, + window: softbuffer::GraphicsContext, + buffer: Vec, } impl crate::graphics::Compositor for Compositor { @@ -36,20 +36,14 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { - let platform = unsafe { softbuffer::Context::new(window) } - .expect("Create softbuffer context"); + let window = + unsafe { softbuffer::GraphicsContext::new(window, window) } + .expect("Create softbuffer for window"); - let mut window = unsafe { softbuffer::Surface::new(&platform, window) } - .expect("Create softbuffer surface"); - - window - .resize( - NonZeroU32::new(width).unwrap(), - NonZeroU32::new(height).unwrap(), - ) - .expect("Resize surface"); - - Surface { window } + Surface { + window, + buffer: vec![0; width as usize * height as usize], + } } fn configure_surface( @@ -58,13 +52,7 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - surface - .window - .resize( - NonZeroU32::new(width).unwrap(), - NonZeroU32::new(height).unwrap(), - ) - .expect("Resize surface"); + surface.buffer.resize((width * height) as usize, 0); } fn fetch_information(&self) -> Information { @@ -118,11 +106,9 @@ pub fn present>( ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); - let mut buffer = surface.window.buffer_mut().expect("Get window buffer"); - let drawn = backend.draw( &mut tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut buffer), + bytemuck::cast_slice_mut(&mut surface.buffer), physical_size.width, physical_size.height, ) @@ -135,7 +121,11 @@ pub fn present>( ); if drawn { - let _ = buffer.present(); + surface.window.set_buffer( + &surface.buffer, + physical_size.width as u16, + physical_size.height as u16, + ); } Ok(()) -- cgit From 16e6efe020e75d51958875fa198196534679af8d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 8 Apr 2023 05:58:27 +0200 Subject: Use `pixels` for presentation in `iced_tiny_skia` when possible --- tiny_skia/src/window/compositor.rs | 76 +++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 13 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 6e4bb6ef..5a0097df 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -11,9 +11,13 @@ pub struct Compositor { _theme: PhantomData, } -pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec, +pub enum Surface { + Cpu { + window: softbuffer::GraphicsContext, + buffer: Vec, + }, + #[cfg(feature = "gpu")] + Gpu { pixels: pixels::Pixels }, } impl crate::graphics::Compositor for Compositor { @@ -36,11 +40,29 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { + #[cfg(feature = "gpu")] + { + let surface_texture = + pixels::SurfaceTexture::new(width, height, window); + + if let Ok(pixels) = + pixels::PixelsBuilder::new(width, height, surface_texture) + .texture_format(pixels::wgpu::TextureFormat::Bgra8UnormSrgb) + .build() + { + log::info!("GPU surface created"); + + return Surface::Gpu { pixels }; + } + } + let window = unsafe { softbuffer::GraphicsContext::new(window, window) } .expect("Create softbuffer for window"); - Surface { + log::info!("CPU surface created"); + + Surface::Cpu { window, buffer: vec![0; width as usize * height as usize], } @@ -52,7 +74,19 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); + match surface { + Surface::Cpu { buffer, .. } => { + buffer.resize((width * height) as usize, 0); + } + #[cfg(feature = "gpu")] + Surface::Gpu { pixels } => { + pixels + .resize_surface(width, height) + .expect("Resize surface"); + + pixels.resize_buffer(width, height).expect("Resize buffer"); + } + } } fn fetch_information(&self) -> Information { @@ -106,9 +140,15 @@ pub fn present>( ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); + let buffer = match surface { + Surface::Cpu { buffer, .. } => bytemuck::cast_slice_mut(buffer), + #[cfg(feature = "gpu")] + Surface::Gpu { pixels } => pixels.frame_mut(), + }; + let drawn = backend.draw( &mut tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), + buffer, physical_size.width, physical_size.height, ) @@ -121,12 +161,22 @@ pub fn present>( ); if drawn { - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); + match surface { + Surface::Cpu { window, buffer } => { + window.set_buffer( + buffer, + physical_size.width as u16, + physical_size.height as u16, + ); + + Ok(()) + } + #[cfg(feature = "gpu")] + Surface::Gpu { pixels } => { + pixels.render().map_err(|_| compositor::SurfaceError::Lost) + } + } + } else { + Ok(()) } - - Ok(()) } -- cgit From 435b54e57ecdaf08b1f36626f0000438895c909d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 26 Apr 2023 16:09:36 +0200 Subject: Revert "Use `pixels` for presentation in `iced_tiny_skia` when possible" This reverts commit 16e6efe020e75d51958875fa198196534679af8d. --- tiny_skia/src/window/compositor.rs | 76 +++++++------------------------------- 1 file changed, 13 insertions(+), 63 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 5a0097df..6e4bb6ef 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -11,13 +11,9 @@ pub struct Compositor { _theme: PhantomData, } -pub enum Surface { - Cpu { - window: softbuffer::GraphicsContext, - buffer: Vec, - }, - #[cfg(feature = "gpu")] - Gpu { pixels: pixels::Pixels }, +pub struct Surface { + window: softbuffer::GraphicsContext, + buffer: Vec, } impl crate::graphics::Compositor for Compositor { @@ -40,29 +36,11 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { - #[cfg(feature = "gpu")] - { - let surface_texture = - pixels::SurfaceTexture::new(width, height, window); - - if let Ok(pixels) = - pixels::PixelsBuilder::new(width, height, surface_texture) - .texture_format(pixels::wgpu::TextureFormat::Bgra8UnormSrgb) - .build() - { - log::info!("GPU surface created"); - - return Surface::Gpu { pixels }; - } - } - let window = unsafe { softbuffer::GraphicsContext::new(window, window) } .expect("Create softbuffer for window"); - log::info!("CPU surface created"); - - Surface::Cpu { + Surface { window, buffer: vec![0; width as usize * height as usize], } @@ -74,19 +52,7 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - match surface { - Surface::Cpu { buffer, .. } => { - buffer.resize((width * height) as usize, 0); - } - #[cfg(feature = "gpu")] - Surface::Gpu { pixels } => { - pixels - .resize_surface(width, height) - .expect("Resize surface"); - - pixels.resize_buffer(width, height).expect("Resize buffer"); - } - } + surface.buffer.resize((width * height) as usize, 0); } fn fetch_information(&self) -> Information { @@ -140,15 +106,9 @@ pub fn present>( ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); - let buffer = match surface { - Surface::Cpu { buffer, .. } => bytemuck::cast_slice_mut(buffer), - #[cfg(feature = "gpu")] - Surface::Gpu { pixels } => pixels.frame_mut(), - }; - let drawn = backend.draw( &mut tiny_skia::PixmapMut::from_bytes( - buffer, + bytemuck::cast_slice_mut(&mut surface.buffer), physical_size.width, physical_size.height, ) @@ -161,22 +121,12 @@ pub fn present>( ); if drawn { - match surface { - Surface::Cpu { window, buffer } => { - window.set_buffer( - buffer, - physical_size.width as u16, - physical_size.height as u16, - ); - - Ok(()) - } - #[cfg(feature = "gpu")] - Surface::Gpu { pixels } => { - pixels.render().map_err(|_| compositor::SurfaceError::Lost) - } - } - } else { - Ok(()) + surface.window.set_buffer( + &surface.buffer, + physical_size.width as u16, + physical_size.height as u16, + ); } + + Ok(()) } -- cgit From 9c63eb7df559e58b14188b4096e9bd206444bbf3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 26 Apr 2023 16:46:27 +0200 Subject: Update `tiny-skia` and `resvg` --- tiny_skia/src/window/compositor.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 6e4bb6ef..7523e06f 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -7,13 +7,13 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; pub struct Compositor { - clip_mask: tiny_skia::ClipMask, _theme: PhantomData, } pub struct Surface { window: softbuffer::GraphicsContext, buffer: Vec, + clip_mask: tiny_skia::Mask, } impl crate::graphics::Compositor for Compositor { @@ -43,6 +43,8 @@ impl crate::graphics::Compositor for Compositor { Surface { window, buffer: vec![0; width as usize * height as usize], + clip_mask: tiny_skia::Mask::new(width, height) + .expect("Create clip mask"), } } @@ -53,6 +55,8 @@ impl crate::graphics::Compositor for Compositor { height: u32, ) { surface.buffer.resize((width * height) as usize, 0); + surface.clip_mask = + tiny_skia::Mask::new(width, height).expect("Create clip mask"); } fn fetch_information(&self) -> Information { @@ -72,7 +76,6 @@ impl crate::graphics::Compositor for Compositor { ) -> Result<(), SurfaceError> { renderer.with_primitives(|backend, primitives| { present( - self, backend, surface, primitives, @@ -85,18 +88,15 @@ impl crate::graphics::Compositor for Compositor { } pub fn new(settings: Settings) -> (Compositor, Backend) { - // TOD ( Compositor { - clip_mask: tiny_skia::ClipMask::new(), _theme: PhantomData, }, Backend::new(settings), ) } -pub fn present>( - compositor: &mut Compositor, +pub fn present>( backend: &mut Backend, surface: &mut Surface, primitives: &[Primitive], @@ -113,7 +113,7 @@ pub fn present>( physical_size.height, ) .expect("Create pixel map"), - &mut compositor.clip_mask, + &mut surface.clip_mask, primitives, viewport, background_color, -- cgit From af0303f95e27737d9de8915f939b60a2bc3282ae Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 27 Apr 2023 15:10:41 +0200 Subject: Move damage tracking logic to `compositor` in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 54 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 7523e06f..d3dffb18 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,5 +1,6 @@ -use crate::core::Color; +use crate::core::{Color, Rectangle}; use crate::graphics::compositor::{self, Information, SurfaceError}; +use crate::graphics::damage; use crate::graphics::{Error, Primitive, Viewport}; use crate::{Backend, Renderer, Settings}; @@ -14,6 +15,8 @@ pub struct Surface { window: softbuffer::GraphicsContext, buffer: Vec, clip_mask: tiny_skia::Mask, + last_primitives: Vec, + last_background_color: Color, } impl crate::graphics::Compositor for Compositor { @@ -45,6 +48,8 @@ impl crate::graphics::Compositor for Compositor { buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), + last_primitives: Vec::new(), + last_background_color: Color::BLACK, } } @@ -57,6 +62,8 @@ impl crate::graphics::Compositor for Compositor { surface.buffer.resize((width * height) as usize, 0); surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); + + surface.last_primitives.clear(); } fn fetch_information(&self) -> Information { @@ -105,28 +112,45 @@ pub fn present>( overlay: &[T], ) -> Result<(), compositor::SurfaceError> { let physical_size = viewport.physical_size(); + let scale_factor = viewport.scale_factor() as f32; + + let mut pixels = &mut tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut surface.buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); + + let damage = if surface.last_background_color == background_color { + damage::list(&surface.last_primitives, primitives) + } else { + vec![Rectangle::with_size(viewport.logical_size())] + }; + + if damage.is_empty() { + return Ok(()); + } + + surface.last_primitives = primitives.to_vec(); + surface.last_background_color = background_color; + + let damage = damage::group(damage, scale_factor, physical_size); - let drawn = backend.draw( - &mut tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), - physical_size.width, - physical_size.height, - ) - .expect("Create pixel map"), + backend.draw( + &mut pixels, &mut surface.clip_mask, primitives, viewport, + &damage, background_color, overlay, ); - if drawn { - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); - } + surface.window.set_buffer( + &surface.buffer, + physical_size.width as u16, + physical_size.height as u16, + ); Ok(()) } -- cgit From 92d808ee73b261b639a4a8d1d4f930cd61a380c6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 27 Apr 2023 15:16:05 +0200 Subject: Fix double reference in `compositor` in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index d3dffb18..1bcce6fe 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -114,7 +114,7 @@ pub fn present>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - let mut pixels = &mut tiny_skia::PixmapMut::from_bytes( + let mut pixels = tiny_skia::PixmapMut::from_bytes( bytemuck::cast_slice_mut(&mut surface.buffer), physical_size.width, physical_size.height, -- cgit From eb1b2bf24174759bba8c63db0ec89c7c6d15d191 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 27 Apr 2023 15:45:02 +0200 Subject: Invalidate `last_primitives` on resize in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 1bcce6fe..3bc06970 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -15,7 +15,7 @@ pub struct Surface { window: softbuffer::GraphicsContext, buffer: Vec, clip_mask: tiny_skia::Mask, - last_primitives: Vec, + last_primitives: Option>, last_background_color: Color, } @@ -48,7 +48,7 @@ impl crate::graphics::Compositor for Compositor { buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - last_primitives: Vec::new(), + last_primitives: None, last_background_color: Color::BLACK, } } @@ -62,8 +62,7 @@ impl crate::graphics::Compositor for Compositor { surface.buffer.resize((width * height) as usize, 0); surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - - surface.last_primitives.clear(); + surface.last_primitives = None; } fn fetch_information(&self) -> Information { @@ -121,17 +120,20 @@ pub fn present>( ) .expect("Create pixel map"); - let damage = if surface.last_background_color == background_color { - damage::list(&surface.last_primitives, primitives) - } else { - vec![Rectangle::with_size(viewport.logical_size())] - }; + let damage = surface + .last_primitives + .as_deref() + .and_then(|last_primitives| { + (surface.last_background_color == background_color) + .then(|| damage::list(last_primitives, primitives)) + }) + .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); if damage.is_empty() { return Ok(()); } - surface.last_primitives = primitives.to_vec(); + surface.last_primitives = Some(primitives.to_vec()); surface.last_background_color = background_color; let damage = damage::group(damage, scale_factor, physical_size); -- cgit From a755472ee35dfb7839f989becafc6028921a3b99 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 27 Apr 2023 15:51:51 +0200 Subject: Remove unnecessary `last_` prefix in `Surface` of `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 3bc06970..9999a188 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -15,8 +15,8 @@ pub struct Surface { window: softbuffer::GraphicsContext, buffer: Vec, clip_mask: tiny_skia::Mask, - last_primitives: Option>, - last_background_color: Color, + primitives: Option>, + background_color: Color, } impl crate::graphics::Compositor for Compositor { @@ -48,8 +48,8 @@ impl crate::graphics::Compositor for Compositor { buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - last_primitives: None, - last_background_color: Color::BLACK, + primitives: None, + background_color: Color::BLACK, } } @@ -62,7 +62,7 @@ impl crate::graphics::Compositor for Compositor { surface.buffer.resize((width * height) as usize, 0); surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.last_primitives = None; + surface.primitives = None; } fn fetch_information(&self) -> Information { @@ -121,10 +121,10 @@ pub fn present>( .expect("Create pixel map"); let damage = surface - .last_primitives + .primitives .as_deref() .and_then(|last_primitives| { - (surface.last_background_color == background_color) + (surface.background_color == background_color) .then(|| damage::list(last_primitives, primitives)) }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); @@ -133,8 +133,8 @@ pub fn present>( return Ok(()); } - surface.last_primitives = Some(primitives.to_vec()); - surface.last_background_color = background_color; + surface.primitives = Some(primitives.to_vec()); + surface.background_color = background_color; let damage = damage::group(damage, scale_factor, physical_size); -- cgit From 233196eb14b40f8bd5201ea0262571f82136ad53 Mon Sep 17 00:00:00 2001 From: Bingus Date: Sat, 25 Mar 2023 10:45:39 -0700 Subject: Added offscreen rendering support for wgpu & tiny-skia exposed with the window::screenshot command. --- tiny_skia/src/window/compositor.rs | 76 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 9999a188..f3be3f16 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,5 +1,5 @@ -use crate::core::{Color, Rectangle}; -use crate::graphics::compositor::{self, Information, SurfaceError}; +use crate::core::{Color, Rectangle, Size}; +use crate::graphics::compositor::{self, Information}; use crate::graphics::damage; use crate::graphics::{Error, Primitive, Viewport}; use crate::{Backend, Renderer, Settings}; @@ -79,7 +79,7 @@ impl crate::graphics::Compositor for Compositor { viewport: &Viewport, background_color: Color, overlay: &[T], - ) -> Result<(), SurfaceError> { + ) -> Result<(), compositor::SurfaceError> { renderer.with_primitives(|backend, primitives| { present( backend, @@ -91,6 +91,26 @@ impl crate::graphics::Compositor for Compositor { ) }) } + + fn screenshot>( + &mut self, + renderer: &mut Self::Renderer, + surface: &mut Self::Surface, + viewport: &Viewport, + background_color: Color, + overlay: &[T], + ) -> Vec { + renderer.with_primitives(|backend, primitives| { + screenshot( + surface, + backend, + primitives, + viewport, + background_color, + overlay, + ) + }) + } } pub fn new(settings: Settings) -> (Compositor, Backend) { @@ -156,3 +176,53 @@ pub fn present>( Ok(()) } + +pub fn screenshot>( + surface: &mut Surface, + backend: &mut Backend, + primitives: &[Primitive], + viewport: &Viewport, + background_color: Color, + overlay: &[T], +) -> Vec { + let size = viewport.physical_size(); + + let mut offscreen_buffer: Vec = + vec![0; size.width as usize * size.height as usize]; + + backend.draw( + &mut tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut offscreen_buffer), + size.width, + size.height, + ) + .expect("Create offscreen pixel map"), + &mut surface.clip_mask, + primitives, + viewport, + &[Rectangle::with_size(Size::new( + size.width as f32, + size.height as f32, + ))], + background_color, + overlay, + ); + + offscreen_buffer.iter().fold( + Vec::with_capacity(offscreen_buffer.len() * 4), + |mut acc, pixel| { + const A_MASK: u32 = 0xFF_00_00_00; + const R_MASK: u32 = 0x00_FF_00_00; + const G_MASK: u32 = 0x00_00_FF_00; + const B_MASK: u32 = 0x00_00_00_FF; + + let a = ((A_MASK & pixel) >> 24) as u8; + let r = ((R_MASK & pixel) >> 16) as u8; + let g = ((G_MASK & pixel) >> 8) as u8; + let b = (B_MASK & pixel) as u8; + + acc.extend([r, g, b, a]); + acc + }, + ) +} -- cgit From 0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 22 Jun 2023 00:38:36 +0200 Subject: Introduce custom backend-specific primitives --- tiny_skia/src/window/compositor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src/window/compositor.rs') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index f3be3f16..775cf9e5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,8 +1,8 @@ use crate::core::{Color, Rectangle, Size}; use crate::graphics::compositor::{self, Information}; use crate::graphics::damage; -use crate::graphics::{Error, Primitive, Viewport}; -use crate::{Backend, Renderer, Settings}; +use crate::graphics::{Error, Viewport}; +use crate::{Backend, Primitive, Renderer, Settings}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; -- cgit