Skip to content
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
merged 3 commits into from Oct 16, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Skip the request and return a invalid CacheItem for the over-size-lim…

…it image request.

WR can't handle the image request if it's bigger than the hardware limit. Please check texture_cache::max_texture_size().

Skip the image request for a big size image in resource_cache::request_image().
Return an Err() for a big size image in resource_cache::get_cached_image().
  • Loading branch information
JerryShih committed Oct 16, 2017
commit 5f5c68f34061799040c435fe1cf7db5aa4ae0935
@@ -188,7 +188,7 @@ impl GlyphRasterizer {
for key in glyph_keys {
match glyph_key_cache.entry(key.clone()) {
Entry::Occupied(mut entry) => {
if let Some(ref mut glyph_info) = *entry.get_mut() {
if let Ok(Some(ref mut glyph_info)) = *entry.get_mut() {
if texture_cache.request(&mut glyph_info.texture_cache_handle, gpu_cache) {
// This case gets hit when we have already rasterized
// the glyph and stored it in CPU memory, the the glyph
@@ -352,7 +352,7 @@ impl GlyphRasterizer {

let glyph_key_cache = glyph_cache.get_glyph_key_cache_for_font_mut(job.request.font);

glyph_key_cache.insert(job.request.key, glyph_info);
glyph_key_cache.insert(job.request.key, Ok(glyph_info));
}

// Now that we are done with the critical path (rendering the glyphs),
@@ -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();

This comment has been minimized.

@kvark

kvark Oct 12, 2017

Member

why is this removed? I assume we get a warning about unused Result or Option

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,
@@ -482,6 +482,7 @@ impl AlphaRenderItem {
);

if color_texture_id == SourceTexture::Invalid {
warn!("Warnings: skip a PrimitiveKind::Image at {:?}.\n", item_bounding_rect);
return;
}

@@ -540,6 +541,8 @@ impl AlphaRenderItem {
glyph_fetch_buffer,
gpu_cache,
|texture_id, glyphs| {
debug_assert_ne!(texture_id, SourceTexture::Invalid);

let textures = BatchTextures {
colors: [
texture_id,
@@ -633,6 +636,7 @@ impl AlphaRenderItem {
);

if texture == SourceTexture::Invalid {
warn!("Warnings: skip a PrimitiveKind::YuvImage at {:?}.\n", item_bounding_rect);
return;
}

@@ -837,16 +841,19 @@ impl ClipBatcher {

match *source {
ClipSource::Image(ref mask) => {
let cache_item =
resource_cache.get_cached_image(mask.image, ImageRendering::Auto, None);
self.images
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
clip_data_address: gpu_address,
resource_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
..instance
});
if let Ok(cache_item) = resource_cache.get_cached_image(mask.image, ImageRendering::Auto, None) {
self.images
.entry(cache_item.texture_id)
.or_insert(Vec::new())
.push(ClipMaskInstance {
clip_data_address: gpu_address,
resource_address: gpu_cache.get_address(&cache_item.uv_rect_handle),
..instance
});
} else {
warn!("Warnings: skip a image mask. Key:{:?} Rect::{:?}.\n", mask.image, mask.rect);
continue;
}
}
ClipSource::Rectangle(..) => {
if work_item.coordinate_system_id != coordinate_system_id {
@@ -1832,10 +1839,12 @@ fn resolve_image(
(SourceTexture::External(external_image), cache_handle)
}
None => {
let cache_item =
resource_cache.get_cached_image(image_key, image_rendering, tile_offset);

(cache_item.texture_id, cache_item.uv_rect_handle)
if let Ok(cache_item) = resource_cache.get_cached_image(image_key, image_rendering, tile_offset) {
(cache_item.texture_id, cache_item.uv_rect_handle)
} else {
// There is no usable texture entry for the image key. Just return an invalid texture here.
(SourceTexture::Invalid, GpuCacheHandle::new())
}
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.