diff options
| author | 2024-01-09 12:25:53 -0800 | |
|---|---|---|
| committer | 2024-01-17 07:46:33 -0800 | |
| commit | ff268c8c4268d930fc337636302175d44e201448 (patch) | |
| tree | 04b416d04a7341593d8ae552a7b651a345704996 /tiny_skia | |
| parent | 070abff5cee7fd351185a7cbc38a54e1d5f0db70 (diff) | |
| download | iced-ff268c8c4268d930fc337636302175d44e201448.tar.gz iced-ff268c8c4268d930fc337636302175d44e201448.tar.bz2 iced-ff268c8c4268d930fc337636302175d44e201448.zip | |
Update to `softbuffer` 0.3, tracking up to `age` sets of primitives
Diffstat (limited to '')
| -rw-r--r-- | tiny_skia/src/window/compositor.rs | 121 | 
1 files changed, 77 insertions, 44 deletions
| diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 87ded746..d99b85d4 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -5,18 +5,21 @@ 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: Option<softbuffer::Context>,      settings: Settings,      _theme: PhantomData<Theme>,  }  pub struct Surface { -    window: softbuffer::GraphicsContext, -    buffer: Vec<u32>, +    window: softbuffer::Surface,      clip_mask: tiny_skia::Mask, -    primitives: Option<Vec<Primitive>>, +    // Primitives of existing buffers, by decreasing age +    primitives: VecDeque<Vec<Primitive>>,      background_color: Color,  } @@ -27,9 +30,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {      fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(          settings: Self::Settings, -        _compatible_window: Option<&W>, +        compatible_window: Option<&W>,      ) -> Result<Self, Error> { -        Ok(new(settings)) +        Ok(new(settings, compatible_window))      }      fn create_renderer(&self) -> Self::Renderer { @@ -47,16 +50,21 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {          height: u32,      ) -> Surface {          #[allow(unsafe_code)] -        let window = -            unsafe { softbuffer::GraphicsContext::new(window, window) } -                .expect("Create softbuffer for window"); +        let window = if let Some(context) = self.context.as_ref() { +            unsafe { softbuffer::Surface::new(context, window) } +                .expect("Create softbuffer surface for window") +        } else { +            let context = unsafe { softbuffer::Context::new(window) } +                .expect("Create softbuffer context for window"); +            unsafe { softbuffer::Surface::new(&context, window) } +                .expect("Create softbuffer surface for window") +        };          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, +            primitives: VecDeque::new(),              background_color: Color::BLACK,          }      } @@ -67,10 +75,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {          width: u32,          height: u32,      ) { -        surface.buffer.resize((width * height) as usize, 0);          surface.clip_mask =              tiny_skia::Mask::new(width, height).expect("Create clip mask"); -        surface.primitives = None; +        surface.primitives.clear();      }      fn fetch_information(&self) -> Information { @@ -121,8 +128,15 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {      }  } -pub fn new<Theme>(settings: Settings) -> Compositor<Theme> { +pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>( +    settings: Settings, +    compatible_window: Option<&W>, +) -> Compositor<Theme> { +    #[allow(unsafe_code)] +    let context = compatible_window +        .and_then(|w| unsafe { softbuffer::Context::new(w) }.ok());      Compositor { +        context,          settings,          _theme: PhantomData,      } @@ -139,48 +153,67 @@ 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"); +    surface +        .window +        .resize( +            NonZeroU32::new(physical_size.width).unwrap(), +            NonZeroU32::new(physical_size.height).unwrap(), +        ) +        .unwrap(); + +    // TODO Add variants to `SurfaceError`? +    let mut buffer = surface +        .window +        .buffer_mut() +        .map_err(|_| compositor::SurfaceError::Lost)?; + +    let age = buffer.age(); -    let damage = surface -        .primitives -        .as_deref() +    // Forget primatives for back buffers older than `age` +    // Or if this is a new buffer, keep at most two. +    let max = if age == 0 { 2 } else { age }; +    while surface.primitives.len() as u8 > max { +        let _ = surface.primitives.pop_front(); +    } + +    let last_primitives = if surface.primitives.len() as u8 == age { +        surface.primitives.pop_front() +    } else { +        None +    }; + +    let damage = last_primitives          .and_then(|last_primitives| {              (surface.background_color == background_color) -                .then(|| damage::list(last_primitives, primitives)) +                .then(|| damage::list(&last_primitives, primitives))          })          .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); -    if damage.is_empty() { -        return Ok(()); -    } - -    surface.primitives = Some(primitives.to_vec()); +    surface.primitives.push_back(primitives.to_vec());      surface.background_color = background_color; -    let damage = damage::group(damage, scale_factor, physical_size); +    if !damage.is_empty() { +        let damage = damage::group(damage, scale_factor, physical_size); -    backend.draw( -        &mut pixels, -        &mut surface.clip_mask, -        primitives, -        viewport, -        &damage, -        background_color, -        overlay, -    ); +        let mut pixels = tiny_skia::PixmapMut::from_bytes( +            bytemuck::cast_slice_mut(&mut buffer), +            physical_size.width, +            physical_size.height, +        ) +        .expect("Create pixel map"); -    surface.window.set_buffer( -        &surface.buffer, -        physical_size.width as u16, -        physical_size.height as u16, -    ); +        backend.draw( +            &mut pixels, +            &mut surface.clip_mask, +            primitives, +            viewport, +            &damage, +            background_color, +            overlay, +        ); +    } -    Ok(()) +    buffer.present().map_err(|_| compositor::SurfaceError::Lost)  }  pub fn screenshot<T: AsRef<str>>( | 
