diff options
author | 2024-01-19 20:41:52 +0100 | |
---|---|---|
committer | 2024-01-19 20:41:52 +0100 | |
commit | 1781068e1c3a65551db1e832fdbaddba99124051 (patch) | |
tree | 60e0b3854cc0541712572fbb0e56f14435951ea9 /tiny_skia/src/window/compositor.rs | |
parent | 41dec5bd203ff5b1574a33a17d5f7358ae1beea2 (diff) | |
parent | 7ae7fcb89855002519bab752fd3686106ce448db (diff) | |
download | iced-1781068e1c3a65551db1e832fdbaddba99124051.tar.gz iced-1781068e1c3a65551db1e832fdbaddba99124051.tar.bz2 iced-1781068e1c3a65551db1e832fdbaddba99124051.zip |
Merge branch 'master' into remove-vertex-indexing
Diffstat (limited to 'tiny_skia/src/window/compositor.rs')
-rw-r--r-- | tiny_skia/src/window/compositor.rs | 141 |
1 files changed, 87 insertions, 54 deletions
diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 828e522f..781ed8a5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,19 +4,25 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use std::collections::VecDeque; use std::marker::PhantomData; +use std::num::NonZeroU32; pub struct Compositor<Theme> { + context: softbuffer::Context<Box<dyn compositor::Window>>, + settings: Settings, _theme: PhantomData<Theme>, } pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec<u32>, + window: softbuffer::Surface< + Box<dyn compositor::Window>, + Box<dyn compositor::Window>, + >, clip_mask: tiny_skia::Mask, - primitives: Option<Vec<Primitive>>, + primitive_stack: VecDeque<Vec<Primitive>>, background_color: Color, + max_age: u8, } impl<Theme> crate::graphics::Compositor for Compositor<Theme> { @@ -24,53 +30,64 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { type Renderer = Renderer<Theme>; type Surface = Surface; - fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn new<W: compositor::Window>( settings: Self::Settings, - _compatible_window: Option<&W>, - ) -> Result<(Self, Self::Renderer), Error> { - let (compositor, backend) = new(); + compatible_window: W, + ) -> Result<Self, Error> { + Ok(new(settings, compatible_window)) + } - Ok(( - compositor, - Renderer::new( - backend, - settings.default_font, - settings.default_text_size, - ), - )) + fn create_renderer(&self) -> Self::Renderer { + Renderer::new( + Backend::new(), + self.settings.default_font, + self.settings.default_text_size, + ) } - fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn create_surface<W: compositor::Window + Clone>( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> Surface { - #[allow(unsafe_code)] - let window = - unsafe { softbuffer::GraphicsContext::new(window, window) } - .expect("Create softbuffer for window"); + ) -> Self::Surface { + let window = softbuffer::Surface::new( + &self.context, + Box::new(window.clone()) as _, + ) + .expect("Create softbuffer surface for window"); - Surface { + let mut surface = Surface { window, - buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - primitives: None, + primitive_stack: VecDeque::new(), background_color: Color::BLACK, - } + max_age: 0, + }; + + self.configure_surface(&mut surface, width, height); + + surface } fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Self::Surface, width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); + surface + .window + .resize( + NonZeroU32::new(width).expect("Non-zero width"), + NonZeroU32::new(height).expect("Non-zero height"), + ) + .expect("Resize surface"); + surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives = None; + surface.primitive_stack.clear(); } fn fetch_information(&self) -> Information { @@ -121,13 +138,19 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { } } -pub fn new<Theme>() -> (Compositor<Theme>, Backend) { - ( - Compositor { - _theme: PhantomData, - }, - Backend::new(), - ) +pub fn new<W: compositor::Window, Theme>( + settings: Settings, + compatible_window: W, +) -> Compositor<Theme> { + #[allow(unsafe_code)] + let context = softbuffer::Context::new(Box::new(compatible_window) as _) + .expect("Create softbuffer context"); + + Compositor { + context, + settings, + _theme: PhantomData, + } } pub fn present<T: AsRef<str>>( @@ -141,16 +164,25 @@ pub fn present<T: AsRef<str>>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - let mut pixels = tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), - physical_size.width, - physical_size.height, - ) - .expect("Create pixel map"); + let mut buffer = surface + .window + .buffer_mut() + .map_err(|_| compositor::SurfaceError::Lost)?; + + let last_primitives = { + let age = buffer.age(); - let damage = surface - .primitives - .as_deref() + surface.max_age = surface.max_age.max(age); + surface.primitive_stack.truncate(surface.max_age as usize); + + if age > 0 { + surface.primitive_stack.get(age as usize - 1) + } else { + None + } + }; + + let damage = last_primitives .and_then(|last_primitives| { (surface.background_color == background_color) .then(|| damage::list(last_primitives, primitives)) @@ -161,11 +193,18 @@ pub fn present<T: AsRef<str>>( return Ok(()); } - surface.primitives = Some(primitives.to_vec()); + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; let damage = damage::group(damage, scale_factor, physical_size); + let mut pixels = tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); + backend.draw( &mut pixels, &mut surface.clip_mask, @@ -176,13 +215,7 @@ pub fn present<T: AsRef<str>>( overlay, ); - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); - - Ok(()) + buffer.present().map_err(|_| compositor::SurfaceError::Lost) } pub fn screenshot<T: AsRef<str>>( |