diff options
| author | 2023-07-12 12:23:18 -0700 | |
|---|---|---|
| committer | 2023-07-12 12:23:18 -0700 | |
| commit | 633f405f3f78bc7f82d2b2061491b0e011137451 (patch) | |
| tree | 5ebfc1f45d216a5c14a90492563599e6969eab4d /renderer/src/geometry/cache.rs | |
| parent | 41836dd80d0534608e7aedfbf2319c540a23de1a (diff) | |
| parent | 21bd51426d900e271206f314e0c915dd41065521 (diff) | |
| download | iced-633f405f3f78bc7f82d2b2061491b0e011137451.tar.gz iced-633f405f3f78bc7f82d2b2061491b0e011137451.tar.bz2 iced-633f405f3f78bc7f82d2b2061491b0e011137451.zip | |
Merge remote-tracking branch 'origin/master' into feat/multi-window-support
# Conflicts:
#	Cargo.toml
#	core/src/window/icon.rs
#	core/src/window/id.rs
#	core/src/window/position.rs
#	core/src/window/settings.rs
#	examples/integration/src/main.rs
#	examples/integration_opengl/src/main.rs
#	glutin/src/application.rs
#	native/src/subscription.rs
#	native/src/window.rs
#	runtime/src/window/action.rs
#	src/lib.rs
#	src/window.rs
#	winit/Cargo.toml
#	winit/src/application.rs
#	winit/src/icon.rs
#	winit/src/settings.rs
#	winit/src/window.rs
Diffstat (limited to 'renderer/src/geometry/cache.rs')
| -rw-r--r-- | renderer/src/geometry/cache.rs | 125 | 
1 files changed, 125 insertions, 0 deletions
| diff --git a/renderer/src/geometry/cache.rs b/renderer/src/geometry/cache.rs new file mode 100644 index 00000000..d82e7f69 --- /dev/null +++ b/renderer/src/geometry/cache.rs @@ -0,0 +1,125 @@ +use crate::core::Size; +use crate::geometry::{Frame, Geometry}; +use crate::Renderer; + +use std::cell::RefCell; +use std::sync::Arc; + +/// A simple cache that stores generated [`Geometry`] to avoid recomputation. +/// +/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer +/// change or it is explicitly cleared. +#[derive(Debug, Default)] +pub struct Cache { +    state: RefCell<State>, +} + +#[derive(Debug, Default)] +enum State { +    #[default] +    Empty, +    Filled { +        bounds: Size, +        primitive: Internal, +    }, +} + +#[derive(Debug, Clone)] +enum Internal { +    TinySkia(Arc<iced_tiny_skia::Primitive>), +    #[cfg(feature = "wgpu")] +    Wgpu(Arc<iced_wgpu::Primitive>), +} + +impl Cache { +    /// Creates a new empty [`Cache`]. +    pub fn new() -> Self { +        Cache { +            state: Default::default(), +        } +    } + +    /// Clears the [`Cache`], forcing a redraw the next time it is used. +    pub fn clear(&self) { +        *self.state.borrow_mut() = State::Empty; +    } + +    /// Draws [`Geometry`] using the provided closure and stores it in the +    /// [`Cache`]. +    /// +    /// The closure will only be called when +    /// - the bounds have changed since the previous draw call. +    /// - the [`Cache`] is empty or has been explicitly cleared. +    /// +    /// Otherwise, the previously stored [`Geometry`] will be returned. The +    /// [`Cache`] is not cleared in this case. In other words, it will keep +    /// returning the stored [`Geometry`] if needed. +    pub fn draw<Theme>( +        &self, +        renderer: &Renderer<Theme>, +        bounds: Size, +        draw_fn: impl FnOnce(&mut Frame), +    ) -> Geometry { +        use std::ops::Deref; + +        if let State::Filled { +            bounds: cached_bounds, +            primitive, +        } = self.state.borrow().deref() +        { +            if *cached_bounds == bounds { +                match primitive { +                    Internal::TinySkia(primitive) => { +                        return Geometry::TinySkia( +                            iced_tiny_skia::Primitive::Cache { +                                content: primitive.clone(), +                            }, +                        ); +                    } +                    #[cfg(feature = "wgpu")] +                    Internal::Wgpu(primitive) => { +                        return Geometry::Wgpu(iced_wgpu::Primitive::Cache { +                            content: primitive.clone(), +                        }); +                    } +                } +            } +        } + +        let mut frame = Frame::new(renderer, bounds); +        draw_fn(&mut frame); + +        let primitive = { +            let geometry = frame.into_geometry(); + +            match geometry { +                Geometry::TinySkia(primitive) => { +                    Internal::TinySkia(Arc::new(primitive)) +                } +                #[cfg(feature = "wgpu")] +                Geometry::Wgpu(primitive) => { +                    Internal::Wgpu(Arc::new(primitive)) +                } +            } +        }; + +        *self.state.borrow_mut() = State::Filled { +            bounds, +            primitive: primitive.clone(), +        }; + +        match primitive { +            Internal::TinySkia(primitive) => { +                Geometry::TinySkia(iced_tiny_skia::Primitive::Cache { +                    content: primitive, +                }) +            } +            #[cfg(feature = "wgpu")] +            Internal::Wgpu(primitive) => { +                Geometry::Wgpu(iced_wgpu::Primitive::Cache { +                    content: primitive, +                }) +            } +        } +    } +} | 
