Skip to content

Commit

Permalink
handle image loading on wasm in the old way
Browse files Browse the repository at this point in the history
  • Loading branch information
bircni committed Nov 20, 2024
1 parent 10e496f commit d1ca8ec
Showing 1 changed file with 68 additions and 28 deletions.
96 changes: 68 additions & 28 deletions crates/egui_extras/src/loaders/image_loader.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use ahash::HashMap;
use egui::{
load::{BytesPoll, ImageLoadResult, ImageLoader, ImagePoll, LoadError, SizeHint},
load::{Bytes, BytesPoll, ImageLoadResult, ImageLoader, ImagePoll, LoadError, SizeHint},
mutex::Mutex,
ColorImage,
};
use image::ImageFormat;
use std::{mem::size_of, path::Path, sync::Arc, task::Poll, thread};
use std::{mem::size_of, path::Path, sync::Arc, task::Poll};

#[cfg(not(target_arch = "wasm32"))]
use std::thread;

type Entry = Poll<Result<Arc<ColorImage>, String>>;

Expand Down Expand Up @@ -55,7 +58,61 @@ impl ImageLoader for ImageCrateLoader {
return Err(LoadError::NotSupported);
}

let mut cache = self.cache.lock();
let cache = self.cache.lock();

#[cfg(not(target_arch = "wasm32"))]
#[allow(clippy::unnecessary_wraps)] // needed here to match other return types
fn load_image(
ctx: &egui::Context,
uri: &str,
cache: &Arc<Mutex<HashMap<String, Entry>>>,
bytes: Bytes,
) -> ImageLoadResult {
let mut cache_lock = cache.lock();

let uri = uri.to_owned();
cache_lock.insert(uri.clone(), Poll::Pending);
drop(cache_lock);

// Do the image parsing on a bg thread
thread::Builder::new()
.name(format!("egui_extras::ImageLoader::load({uri:?})"))
.spawn({
let ctx = ctx.clone();
let cache = cache.clone();

let uri = uri.clone();
move || {
log::trace!("ImageLoader - started loading {uri:?}");
let result = crate::image::load_image_bytes(&bytes).map(Arc::new);
log::trace!("ImageLoader - finished loading {uri:?}");
let prev = cache.lock().insert(uri, Poll::Ready(result));
assert!(matches!(prev, Some(Poll::Pending)));

ctx.request_repaint();
}
})
.expect("failed to spawn thread");

Ok(ImagePoll::Pending { size: None })
}

fn load_image_wasm(
uri: &str,
cache: &Arc<Mutex<HashMap<String, Entry>>>,
bytes: &Bytes,
) -> ImageLoadResult {
let mut cache_lock = cache.lock();
log::trace!("started loading {uri:?}");
let result = crate::image::load_image_bytes(bytes).map(Arc::new);
log::trace!("finished loading {uri:?}");
cache_lock.insert(uri.into(), std::task::Poll::Ready(result.clone()));
match result {
Ok(image) => Ok(ImagePoll::Ready { image }),
Err(err) => Err(LoadError::Loading(err)),
}
}

if let Some(entry) = cache.get(uri).cloned() {
match entry {
Poll::Ready(Ok(image)) => Ok(ImagePoll::Ready { image }),
Expand All @@ -72,31 +129,14 @@ impl ImageLoader for ImageCrateLoader {
return Err(LoadError::NotSupported);
}

let uri = uri.to_owned();
cache.insert(uri.clone(), Poll::Pending);
drop(cache);

// Do the image parsing on a bg thread
thread::Builder::new()
.name(format!("egui_extras::ImageLoader::load({uri:?})"))
.spawn({
let ctx = ctx.clone();
let cache = self.cache.clone();

let uri = uri.clone();
move || {
log::trace!("ImageLoader - started loading {uri:?}");
let result = crate::image::load_image_bytes(&bytes).map(Arc::new);
log::trace!("ImageLoader - finished loading {uri:?}");
let prev = cache.lock().insert(uri, Poll::Ready(result));
assert!(matches!(prev, Some(Poll::Pending)));

ctx.request_repaint();
}
})
.expect("failed to spawn thread");

Ok(ImagePoll::Pending { size: None })
if cfg!(target_arch = "wasm32") {
load_image_wasm(uri, &self.cache, &bytes)
} else {
#[cfg(target_arch = "wasm32")]
unreachable!();
#[cfg(not(target_arch = "wasm32"))]
load_image(ctx, uri, &self.cache, bytes)
}
}
Ok(BytesPoll::Pending { size }) => Ok(ImagePoll::Pending { size }),
Err(err) => Err(err),
Expand Down

0 comments on commit d1ca8ec

Please sign in to comment.