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 all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -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),
@@ -1058,7 +1058,6 @@ impl PrimitiveStore {
}
}

/// Returns true if the bounding box needs to be updated.

This comment has been minimized.

@JerryShih

JerryShih Oct 12, 2017

Author Contributor

This comment is not correct now.

fn prepare_prim_for_render_inner(
&mut self,
prim_index: PrimitiveIndex,
@@ -1326,7 +1325,6 @@ impl PrimitiveStore {
true
}

/// Returns true if the bounding box needs to be updated.
pub fn prepare_prim_for_render(
&mut self,
prim_index: PrimitiveIndex,
@@ -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())
}
}
}
}
@@ -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.
You can’t perform that action at this time.