diff options
author | 2023-04-27 15:10:41 +0200 | |
---|---|---|
committer | 2023-04-27 15:10:41 +0200 | |
commit | af0303f95e27737d9de8915f939b60a2bc3282ae (patch) | |
tree | e0eb6d5a5a5cc1cedf057cf4ce83932eeb3c9d32 /tiny_skia | |
parent | d953d12c38ad368110f4f9f40fb0f185c11dec54 (diff) | |
download | iced-af0303f95e27737d9de8915f939b60a2bc3282ae.tar.gz iced-af0303f95e27737d9de8915f939b60a2bc3282ae.tar.bz2 iced-af0303f95e27737d9de8915f939b60a2bc3282ae.zip |
Move damage tracking logic to `compositor` in `iced_tiny_skia`
Diffstat (limited to 'tiny_skia')
-rw-r--r-- | tiny_skia/src/backend.rs | 80 | ||||
-rw-r--r-- | tiny_skia/src/window/compositor.rs | 54 |
2 files changed, 42 insertions, 92 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 16a7f9b8..9c69e1d2 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -16,10 +16,6 @@ pub struct Backend { #[cfg(feature = "svg")] vector_pipeline: crate::vector::Pipeline, - - last_primitives: Vec<Primitive>, - last_background_color: Color, - last_size: Size<u32>, } impl Backend { @@ -34,10 +30,6 @@ impl Backend { #[cfg(feature = "svg")] vector_pipeline: crate::vector::Pipeline::new(), - - last_primitives: Vec::new(), - last_background_color: Color::BLACK, - last_size: Size::new(0, 0), } } @@ -47,31 +39,13 @@ impl Backend { clip_mask: &mut tiny_skia::Mask, primitives: &[Primitive], viewport: &Viewport, + damage: &[Rectangle], background_color: Color, overlay: &[T], - ) -> bool { + ) { let physical_size = viewport.physical_size(); - - let damage = if self.last_background_color == background_color - && self.last_size == physical_size - { - Primitive::damage_list(&self.last_primitives, primitives) - } else { - vec![Rectangle::with_size(viewport.logical_size())] - }; - - if damage.is_empty() { - return false; - } - - self.last_primitives = primitives.to_vec(); - self.last_background_color = background_color; - self.last_size = physical_size; - let scale_factor = viewport.scale_factor() as f32; - let damage = group_damage(damage, scale_factor, physical_size); - if !overlay.is_empty() { let path = tiny_skia::PathBuilder::from_rect( tiny_skia::Rect::from_xywh( @@ -99,7 +73,7 @@ impl Backend { ); } - for region in damage { + for ®ion in damage { let path = tiny_skia::PathBuilder::from_rect( tiny_skia::Rect::from_xywh( region.x, @@ -164,8 +138,6 @@ impl Backend { #[cfg(feature = "svg")] self.vector_pipeline.trim_cache(); - - true } fn draw_primitive( @@ -629,52 +601,6 @@ fn adjust_clip_mask(clip_mask: &mut tiny_skia::Mask, bounds: Rectangle) { ); } -fn group_damage( - mut damage: Vec<Rectangle>, - scale_factor: f32, - bounds: Size<u32>, -) -> Vec<Rectangle> { - use std::cmp::Ordering; - - const AREA_THRESHOLD: f32 = 20_000.0; - - let bounds = Rectangle { - x: 0.0, - y: 0.0, - width: bounds.width as f32, - height: bounds.height as f32, - }; - - damage.sort_by(|a, b| { - a.x.partial_cmp(&b.x) - .unwrap_or(Ordering::Equal) - .then_with(|| a.y.partial_cmp(&b.y).unwrap_or(Ordering::Equal)) - }); - - let mut output = Vec::new(); - let mut scaled = damage - .into_iter() - .filter_map(|region| (region * scale_factor).intersection(&bounds)) - .filter(|region| region.width >= 1.0 && region.height >= 1.0); - - if let Some(mut current) = scaled.next() { - for region in scaled { - let union = current.union(®ion); - - if union.area() - current.area() - region.area() <= AREA_THRESHOLD { - current = union; - } else { - output.push(current); - current = region; - } - } - - output.push(current); - } - - output -} - impl iced_graphics::Backend for Backend { fn trim_measurements(&mut self) { self.text_pipeline.trim_measurement_cache(); 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<u32>, clip_mask: tiny_skia::Mask, + last_primitives: Vec<Primitive>, + last_background_color: Color, } impl<Theme> crate::graphics::Compositor for Compositor<Theme> { @@ -45,6 +48,8 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { 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<Theme> crate::graphics::Compositor for Compositor<Theme> { 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<T: AsRef<str>>( 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(()) } |