mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Add some basic image loading caching for images loaded from the file system
Place them in a HashMap that's indexed by the path. This needs further tuning, for example to also be applied to embedded images, and the cache shouldn't hold a strong reference. But it makes the berlin page playable.
This commit is contained in:
parent
3d85e45ec3
commit
fdeda0d0ed
1 changed files with 53 additions and 16 deletions
|
@ -24,7 +24,7 @@ use sixtyfps_corelib::{
|
||||||
SharedArray,
|
SharedArray,
|
||||||
};
|
};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use std::cell::RefCell;
|
use std::{cell::RefCell, collections::HashMap};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
@ -76,7 +76,7 @@ enum GLRenderingPrimitive {
|
||||||
Texture {
|
Texture {
|
||||||
vertices: GLArrayBuffer<Vertex>,
|
vertices: GLArrayBuffer<Vertex>,
|
||||||
texture_vertices: GLArrayBuffer<Vertex>,
|
texture_vertices: GLArrayBuffer<Vertex>,
|
||||||
texture: texture::AtlasAllocation,
|
texture: Rc<texture::AtlasAllocation>,
|
||||||
},
|
},
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
DynamicPrimitive {
|
DynamicPrimitive {
|
||||||
|
@ -102,6 +102,8 @@ struct NormalRectangle {
|
||||||
indices: GLIndexBuffer<u16>,
|
indices: GLIndexBuffer<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TextureCacheKey = String;
|
||||||
|
|
||||||
pub struct GLRenderer {
|
pub struct GLRenderer {
|
||||||
context: Rc<glow::Context>,
|
context: Rc<glow::Context>,
|
||||||
path_shader: PathShader,
|
path_shader: PathShader,
|
||||||
|
@ -119,6 +121,7 @@ pub struct GLRenderer {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
windowed_context: Option<glutin::WindowedContext<glutin::NotCurrent>>,
|
windowed_context: Option<glutin::WindowedContext<glutin::NotCurrent>>,
|
||||||
normal_rectangle: Option<NormalRectangle>,
|
normal_rectangle: Option<NormalRectangle>,
|
||||||
|
texture_cache: Rc<RefCell<HashMap<TextureCacheKey, Rc<texture::AtlasAllocation>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GLRenderingPrimitivesBuilder {
|
pub struct GLRenderingPrimitivesBuilder {
|
||||||
|
@ -136,6 +139,8 @@ pub struct GLRenderingPrimitivesBuilder {
|
||||||
Rc<winit::event_loop::EventLoopProxy<sixtyfps_corelib::eventloop::CustomEvent>>,
|
Rc<winit::event_loop::EventLoopProxy<sixtyfps_corelib::eventloop::CustomEvent>>,
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
|
windowed_context: glutin::WindowedContext<glutin::PossiblyCurrent>,
|
||||||
|
|
||||||
|
texture_cache: Rc<RefCell<HashMap<TextureCacheKey, Rc<texture::AtlasAllocation>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GLFrame {
|
pub struct GLFrame {
|
||||||
|
@ -272,6 +277,7 @@ impl GLRenderer {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
windowed_context: Some(unsafe { windowed_context.make_not_current().unwrap() }),
|
windowed_context: Some(unsafe { windowed_context.make_not_current().unwrap() }),
|
||||||
normal_rectangle: None,
|
normal_rectangle: None,
|
||||||
|
texture_cache: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,6 +328,8 @@ impl GraphicsBackend for GLRenderer {
|
||||||
event_loop_proxy: self.event_loop_proxy.clone(),
|
event_loop_proxy: self.event_loop_proxy.clone(),
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
windowed_context: current_windowed_context,
|
windowed_context: current_windowed_context,
|
||||||
|
|
||||||
|
texture_cache: self.texture_cache.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,17 +428,15 @@ impl RenderingPrimitivesBuilder for GLRenderingPrimitivesBuilder {
|
||||||
let mut image_path = std::env::current_exe().unwrap();
|
let mut image_path = std::env::current_exe().unwrap();
|
||||||
image_path.pop(); // pop of executable name
|
image_path.pop(); // pop of executable name
|
||||||
image_path.push(&*path.clone());
|
image_path.push(&*path.clone());
|
||||||
let image = image::open(image_path.as_path()).unwrap().into_rgba();
|
|
||||||
let image = image::ImageBuffer::<image::Rgba<u8>, &[u8]>::from_raw(
|
let atlas_allocation = self
|
||||||
image.width(),
|
.cached_texture(image_path.to_string_lossy().to_string(), || {
|
||||||
image.height(),
|
image::open(image_path.as_path()).unwrap().into_rgba()
|
||||||
&image,
|
});
|
||||||
)
|
|
||||||
.unwrap();
|
smallvec![GLRenderingPrimitivesBuilder::create_texture(
|
||||||
smallvec![GLRenderingPrimitivesBuilder::create_image(
|
|
||||||
&self.context,
|
&self.context,
|
||||||
&mut *self.texture_atlas.borrow_mut(),
|
atlas_allocation,
|
||||||
image,
|
|
||||||
source_clip_rect
|
source_clip_rect
|
||||||
)]
|
)]
|
||||||
}
|
}
|
||||||
|
@ -634,16 +640,29 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
image: impl texture::UploadableAtlasImage,
|
image: impl texture::UploadableAtlasImage,
|
||||||
source_rect: &IntRect,
|
source_rect: &IntRect,
|
||||||
) -> GLRenderingPrimitive {
|
) -> GLRenderingPrimitive {
|
||||||
let rect =
|
let atlas_allocation = atlas.allocate_image_in_atlas(&context, image);
|
||||||
Rect::new(Point::new(0.0, 0.0), Size::new(image.width() as f32, image.height() as f32));
|
|
||||||
|
Self::create_texture(context, Rc::new(atlas_allocation), source_rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_texture(
|
||||||
|
context: &Rc<glow::Context>,
|
||||||
|
atlas_allocation: Rc<texture::AtlasAllocation>,
|
||||||
|
source_rect: &IntRect,
|
||||||
|
) -> GLRenderingPrimitive {
|
||||||
|
let rect = Rect::new(
|
||||||
|
Point::new(0.0, 0.0),
|
||||||
|
Size::new(
|
||||||
|
atlas_allocation.texture_coordinates.width() as f32,
|
||||||
|
atlas_allocation.texture_coordinates.height() as f32,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
let vertex1 = Vertex { _pos: [rect.min_x(), rect.min_y()] };
|
let vertex1 = Vertex { _pos: [rect.min_x(), rect.min_y()] };
|
||||||
let vertex2 = Vertex { _pos: [rect.max_x(), rect.min_y()] };
|
let vertex2 = Vertex { _pos: [rect.max_x(), rect.min_y()] };
|
||||||
let vertex3 = Vertex { _pos: [rect.max_x(), rect.max_y()] };
|
let vertex3 = Vertex { _pos: [rect.max_x(), rect.max_y()] };
|
||||||
let vertex4 = Vertex { _pos: [rect.min_x(), rect.max_y()] };
|
let vertex4 = Vertex { _pos: [rect.min_x(), rect.max_y()] };
|
||||||
|
|
||||||
let atlas_allocation = atlas.allocate_image_in_atlas(&context, image);
|
|
||||||
|
|
||||||
let vertices = GLArrayBuffer::new(
|
let vertices = GLArrayBuffer::new(
|
||||||
&context,
|
&context,
|
||||||
&vec![vertex1, vertex2, vertex3, vertex1, vertex3, vertex4],
|
&vec![vertex1, vertex2, vertex3, vertex1, vertex3, vertex4],
|
||||||
|
@ -656,6 +675,24 @@ impl GLRenderingPrimitivesBuilder {
|
||||||
GLRenderingPrimitive::Texture { vertices, texture_vertices, texture: atlas_allocation }
|
GLRenderingPrimitive::Texture { vertices, texture_vertices, texture: atlas_allocation }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cached_texture<Img: texture::UploadableAtlasImage>(
|
||||||
|
&self,
|
||||||
|
key: TextureCacheKey,
|
||||||
|
create_fn: impl Fn() -> Img,
|
||||||
|
) -> Rc<texture::AtlasAllocation> {
|
||||||
|
self.texture_cache
|
||||||
|
.borrow_mut()
|
||||||
|
.entry(key)
|
||||||
|
.or_insert_with(|| {
|
||||||
|
Rc::new(
|
||||||
|
self.texture_atlas
|
||||||
|
.borrow_mut()
|
||||||
|
.allocate_image_in_atlas(&self.context, create_fn()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn create_glyph_runs(
|
fn create_glyph_runs(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue