New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle big size image #1564
Merged
+89
−37
Merged
Handle big size image #1564
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.
| @@ -22,6 +22,7 @@ use internal_types::{FastHashMap, FastHashSet, SourceTexture, TextureUpdateList} | ||
| use profiler::{ResourceProfileCounters, TextureCacheProfileCounters}; | ||
| use rayon::ThreadPool; | ||
| use std::collections::hash_map::Entry::{self, Occupied, Vacant}; | ||
| use std::cmp; | ||
| use std::fmt::Debug; | ||
| use std::hash::Hash; | ||
| use std::mem; | ||
| @@ -113,8 +114,15 @@ struct CachedImageInfo { | ||
| epoch: Epoch, | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| pub enum ResourceClassCacheError { | ||
| OverLimitSize, | ||
| } | ||
|
|
||
| pub type ResourceCacheResult<V> = Result<V, ResourceClassCacheError>; | ||
|
|
||
| pub struct ResourceClassCache<K, V> { | ||
| resources: FastHashMap<K, V>, | ||
| resources: FastHashMap<K, ResourceCacheResult<V>>, | ||
| } | ||
|
|
||
| impl<K, V> ResourceClassCache<K, V> | ||
| @@ -127,21 +135,21 @@ where | ||
| } | ||
| } | ||
|
|
||
| fn get(&self, key: &K) -> &V { | ||
| self.resources | ||
| .get(key) | ||
| fn get(&self, key: &K) -> &ResourceCacheResult<V> { | ||
| self.resources.get(key) | ||
| .expect("Didn't find a cached resource with that ID!") | ||
| } | ||
|
|
||
| pub fn insert(&mut self, key: K, value: V) { | ||
| pub fn insert(&mut self, key: K, value: ResourceCacheResult<V>) { | ||
| self.resources.insert(key, value); | ||
| } | ||
|
|
||
| pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { | ||
| pub fn get_mut(&mut self, key: &K) -> &mut ResourceCacheResult<V> { | ||
| self.resources.get_mut(key) | ||
| .expect("Didn't find a cached resource with that ID!") | ||
| } | ||
|
|
||
| pub fn entry(&mut self, key: K) -> Entry<K, V> { | ||
| pub fn entry(&mut self, key: K) -> Entry<K, ResourceCacheResult<V>> { | ||
| self.resources.entry(key) | ||
| } | ||
|
|
||
| @@ -159,7 +167,7 @@ where | ||
| .cloned() | ||
| .collect::<Vec<_>>(); | ||
| for key in resources_to_destroy { | ||
| self.resources.remove(&key).unwrap(); | ||
kvark
Member
|
||
| let _ = self.resources.remove(&key).unwrap(); | ||
| } | ||
| } | ||
| } | ||
| @@ -483,25 +491,38 @@ impl ResourceCache { | ||
| return; | ||
| } | ||
|
|
||
| let side_size = | ||
| template.tiling.map_or(cmp::max(template.descriptor.width, template.descriptor.height), | ||
| |tile_size| tile_size as u32); | ||
| if side_size > self.texture_cache.max_texture_size() { | ||
| // The image or tiling size is too big for hardware texture size. | ||
| warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!", | ||
| template.descriptor.width, template.descriptor.height, template.tiling.unwrap_or(0)); | ||
| self.cached_images.insert(request, Err(ResourceClassCacheError::OverLimitSize)); | ||
| return; | ||
| } | ||
|
|
||
| // If this image exists in the texture cache, *and* the epoch | ||
| // in the cache matches that of the template, then it is | ||
| // valid to use as-is. | ||
| let (entry, needs_update) = match self.cached_images.entry(request) { | ||
| Occupied(entry) => { | ||
| let needs_update = entry.get().epoch != template.epoch; | ||
| let needs_update = entry.get().as_ref().unwrap().epoch != template.epoch; | ||
| (entry.into_mut(), needs_update) | ||
| } | ||
| Vacant(entry) => ( | ||
| entry.insert(CachedImageInfo { | ||
| epoch: template.epoch, | ||
| texture_cache_handle: TextureCacheHandle::new(), | ||
| }), | ||
| entry.insert(Ok( | ||
| CachedImageInfo { | ||
| epoch: template.epoch, | ||
| texture_cache_handle: TextureCacheHandle::new(), | ||
| } | ||
| )), | ||
| true, | ||
| ), | ||
| }; | ||
|
|
||
| let needs_upload = self.texture_cache | ||
| .request(&mut entry.texture_cache_handle, gpu_cache); | ||
| .request(&mut entry.as_mut().unwrap().texture_cache_handle, gpu_cache); | ||
|
|
||
| if !needs_upload && !needs_update { | ||
| return; | ||
| @@ -600,7 +621,7 @@ impl ResourceCache { | ||
| debug_assert!(fetch_buffer.is_empty()); | ||
|
|
||
| for (loop_index, key) in glyph_keys.iter().enumerate() { | ||
| if let Some(ref glyph) = *glyph_key_cache.get(key) { | ||
| if let Ok(Some(ref glyph)) = *glyph_key_cache.get(key) { | ||
| let cache_item = self.texture_cache.get(&glyph.texture_cache_handle); | ||
| if current_texture_id != cache_item.texture_id { | ||
| if !fetch_buffer.is_empty() { | ||
| @@ -648,15 +669,24 @@ impl ResourceCache { | ||
| image_key: ImageKey, | ||
| image_rendering: ImageRendering, | ||
| tile: Option<TileOffset>, | ||
| ) -> CacheItem { | ||
| ) -> Result<CacheItem, ()> { | ||
| debug_assert_eq!(self.state, State::QueryResources); | ||
| let key = ImageRequest { | ||
| key: image_key, | ||
| rendering: image_rendering, | ||
| tile, | ||
| }; | ||
| let image_info = &self.cached_images.get(&key); | ||
| self.texture_cache.get(&image_info.texture_cache_handle) | ||
|
|
||
| // TODO(Jerry): add a debug option to visualize the corresponding area for | ||
| // the Err() case of CacheItem. | ||
| match *self.cached_images.get(&key) { | ||
| Ok(ref image_info) => { | ||
| Ok(self.texture_cache.get(&image_info.texture_cache_handle)) | ||
| } | ||
| Err(_) => { | ||
| Err(()) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pub fn get_image_properties(&self, image_key: ImageKey) -> Option<ImageProperties> { | ||
| @@ -816,7 +846,7 @@ impl ResourceCache { | ||
| image_template.descriptor.clone() | ||
| }; | ||
|
|
||
| let entry = self.cached_images.get_mut(&request).unwrap(); | ||
| let entry = self.cached_images.get_mut(&request).as_mut().unwrap(); | ||
| self.texture_cache.update( | ||
| &mut entry.texture_cache_handle, | ||
| descriptor, | ||
| @@ -1,4 +1,5 @@ | ||
| == tile-size.yaml tile-size-ref.yaml | ||
| == very-big.yaml very-big-ref.yaml | ||
| == very-big-tile-size.yaml very-big-tile-size-ref.yaml | ||
| == tile-with-spacing.yaml tile-with-spacing-ref.yaml | ||
| fuzzy(1,250000) == tile-repeat-prim-or-decompose.yaml tile-repeat-prim-or-decompose-ref.yaml |
| @@ -0,0 +1,5 @@ | ||
| root: | ||
| items: | ||
| - type: rect | ||
| bounds: 0 0 500 500 | ||
| color: green |
| @@ -0,0 +1,9 @@ | ||
| root: | ||
| items: | ||
| - type: rect | ||
| bounds: 0 0 500 500 | ||
| color: green | ||
| - image: solid-color(255, 0, 0, 255, 100000, 1000) | ||
| bounds: 0 0 500 500 | ||
| stretch-size: 1000000 1000 | ||
| tile-size: 60000 |
ProTip!
Use n and p to navigate between commits in a pull request.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
This comment is not correct now.