Draft multi-threaded image rendering in iced_wgpu

This commit is contained in:
Héctor Ramón Jiménez 2025-10-24 17:23:40 +02:00
parent 92888a3639
commit cb8d2710da
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
22 changed files with 886 additions and 305 deletions

View file

@ -18,7 +18,7 @@ use iced::{
Subscription, Task, Theme, color,
};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
fn main() -> iced::Result {
iced::application::timed(
@ -35,6 +35,8 @@ fn main() -> iced::Result {
struct Gallery {
images: Vec<Image>,
previews: HashMap<Id, Preview>,
visible: HashSet<Id>,
downloaded: HashSet<Id>,
viewer: Viewer,
now: Instant,
}
@ -43,6 +45,7 @@ struct Gallery {
enum Message {
ImagesListed(Result<Vec<Image>, Error>),
ImagePoppedIn(Id),
ImagePoppedOut(Id),
ImageDownloaded(Result<Rgba, Error>),
ThumbnailDownloaded(Id, Result<Rgba, Error>),
ThumbnailHovered(Id, bool),
@ -58,6 +61,8 @@ impl Gallery {
Self {
images: Vec::new(),
previews: HashMap::new(),
visible: HashSet::new(),
downloaded: HashSet::new(),
viewer: Viewer::new(),
now: Instant::now(),
},
@ -102,6 +107,14 @@ impl Gallery {
return Task::none();
};
let _ = self.visible.insert(id);
if self.downloaded.contains(&id) {
return Task::none();
}
let _ = self.downloaded.insert(id);
Task::sip(
image.download(Size::Thumbnail {
width: Preview::WIDTH,
@ -111,6 +124,11 @@ impl Gallery {
Message::ThumbnailDownloaded.with(id),
)
}
Message::ImagePoppedOut(id) => {
let _ = self.visible.remove(&id);
Task::none()
}
Message::ImageDownloaded(Ok(rgba)) => {
self.viewer.show(rgba, self.now);
@ -181,7 +199,17 @@ impl Gallery {
let images = self
.images
.iter()
.map(|image| card(image, self.previews.get(&image.id), self.now))
.map(|image| {
card(
image,
if self.visible.contains(&image.id) {
self.previews.get(&image.id)
} else {
None
},
self.now,
)
})
.chain((self.images.len()..=Image::LIMIT).map(|_| placeholder()));
let gallery = grid(images)
@ -248,7 +276,7 @@ fn card<'a>(
.on_enter(Message::ThumbnailHovered(metadata.id, true))
.on_exit(Message::ThumbnailHovered(metadata.id, false));
if let Some(preview) = preview {
let card: Element<'_, _> = if let Some(preview) = preview {
let is_thumbnail = matches!(preview, Preview::Ready { .. });
button(card)
@ -257,10 +285,13 @@ fn card<'a>(
.style(button::text)
.into()
} else {
sensor(card)
.on_show(|_| Message::ImagePoppedIn(metadata.id))
.into()
}
card.into()
};
sensor(card)
.on_show(|_| Message::ImagePoppedIn(metadata.id))
.on_hide(Message::ImagePoppedOut(metadata.id))
.into()
}
fn placeholder<'a>() -> Element<'a, Message> {