summaryrefslogtreecommitdiffstats
path: root/renderer/src/geometry/cache.rs
diff options
context:
space:
mode:
authorLibravatar Bingus <shankern@protonmail.com>2023-07-12 12:23:18 -0700
committerLibravatar Bingus <shankern@protonmail.com>2023-07-12 12:23:18 -0700
commit633f405f3f78bc7f82d2b2061491b0e011137451 (patch)
tree5ebfc1f45d216a5c14a90492563599e6969eab4d /renderer/src/geometry/cache.rs
parent41836dd80d0534608e7aedfbf2319c540a23de1a (diff)
parent21bd51426d900e271206f314e0c915dd41065521 (diff)
downloadiced-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.rs125
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,
+ })
+ }
+ }
+ }
+}