diff options
Diffstat (limited to 'tiny_skia')
-rw-r--r-- | tiny_skia/Cargo.toml | 1 | ||||
-rw-r--r-- | tiny_skia/src/window/compositor.rs | 113 |
2 files changed, 74 insertions, 40 deletions
diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml index df4c6143..68b2a03a 100644 --- a/tiny_skia/Cargo.toml +++ b/tiny_skia/Cargo.toml @@ -22,7 +22,6 @@ bytemuck.workspace = true cosmic-text.workspace = true kurbo.workspace = true log.workspace = true -raw-window-handle.workspace = true rustc-hash.workspace = true softbuffer.workspace = true tiny-skia.workspace = true diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 87ded746..781ed8a5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,20 +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> { @@ -25,11 +30,11 @@ 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>, + compatible_window: W, ) -> Result<Self, Error> { - Ok(new(settings)) + Ok(new(settings, compatible_window)) } fn create_renderer(&self) -> Self::Renderer { @@ -40,37 +45,49 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { ) } - 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,8 +138,16 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { } } -pub fn new<Theme>(settings: Settings) -> Compositor<Theme> { +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, } @@ -139,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)) @@ -159,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, @@ -174,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>>( |