From 2af89314cf7e1d6dfee3b92beaf3f797added74f Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 17 Jul 2017 11:50:50 +0200 Subject: [PATCH 1/3] Support resizing items in the texture cache. --- webrender/src/resource_cache.rs | 6 +++ webrender/src/texture_cache.rs | 81 +++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index bdf8a5c9e5..805d3fa71a 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -659,6 +659,11 @@ impl ResourceCache { image_template.data.clone() }); + let filter = match request.rendering { + ImageRendering::Pixelated => TextureFilter::Nearest, + ImageRendering::Auto | ImageRendering::CrispEdges => TextureFilter::Linear, + }; + let descriptor = if let Some(tile) = request.tile { let tile_size = image_template.tiling.unwrap(); let image_descriptor = &image_template.descriptor; @@ -699,6 +704,7 @@ impl ResourceCache { if entry.get().epoch != image_template.epoch { self.texture_cache.update(image_id, descriptor, + filter, image_data, image_template.dirty_rect); diff --git a/webrender/src/texture_cache.rs b/webrender/src/texture_cache.rs index 8ade4b948e..d9a4279dd7 100644 --- a/webrender/src/texture_cache.rs +++ b/webrender/src/texture_cache.rs @@ -615,14 +615,37 @@ impl TextureCache { mem::replace(&mut self.pending_updates, TextureUpdateList::new()) } - pub fn allocate(&mut self, - requested_width: u32, - requested_height: u32, - format: ImageFormat, - filter: TextureFilter, - user_data: [f32; 2], - profile: &mut TextureCacheProfileCounters) - -> AllocationResult { + pub fn allocate( + &mut self, + requested_width: u32, + requested_height: u32, + format: ImageFormat, + filter: TextureFilter, + user_data: [f32; 2], + profile: &mut TextureCacheProfileCounters + ) -> AllocationResult { + self.allocate_impl( + requested_width, + requested_height, + format, + filter, + user_data, + profile, + None, + ) + } + + // If item_id is None, create a new id, otherwise reuse it. + fn allocate_impl( + &mut self, + requested_width: u32, + requested_height: u32, + format: ImageFormat, + filter: TextureFilter, + user_data: [f32; 2], + profile: &mut TextureCacheProfileCounters, + item_id: Option + ) -> AllocationResult { let requested_size = DeviceUintSize::new(requested_width, requested_height); // TODO(gw): For now, anything that requests nearest filtering @@ -636,8 +659,13 @@ impl TextureCache { let cache_item = TextureCacheItem::new( texture_id, DeviceUintRect::new(DeviceUintPoint::zero(), requested_size), - user_data); - let image_id = self.items.insert(cache_item); + user_data + ); + + let image_id = match item_id { + Some(id) => id, + None => self.items.insert(cache_item.clone()), + }; return AllocationResult { item: self.items.get(image_id).clone(), @@ -734,7 +762,11 @@ impl TextureCache { let cache_item = TextureCacheItem::new(page.texture_id, DeviceUintRect::new(location, requested_size), user_data); - let image_id = self.items.insert(cache_item.clone()); + + let image_id = match item_id { + Some(id) => id, + None => self.items.insert(cache_item.clone()), + }; AllocationResult { item: cache_item, @@ -746,13 +778,28 @@ impl TextureCache { pub fn update(&mut self, image_id: TextureCacheItemId, descriptor: ImageDescriptor, + filter: TextureFilter, data: ImageData, dirty_rect: Option) { - let existing_item = self.items.get(image_id); + let existing_item = self.items.get(image_id).clone(); + + if existing_item.allocated_rect.size.width != descriptor.width || + existing_item.allocated_rect.size.height != descriptor.height { - // TODO(gw): Handle updates to size/format! - debug_assert_eq!(existing_item.allocated_rect.size.width, descriptor.width); - debug_assert_eq!(existing_item.allocated_rect.size.height, descriptor.height); + self.free_item_rect(existing_item.clone()); + + self.allocate_impl( + descriptor.width, + descriptor.height, + descriptor.format, + filter, + existing_item.user_data, + &mut TextureCacheProfileCounters::new(), + Some(image_id), + ); + + return; + } let op = match data { ImageData::External(..) => { @@ -933,6 +980,10 @@ impl TextureCache { pub fn free(&mut self, id: TextureCacheItemId) { let item = self.items.free(id); + self.free_item_rect(item); + } + + fn free_item_rect(&mut self, item: TextureCacheItem) { match self.arena.texture_page_for_id(item.texture_id) { Some(texture_page) => texture_page.free(&item.allocated_rect), None => { From f388a42530fa026032bd2fd18269b33b8d5a4c5f Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Tue, 18 Jul 2017 15:30:59 +0200 Subject: [PATCH 2/3] Texture size update fixes. --- webrender/src/resource_cache.rs | 2 -- webrender/src/texture_cache.rs | 21 +++++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 805d3fa71a..f89447ec53 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -312,8 +312,6 @@ impl ResourceCache { mut data: ImageData, dirty_rect: Option) { let resource = if let Some(image) = self.resources.image_templates.get(image_key) { - assert_eq!(image.descriptor.width, descriptor.width); - assert_eq!(image.descriptor.height, descriptor.height); assert_eq!(image.descriptor.format, descriptor.format); let next_epoch = Epoch(image.epoch.0 + 1); diff --git a/webrender/src/texture_cache.rs b/webrender/src/texture_cache.rs index d9a4279dd7..d5c657f2ee 100644 --- a/webrender/src/texture_cache.rs +++ b/webrender/src/texture_cache.rs @@ -775,13 +775,15 @@ impl TextureCache { } } - pub fn update(&mut self, - image_id: TextureCacheItemId, - descriptor: ImageDescriptor, - filter: TextureFilter, - data: ImageData, - dirty_rect: Option) { - let existing_item = self.items.get(image_id).clone(); + pub fn update( + &mut self, + image_id: TextureCacheItemId, + descriptor: ImageDescriptor, + filter: TextureFilter, + data: ImageData, + mut dirty_rect: Option, + ) { + let mut existing_item = self.items.get(image_id).clone(); if existing_item.allocated_rect.size.width != descriptor.width || existing_item.allocated_rect.size.height != descriptor.height { @@ -798,7 +800,10 @@ impl TextureCache { Some(image_id), ); - return; + // Fetch the item again because the rect most likely changed during reallocation. + existing_item = self.items.get(image_id).clone(); + // If we reallocated, we need to upload the whole item again. + dirty_rect = None; } let op = match data { From edada88bb4598b6474fde1b0569906809a8bd8bb Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Wed, 19 Jul 2017 16:15:11 +0200 Subject: [PATCH 3/3] Support changing the format of items in the texture cache. --- webrender/src/resource_cache.rs | 1 - webrender/src/texture_cache.rs | 17 +++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index f89447ec53..49613c8bee 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -312,7 +312,6 @@ impl ResourceCache { mut data: ImageData, dirty_rect: Option) { let resource = if let Some(image) = self.resources.image_templates.get(image_key) { - assert_eq!(image.descriptor.format, descriptor.format); let next_epoch = Epoch(image.epoch.0 + 1); diff --git a/webrender/src/texture_cache.rs b/webrender/src/texture_cache.rs index d5c657f2ee..26d01beeb9 100644 --- a/webrender/src/texture_cache.rs +++ b/webrender/src/texture_cache.rs @@ -452,6 +452,8 @@ pub struct TextureCacheItem { // Handle to the location of the UV rect for this item in GPU cache. pub uv_rect_handle: GpuCacheHandle, + pub format: ImageFormat, + // Some arbitrary data associated with this item. // In the case of glyphs, it is the top / left offset // from the rasterized glyph. @@ -493,6 +495,7 @@ impl FreeListItem for TextureCacheItem { impl TextureCacheItem { fn new(texture_id: CacheTextureId, rect: DeviceUintRect, + format: ImageFormat, user_data: [f32; 2]) -> TextureCacheItem { TextureCacheItem { @@ -505,6 +508,7 @@ impl TextureCacheItem { }, allocated_rect: rect, uv_rect_handle: GpuCacheHandle::new(), + format, user_data, } } @@ -659,6 +663,7 @@ impl TextureCache { let cache_item = TextureCacheItem::new( texture_id, DeviceUintRect::new(DeviceUintPoint::zero(), requested_size), + format, user_data ); @@ -759,9 +764,12 @@ impl TextureCache { let location = page.allocate(&requested_size) .expect("All the checks have passed till now, there is no way back."); - let cache_item = TextureCacheItem::new(page.texture_id, - DeviceUintRect::new(location, requested_size), - user_data); + let cache_item = TextureCacheItem::new( + page.texture_id, + DeviceUintRect::new(location, requested_size), + format, + user_data + ); let image_id = match item_id { Some(id) => id, @@ -786,7 +794,8 @@ impl TextureCache { let mut existing_item = self.items.get(image_id).clone(); if existing_item.allocated_rect.size.width != descriptor.width || - existing_item.allocated_rect.size.height != descriptor.height { + existing_item.allocated_rect.size.height != descriptor.height || + existing_item.format != descriptor.format { self.free_item_rect(existing_item.clone());