diff options
author | 2019-12-04 04:28:07 +0100 | |
---|---|---|
committer | 2019-12-04 04:28:07 +0100 | |
commit | d1eb187e2673150b6c3f9fed0c15a1804ce0d75b (patch) | |
tree | 18ba66323f0aa2f3b8c25b80d1d74acfa41c13a2 /wgpu | |
parent | 6c145bbb239e87569bf4aa797ea7f8d34e25cf62 (diff) | |
parent | 2144109dd7f9ab811393d3d725ba1cb7371aa672 (diff) | |
download | iced-d1eb187e2673150b6c3f9fed0c15a1804ce0d75b.tar.gz iced-d1eb187e2673150b6c3f9fed0c15a1804ce0d75b.tar.bz2 iced-d1eb187e2673150b6c3f9fed0c15a1804ce0d75b.zip |
Merge pull request #90 from hecrj/feature/image-from-bytes
Load images from memory and image viewer example
Diffstat (limited to '')
-rw-r--r-- | wgpu/src/image.rs | 102 | ||||
-rw-r--r-- | wgpu/src/primitive.rs | 6 | ||||
-rw-r--r-- | wgpu/src/renderer.rs | 5 | ||||
-rw-r--r-- | wgpu/src/renderer/widget/image.rs | 12 |
4 files changed, 97 insertions, 28 deletions
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs index 40d9c318..7e4e2670 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -1,11 +1,19 @@ use crate::Transformation; -use iced_native::Rectangle; - -use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; +use iced_native::{ + image::{Data, Handle}, + Rectangle, +}; + +use std::{ + cell::RefCell, + collections::{HashMap, HashSet}, + mem, + rc::Rc, +}; #[derive(Debug)] pub struct Pipeline { - cache: RefCell<HashMap<String, Memory>>, + cache: RefCell<Cache>, pipeline: wgpu::RenderPipeline, uniforms: wgpu::Buffer, @@ -185,7 +193,7 @@ impl Pipeline { }); Pipeline { - cache: RefCell::new(HashMap::new()), + cache: RefCell::new(Cache::new()), pipeline, uniforms: uniforms_buffer, @@ -197,23 +205,36 @@ impl Pipeline { } } - pub fn dimensions(&self, path: &str) -> (u32, u32) { - self.load(path); + pub fn dimensions(&self, handle: &Handle) -> (u32, u32) { + self.load(handle); - self.cache.borrow().get(path).unwrap().dimensions() + self.cache.borrow_mut().get(handle).unwrap().dimensions() } - fn load(&self, path: &str) { - if !self.cache.borrow().contains_key(path) { - let memory = if let Ok(image) = image::open(path) { - Memory::Host { - image: image.to_bgra(), + fn load(&self, handle: &Handle) { + if !self.cache.borrow().contains(&handle) { + let memory = match handle.data() { + Data::Path(path) => { + if let Ok(image) = image::open(path) { + Memory::Host { + image: image.to_bgra(), + } + } else { + Memory::NotFound + } + } + Data::Bytes(bytes) => { + if let Ok(image) = image::load_from_memory(&bytes) { + Memory::Host { + image: image.to_bgra(), + } + } else { + Memory::Invalid + } } - } else { - Memory::NotFound }; - let _ = self.cache.borrow_mut().insert(path.to_string(), memory); + let _ = self.cache.borrow_mut().insert(&handle, memory); } } @@ -245,12 +266,12 @@ impl Pipeline { // // [1]: https://github.com/nical/guillotiere for image in instances { - self.load(&image.path); + self.load(&image.handle); if let Some(texture) = self .cache .borrow_mut() - .get_mut(&image.path) + .get(&image.handle) .unwrap() .upload(device, encoder, &self.texture_layout) { @@ -314,6 +335,10 @@ impl Pipeline { } } } + + pub fn trim_cache(&mut self) { + self.cache.borrow_mut().trim(); + } } #[derive(Debug)] @@ -327,6 +352,7 @@ enum Memory { height: u32, }, NotFound, + Invalid, } impl Memory { @@ -335,6 +361,7 @@ impl Memory { Memory::Host { image } => image.dimensions(), Memory::Device { width, height, .. } => (*width, *height), Memory::NotFound => (1, 1), + Memory::Invalid => (1, 1), } } @@ -417,12 +444,49 @@ impl Memory { } Memory::Device { bind_group, .. } => Some(bind_group.clone()), Memory::NotFound => None, + Memory::Invalid => None, + } + } +} + +#[derive(Debug)] +struct Cache { + map: HashMap<u64, Memory>, + hits: HashSet<u64>, +} + +impl Cache { + fn new() -> Self { + Self { + map: HashMap::new(), + hits: HashSet::new(), } } + + fn contains(&self, handle: &Handle) -> bool { + self.map.contains_key(&handle.id()) + } + + fn get(&mut self, handle: &Handle) -> Option<&mut Memory> { + let _ = self.hits.insert(handle.id()); + + self.map.get_mut(&handle.id()) + } + + fn insert(&mut self, handle: &Handle, memory: Memory) { + let _ = self.map.insert(handle.id(), memory); + } + + fn trim(&mut self) { + let hits = &self.hits; + + self.map.retain(|k, _| hits.contains(k)); + self.hits.clear(); + } } pub struct Image { - pub path: String, + pub handle: Handle, pub position: [f32; 2], pub scale: [f32; 2], } diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 9efd74f6..04264e5d 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,5 +1,5 @@ use iced_native::{ - Background, Color, Font, HorizontalAlignment, Rectangle, Vector, + image, Background, Color, Font, HorizontalAlignment, Rectangle, Vector, VerticalAlignment, }; @@ -41,8 +41,8 @@ pub enum Primitive { }, /// An image primitive Image { - /// The path of the image - path: String, + /// The handle of the image + handle: image::Handle, /// The bounds of the image bounds: Rectangle, }, diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 268a3630..fa52bd96 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -127,6 +127,7 @@ impl Renderer { } self.queue.submit(&[encoder.finish()]); + self.image_pipeline.trim_cache(); *mouse_cursor } @@ -229,9 +230,9 @@ impl Renderer { border_radius: *border_radius as f32, }); } - Primitive::Image { path, bounds } => { + Primitive::Image { handle, bounds } => { layer.images.push(Image { - path: path.clone(), + handle: handle.clone(), position: [bounds.x, bounds.y], scale: [bounds.width, bounds.height], }); diff --git a/wgpu/src/renderer/widget/image.rs b/wgpu/src/renderer/widget/image.rs index 0006dde1..70dc5d97 100644 --- a/wgpu/src/renderer/widget/image.rs +++ b/wgpu/src/renderer/widget/image.rs @@ -2,14 +2,18 @@ use crate::{Primitive, Renderer}; use iced_native::{image, Layout, MouseCursor}; impl image::Renderer for Renderer { - fn dimensions(&self, path: &str) -> (u32, u32) { - self.image_pipeline.dimensions(path) + fn dimensions(&self, handle: &image::Handle) -> (u32, u32) { + self.image_pipeline.dimensions(handle) } - fn draw(&mut self, path: &str, layout: Layout<'_>) -> Self::Output { + fn draw( + &mut self, + handle: image::Handle, + layout: Layout<'_>, + ) -> Self::Output { ( Primitive::Image { - path: String::from(path), + handle, bounds: layout.bounds(), }, MouseCursor::OutOfBounds, |