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 | |
| 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')
| -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>>(  | 
