use super::resources::EglImage;
#[derive(Debug, PartialEq)]
pub(super) enum CacheKind {
Src,
Dst,
}
pub(super) struct CachedEglImage {
pub(super) egl_image: EglImage,
pub(super) guard: std::sync::Weak<()>,
pub(super) renderbuffer: Option<u32>,
pub(super) last_used: u64,
}
pub(super) type EglCacheKey = (u64, Option<u64>);
pub(super) struct EglImageCache {
pub(super) entries: std::collections::HashMap<EglCacheKey, CachedEglImage>,
pub(super) capacity: usize,
pub(super) hits: u64,
pub(super) misses: u64,
pub(super) access_counter: u64,
}
impl EglImageCache {
pub(super) fn new(capacity: usize) -> Self {
Self {
entries: std::collections::HashMap::with_capacity(capacity),
capacity,
hits: 0,
misses: 0,
access_counter: 0,
}
}
pub(super) fn next_timestamp(&mut self) -> u64 {
self.access_counter += 1;
self.access_counter
}
pub(super) fn evict_lru(&mut self) -> bool {
if let Some((&evict_id, _)) = self.entries.iter().min_by_key(|(_, entry)| entry.last_used) {
let evicted = self.entries.remove(&evict_id).expect("key just found");
if let Some(rbo) = evicted.renderbuffer {
unsafe { gls::gl::DeleteRenderbuffers(1, &rbo) };
}
return true;
}
false
}
pub(super) fn sweep(&mut self) -> bool {
let before = self.entries.len();
self.entries.retain(|_id, entry| {
let alive = entry.guard.upgrade().is_some();
if !alive {
if let Some(rbo) = entry.renderbuffer {
unsafe { gls::gl::DeleteRenderbuffers(1, &rbo) };
}
}
alive
});
let swept = before - self.entries.len();
if swept > 0 {
log::debug!("EglImageCache: swept {swept} dead entries");
}
swept > 0
}
}
impl Drop for EglImageCache {
fn drop(&mut self) {
for entry in self.entries.values() {
if let Some(rbo) = entry.renderbuffer {
unsafe { gls::gl::DeleteRenderbuffers(1, &rbo) };
}
}
log::debug!(
"EglImageCache stats: {} hits, {} misses, {} entries remaining",
self.hits,
self.misses,
self.entries.len()
);
}
}