From 604018cb2ecd6e729f59bca78792e6116265d099 Mon Sep 17 00:00:00 2001 From: "arthur.iakab" Date: Fri, 11 Oct 2019 18:27:52 +0300 Subject: [PATCH] Backed out changeset 42d3ccf69629 (bug 1583879) for causing reftest failures on sort-startSame-1b.svg CLOSED TREE --- gfx/webrender_bindings/Moz2DImageRenderer.cpp | 51 ++-- gfx/webrender_bindings/src/bindings.rs | 30 +- gfx/webrender_bindings/src/moz2d_renderer.rs | 36 +-- gfx/wr/examples/blob.rs | 2 +- gfx/wr/webrender/src/clip.rs | 19 +- gfx/wr/webrender/src/prim_store/borders.rs | 6 +- gfx/wr/webrender/src/prim_store/image.rs | 12 +- gfx/wr/webrender/src/prim_store/mod.rs | 37 +-- gfx/wr/webrender/src/resource_cache.rs | 282 ++++++------------ gfx/wr/webrender/src/texture_cache.rs | 9 - gfx/wr/webrender_api/src/image.rs | 5 +- gfx/wr/wrench/src/blob.rs | 2 +- 12 files changed, 177 insertions(+), 314 deletions(-) diff --git a/gfx/webrender_bindings/Moz2DImageRenderer.cpp b/gfx/webrender_bindings/Moz2DImageRenderer.cpp index 59d9b0bb70fe..46284274ee9c 100644 --- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp +++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp @@ -333,26 +333,25 @@ struct Reader { layers::BlobFont ReadBlobFont() { return Read(); } }; -static wr::BlobRenderStatus -Moz2DRenderCallback(const Range aBlob, - gfx::SurfaceFormat aFormat, - const mozilla::wr::DeviceIntRect* aVisibleRect, - const mozilla::wr::LayoutIntRect* aRenderRect, - const uint16_t* aTileSize, - const mozilla::wr::TileOffset* aTileOffset, - const mozilla::wr::LayoutIntRect* aDirtyRect, - Range aOutput) { +static bool Moz2DRenderCallback(const Range aBlob, + gfx::SurfaceFormat aFormat, + const mozilla::wr::DeviceIntRect* aVisibleRect, + const mozilla::wr::LayoutIntRect* aRenderRect, + const uint16_t* aTileSize, + const mozilla::wr::TileOffset* aTileOffset, + const mozilla::wr::LayoutIntRect* aDirtyRect, + Range aOutput) { IntSize size(aRenderRect->size.width, aRenderRect->size.height); AUTO_PROFILER_TRACING("WebRender", "RasterizeSingleBlob", GRAPHICS); MOZ_RELEASE_ASSERT(size.width > 0 && size.height > 0); if (size.width <= 0 || size.height <= 0) { - return BlobRenderStatus::Error; + return false; } auto stride = size.width * gfx::BytesPerPixel(aFormat); if (aOutput.length() < static_cast(size.height * stride)) { - return BlobRenderStatus::Error; + return false; } // In bindings.rs we allocate a buffer filled with opaque white. @@ -363,7 +362,7 @@ Moz2DRenderCallback(const Range aBlob, uninitialized); if (!dt) { - return BlobRenderStatus::Error; + return false; } // We try hard to not have empty blobs but we can end up with @@ -393,7 +392,7 @@ Moz2DRenderCallback(const Range aBlob, aDirtyRect->size.width, aDirtyRect->size.height)); } - wr::BlobRenderStatus status = wr::BlobRenderStatus::Empty; + bool ret = true; size_t offset = 0; auto absBounds = IntRectAbsolute::FromRect(bounds); while (reader.pos < reader.len) { @@ -408,8 +407,6 @@ Moz2DRenderCallback(const Range aBlob, continue; } - status = BlobRenderStatus::Ok; - layers::WebRenderTranslator translator(dt); Reader fontReader(aBlob.begin().get() + end, extra_end - end); size_t count = fontReader.ReadSize(); @@ -421,10 +418,9 @@ Moz2DRenderCallback(const Range aBlob, } Range blob(aBlob.begin() + offset, aBlob.begin() + end); - bool ok = + ret = translator.TranslateRecording((char*)blob.begin().get(), blob.length()); - if (!ok) { - status = BlobRenderStatus::Error; + if (!ret) { gfxCriticalNote << "Replay failure: " << translator.GetError(); MOZ_RELEASE_ASSERT(false); } @@ -451,7 +447,7 @@ Moz2DRenderCallback(const Range aBlob, gfxUtils::WriteAsPNG(dt, filename); #endif - return status; + return ret; } } // namespace wr @@ -459,15 +455,14 @@ Moz2DRenderCallback(const Range aBlob, extern "C" { -mozilla::wr::BlobRenderStatus -wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob, - mozilla::wr::ImageFormat aFormat, - const mozilla::wr::LayoutIntRect* aRenderRect, - const mozilla::wr::DeviceIntRect* aVisibleRect, - const uint16_t* aTileSize, - const mozilla::wr::TileOffset* aTileOffset, - const mozilla::wr::LayoutIntRect* aDirtyRect, - mozilla::wr::MutByteSlice output) { +bool wr_moz2d_render_cb(const mozilla::wr::ByteSlice blob, + mozilla::wr::ImageFormat aFormat, + const mozilla::wr::LayoutIntRect* aRenderRect, + const mozilla::wr::DeviceIntRect* aVisibleRect, + const uint16_t* aTileSize, + const mozilla::wr::TileOffset* aTileOffset, + const mozilla::wr::LayoutIntRect* aDirtyRect, + mozilla::wr::MutByteSlice output) { return mozilla::wr::Moz2DRenderCallback( mozilla::wr::ByteSliceToRange(blob), mozilla::wr::ImageFormatToSurfaceFormat(aFormat), aVisibleRect, diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index d31ef39ad0f6..3f1d0c38ff5d 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -3263,24 +3263,20 @@ pub unsafe extern "C" fn wr_dec_ref_arc(arc: *const VecU8) { Arc::from_raw(arc); } -#[repr(u32)] -pub enum BlobRenderStatus { - Ok, - Empty, - Error, -} - +// TODO: nical +// Update for the new blob image interface changes. +// extern "C" { - // TODO: figure out the API for tiled blob images. - pub fn wr_moz2d_render_cb(blob: ByteSlice, - format: ImageFormat, - render_rect: &LayoutIntRect, - visible_rect: &DeviceIntRect, - tile_size: Option<&u16>, - tile_offset: Option<&TileOffset>, - dirty_rect: Option<&LayoutIntRect>, - output: MutByteSlice) - -> BlobRenderStatus; + // TODO: figure out the API for tiled blob images. + pub fn wr_moz2d_render_cb(blob: ByteSlice, + format: ImageFormat, + render_rect: &LayoutIntRect, + visible_rect: &DeviceIntRect, + tile_size: Option<&u16>, + tile_offset: Option<&TileOffset>, + dirty_rect: Option<&LayoutIntRect>, + output: MutByteSlice) + -> bool; } #[no_mangle] diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs index f99ab81e06e0..aec63393dfc5 100644 --- a/gfx/webrender_bindings/src/moz2d_renderer.rs +++ b/gfx/webrender_bindings/src/moz2d_renderer.rs @@ -8,8 +8,7 @@ use webrender::api::*; use webrender::api::units::{BlobDirtyRect, BlobToDeviceTranslation, DeviceIntRect}; -use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8}; -use bindings::{BlobRenderStatus, gecko_profiler_start_marker, gecko_profiler_end_marker}; +use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8, gecko_profiler_start_marker, gecko_profiler_end_marker}; use rayon::ThreadPool; use rayon::prelude::*; @@ -580,7 +579,7 @@ fn rasterize_blob(job: Job) -> (BlobImageRequest, BlobImageResult) { assert!(descriptor.rect.size.width > 0 && descriptor.rect.size.height > 0); let result = unsafe { - match wr_moz2d_render_cb( + if wr_moz2d_render_cb( ByteSlice::new(&job.commands[..]), descriptor.format, &descriptor.rect, @@ -590,27 +589,18 @@ fn rasterize_blob(job: Job) -> (BlobImageRequest, BlobImageResult) { dirty_rect.as_ref(), MutByteSlice::new(output.as_mut_slice()), ) { - BlobRenderStatus::Ok => { - // We want the dirty rect local to the tile rather than the whole image. - // TODO(nical): move that up and avoid recomputing the tile bounds in the callback - let local_dirty_rect = job.dirty_rect.to_subrect_of(&descriptor.rect); - let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into(); - let rasterized_rect = tx.transform_rect(&local_dirty_rect); + // We want the dirty rect local to the tile rather than the whole image. + // TODO(nical): move that up and avoid recomupting the tile bounds in the callback + let dirty_rect = job.dirty_rect.to_subrect_of(&descriptor.rect); + let tx: BlobToDeviceTranslation = (-descriptor.rect.origin.to_vector()).into(); + let rasterized_rect = tx.transform_rect(&dirty_rect); - Ok(RasterizedBlobImage { - rasterized_rect, - data: Some(Arc::new(output)), - }) - } - BlobRenderStatus::Empty => { - Ok(RasterizedBlobImage { - rasterized_rect: DeviceIntRect::zero(), - data: None, - }) - } - BlobRenderStatus::Error => { - panic!("Moz2D replay problem"); - } + Ok(RasterizedBlobImage { + rasterized_rect, + data: Arc::new(output), + }) + } else { + panic!("Moz2D replay problem"); } }; diff --git a/gfx/wr/examples/blob.rs b/gfx/wr/examples/blob.rs index cfb472bd1d49..b82efc97f36d 100644 --- a/gfx/wr/examples/blob.rs +++ b/gfx/wr/examples/blob.rs @@ -106,7 +106,7 @@ fn render_blob( } Ok(api::RasterizedBlobImage { - data: Some(Arc::new(texels)), + data: Arc::new(texels), rasterized_rect: size2(w, h).into(), }) } diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs index eb93f6d74aba..d3688c95c8a7 100644 --- a/gfx/wr/webrender/src/clip.rs +++ b/gfx/wr/webrender/src/clip.rs @@ -403,26 +403,21 @@ impl ClipNodeInfo { tile_size as i32, ); for tile in tiles { - let mut render = true; if request_resources { - render = resource_cache.request_image( + resource_cache.request_image( request.with_tile(tile.offset), gpu_cache, - ).should_render(); - } - if render { - mask_tiles.push(VisibleMaskImageTile { - tile_offset: tile.offset, - tile_rect: tile.rect, - }); + ); } + mask_tiles.push(VisibleMaskImageTile { + tile_offset: tile.offset, + tile_rect: tile.rect, + }); } } visible_tiles = Some(mask_tiles); } else if request_resources { - if resource_cache.request_image(request, gpu_cache).should_skip() { - return None; - } + resource_cache.request_image(request, gpu_cache); } } else { // If the supplied image key doesn't exist in the resource cache, diff --git a/gfx/wr/webrender/src/prim_store/borders.rs b/gfx/wr/webrender/src/prim_store/borders.rs index 113cd3101066..10ecd86ba6f5 100644 --- a/gfx/wr/webrender/src/prim_store/borders.rs +++ b/gfx/wr/webrender/src/prim_store/borders.rs @@ -17,7 +17,7 @@ use crate::prim_store::{ PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData, PrimitiveStore, InternablePrimitive, }; -use crate::resource_cache::{ImageRequest, ResourceCache, ImageRequestStatus}; +use crate::resource_cache::{ImageRequest, ResourceCache}; use crate::storage; #[cfg_attr(feature = "capture", derive(Serialize))] @@ -260,11 +260,11 @@ impl ImageBorderData { &mut self, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, - ) -> ImageRequestStatus { + ) { resource_cache.request_image( self.request, gpu_cache, - ) + ); } fn write_prim_gpu_blocks( diff --git a/gfx/wr/webrender/src/prim_store/image.rs b/gfx/wr/webrender/src/prim_store/image.rs index 81de81563fc8..29563838eefd 100644 --- a/gfx/wr/webrender/src/prim_store/image.rs +++ b/gfx/wr/webrender/src/prim_store/image.rs @@ -24,7 +24,7 @@ use crate::render_task::{BlitSource, RenderTask}; use crate::render_task_cache::{ RenderTaskCacheEntryHandle, RenderTaskCacheKey, RenderTaskCacheKeyKind }; -use crate::resource_cache::{ImageRequest, ResourceCache, ImageRequestStatus}; +use crate::resource_cache::{ImageRequest, ResourceCache}; use crate::util::pack_as_float; #[derive(Debug)] @@ -457,11 +457,11 @@ impl YuvImageData { &mut self, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, - ) -> ImageRequestStatus { + ) { let channel_num = self.format.get_plane_num(); debug_assert!(channel_num <= 3); for channel in 0 .. channel_num { - let status = resource_cache.request_image( + resource_cache.request_image( ImageRequest { key: self.yuv_key[channel], rendering: self.image_rendering, @@ -469,13 +469,7 @@ impl YuvImageData { }, gpu_cache, ); - - if status != ImageRequestStatus::Requested { - return status; - } } - - ImageRequestStatus::Requested } pub fn write_prim_gpu_blocks(&self, request: &mut GpuDataRequest) { diff --git a/gfx/wr/webrender/src/prim_store/mod.rs b/gfx/wr/webrender/src/prim_store/mod.rs index cf09fd49c405..585967089b34 100644 --- a/gfx/wr/webrender/src/prim_store/mod.rs +++ b/gfx/wr/webrender/src/prim_store/mod.rs @@ -2364,12 +2364,11 @@ impl PrimitiveStore { match image_properties { Some(ImageProperties { tiling: None, .. }) => { - if frame_state.resource_cache.request_image( + + frame_state.resource_cache.request_image( request, frame_state.gpu_cache, - ).should_skip() { - prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID; - } + ); } Some(ImageProperties { tiling: Some(tile_size), visible_rect, .. }) => { image_instance.visible_tiles.clear(); @@ -2434,17 +2433,17 @@ impl PrimitiveStore { ); for tile in tiles { - if frame_state.resource_cache.request_image( + frame_state.resource_cache.request_image( request.with_tile(tile.offset), frame_state.gpu_cache, - ).should_render() { - image_instance.visible_tiles.push(VisibleImageTile { - tile_offset: tile.offset, - edge_flags: tile.edge_flags & edge_flags, - local_rect: tile.rect, - local_clip_rect: tight_clip_rect, - }); - } + ); + + image_instance.visible_tiles.push(VisibleImageTile { + tile_offset: tile.offset, + edge_flags: tile.edge_flags & edge_flags, + local_rect: tile.rect, + local_clip_rect: tight_clip_rect, + }); } } @@ -2458,21 +2457,17 @@ impl PrimitiveStore { } PrimitiveInstanceKind::ImageBorder { data_handle, .. } => { let prim_data = &mut frame_state.data_stores.image_border[data_handle]; - if prim_data.kind.request_resources( + prim_data.kind.request_resources( frame_state.resource_cache, frame_state.gpu_cache, - ).should_skip() { - prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID; - } + ); } PrimitiveInstanceKind::YuvImage { data_handle, .. } => { let prim_data = &mut frame_state.data_stores.yuv_image[data_handle]; - if prim_data.kind.request_resources( + prim_data.kind.request_resources( frame_state.resource_cache, frame_state.gpu_cache, - ).should_skip() { - prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID; - } + ); } _ => {} } diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs index b7a50cbf8823..881d8e875df2 100644 --- a/gfx/wr/webrender/src/resource_cache.rs +++ b/gfx/wr/webrender/src/resource_cache.rs @@ -101,8 +101,6 @@ pub enum CachedImageData { /// An image owned by the embedding, and referenced by WebRender. This may /// take the form of a texture or a heap-allocated buffer. External(ExternalImageData), - /// The image data is only transparent pixels, we can skip rendering it. - Empty, } impl From for CachedImageData { @@ -133,9 +131,8 @@ impl CachedImageData { ExternalImageType::TextureHandle(_) => false, ExternalImageType::Buffer => true, }, - CachedImageData::Blob - | CachedImageData::Raw(_) - | CachedImageData::Empty => true, + CachedImageData::Blob => true, + CachedImageData::Raw(_) => true, } } } @@ -226,7 +223,6 @@ struct CachedImageInfo { texture_cache_handle: TextureCacheHandle, dirty_rect: ImageDirtyRect, manual_eviction: bool, - is_fully_transparent: bool } impl CachedImageInfo { @@ -460,27 +456,6 @@ pub struct AsyncBlobImageInfo { pub clear_requests: Vec, } -#[must_use] -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum ImageRequestStatus { - Requested, - FullyTransparent, - Error, -} - -impl ImageRequestStatus { - pub fn should_render(self) -> bool { - match self { - Self::Requested => true, - _ => false, - } - } - - pub fn should_skip(self) -> bool { - !self.should_render() - } -} - /// High-level container for resources managed by the `RenderBackend`. /// /// This includes a variety of things, including images, fonts, and glyphs, @@ -574,9 +549,7 @@ impl ResourceCache { fn should_tile(limit: i32, descriptor: &ImageDescriptor, data: &CachedImageData) -> bool { let size_check = descriptor.size.width > limit || descriptor.size.height > limit; match *data { - CachedImageData::Raw(_) - | CachedImageData::Blob - | CachedImageData::Empty => size_check, + CachedImageData::Raw(_) | CachedImageData::Blob => size_check, CachedImageData::External(info) => { // External handles already represent existing textures so it does // not make sense to tile them into smaller ones. @@ -810,20 +783,6 @@ impl ResourceCache { || { RasterizedBlob::Tiled(FastHashMap::default()) } ); - if data.data.is_none() { - let entry = ensure_cached_image_entry( - &mut self.cached_images, - ImageRequest { - key: request.key.as_image(), - tile: request.tile, - rendering: ImageRendering::Auto, - }, - ); - - // Mark the cached image as empty to skip rendering it later. - entry.is_fully_transparent = true; - } - if let Some(tile) = request.tile { if let RasterizedBlob::NonTiled(..) = *image { *image = RasterizedBlob::Tiled(FastHashMap::default()); @@ -1151,13 +1110,11 @@ impl ResourceCache { self.active_image_keys.insert(image_key); } - // Returns false if the image should not be rendered, either due to an error, - // or if the image only contains fully transparent pixels. pub fn request_image( &mut self, request: ImageRequest, gpu_cache: &mut GpuCache, - ) -> ImageRequestStatus { + ) { debug_assert_eq!(self.state, State::AddResources); let template = match self.resources.image_templates.get(request.key) { @@ -1165,13 +1122,13 @@ impl ResourceCache { None => { warn!("ERROR: Trying to render deleted / non-existent key"); debug!("key={:?}", request.key); - return ImageRequestStatus::Error; + return } }; // Images that don't use the texture cache can early out. if !template.data.uses_texture_cache() { - return ImageRequestStatus::Requested; + return; } let side_size = @@ -1182,27 +1139,76 @@ impl ResourceCache { warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!", template.descriptor.size.width, template.descriptor.size.height, template.tiling.unwrap_or(0)); self.cached_images.insert(request.key, ImageResult::Err(ImageCacheError::OverLimitSize)); - return ImageRequestStatus::Error; + return; } - let entry = ensure_cached_image_entry(&mut self.cached_images, request); + let storage = match self.cached_images.entry(request.key) { + Occupied(e) => { + // We might have an existing untiled entry, and need to insert + // a second entry. In such cases we need to move the old entry + // out first, replacing it with a dummy entry, and then creating + // the tiled/multi-entry variant. + let entry = e.into_mut(); + if !request.is_untiled_auto() { + let untiled_entry = match entry { + &mut ImageResult::UntiledAuto(ref mut entry) => { + Some(mem::replace(entry, CachedImageInfo { + texture_cache_handle: TextureCacheHandle::invalid(), + dirty_rect: DirtyRect::All, + manual_eviction: false, + })) + } + _ => None + }; - let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache); - - - if entry.is_fully_transparent { - // Empty tile, skip rendering. - return ImageRequestStatus::FullyTransparent; - } + if let Some(untiled_entry) = untiled_entry { + let mut entries = ResourceClassCache::new(); + let untiled_key = CachedImageKey { + rendering: ImageRendering::Auto, + tile: None, + }; + entries.insert(untiled_key, untiled_entry); + *entry = ImageResult::Multi(entries); + } + } + entry + } + Vacant(entry) => { + entry.insert(if request.is_untiled_auto() { + ImageResult::UntiledAuto(CachedImageInfo { + texture_cache_handle: TextureCacheHandle::invalid(), + dirty_rect: DirtyRect::All, + manual_eviction: false, + }) + } else { + ImageResult::Multi(ResourceClassCache::new()) + }) + } + }; // If this image exists in the texture cache, *and* the dirty rect // in the cache is empty, then it is valid to use as-is. + let entry = match *storage { + ImageResult::UntiledAuto(ref mut entry) => entry, + ImageResult::Multi(ref mut entries) => { + entries.entry(request.into()) + .or_insert(CachedImageInfo { + texture_cache_handle: TextureCacheHandle::invalid(), + dirty_rect: DirtyRect::All, + manual_eviction: false, + }) + }, + ImageResult::Err(_) => panic!("Errors should already have been handled"), + }; + + let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache); + if !needs_upload && entry.dirty_rect.is_empty() { - return ImageRequestStatus::Requested; + return } if !self.pending_image_requests.insert(request) { - return ImageRequestStatus::Requested; + return } // By this point, we know that the image request is considered dirty, and will @@ -1250,8 +1256,6 @@ impl ResourceCache { ); } } - - return ImageRequestStatus::Requested; } pub fn create_blob_scene_builder_requests( @@ -1579,14 +1583,6 @@ impl ResourceCache { pub fn get_cached_image(&self, request: ImageRequest) -> Result { debug_assert_eq!(self.state, State::QueryResources); let image_info = self.get_image_info(request)?; - if image_info.is_fully_transparent { - // TODO(nical): Ideally we should have discarded the primitive already. - // If a blob image was not rasterized before frame building we end up - // knowing whether its content is transparent after the culling phase - // so we have to check again here. The plan is to remove the late blob - // rasterization code, after which we can simplify this. - return Err(()) - } Ok(self.get_texture_cache_item(&image_info.texture_cache_handle)) } @@ -1624,9 +1620,7 @@ impl ResourceCache { ExternalImageType::Buffer => None, }, // raw and blob image are all using resource_cache. - CachedImageData::Raw(..) - | CachedImageData::Blob - | CachedImageData::Empty => None, + CachedImageData::Raw(..) | CachedImageData::Blob => None, }; ImageProperties { @@ -1733,9 +1727,7 @@ impl ResourceCache { let mut updates: SmallVec<[(CachedImageData, Option); 1]> = SmallVec::new(); match image_template.data { - CachedImageData::Raw(..) - | CachedImageData::External(..) - | CachedImageData::Empty => { + CachedImageData::Raw(..) | CachedImageData::External(..) => { // Safe to clone here since the Raw image data is an // Arc, and the external image data is small. updates.push((image_template.data.clone(), None)); @@ -1746,29 +1738,17 @@ impl ResourceCache { match (blob_image, request.tile) { (RasterizedBlob::Tiled(ref tiles), Some(tile)) => { let img = &tiles[&tile]; - updates.push( - if let Some(ref data) = img.data { - ( - CachedImageData::Raw(Arc::clone(data)), - Some(img.rasterized_rect) - ) - } else { - (CachedImageData::Empty, None) - } - ); + updates.push(( + CachedImageData::Raw(Arc::clone(&img.data)), + Some(img.rasterized_rect) + )); } (RasterizedBlob::NonTiled(ref mut queue), None) => { for img in queue.drain(..) { - updates.push( - if let Some(data) = img.data { - ( - CachedImageData::Raw(data), - Some(img.rasterized_rect) - ) - } else { - (CachedImageData::Empty, None) - } - ); + updates.push(( + CachedImageData::Raw(img.data), + Some(img.rasterized_rect) + )); } } _ => { @@ -1946,9 +1926,7 @@ impl ResourceCache { for (_, image) in self.resources.image_templates.images.iter() { report.images += match image.data { CachedImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) }, - CachedImageData::Blob - | CachedImageData::External(..) - | CachedImageData::Empty => 0, + CachedImageData::Blob | CachedImageData::External(..) => 0, } } @@ -1993,72 +1971,6 @@ impl Drop for ResourceCache { } } - -fn ensure_cached_image_entry(cached_images: &mut ImageCache, request: ImageRequest) -> &mut CachedImageInfo { - let storage = match cached_images.entry(request.key) { - Occupied(e) => { - // We might have an existing untiled entry, and need to insert - // a second entry. In such cases we need to move the old entry - // out first, replacing it with a dummy entry, and then creating - // the tiled/multi-entry variant. - let entry = e.into_mut(); - if !request.is_untiled_auto() { - let untiled_entry = match entry { - &mut ImageResult::UntiledAuto(ref mut entry) => { - Some(mem::replace(entry, CachedImageInfo { - texture_cache_handle: TextureCacheHandle::invalid(), - dirty_rect: DirtyRect::All, - manual_eviction: false, - is_fully_transparent: false, - })) - } - _ => None - }; - - if let Some(untiled_entry) = untiled_entry { - let mut entries = ResourceClassCache::new(); - let untiled_key = CachedImageKey { - rendering: ImageRendering::Auto, - tile: None, - }; - entries.insert(untiled_key, untiled_entry); - *entry = ImageResult::Multi(entries); - } - } - entry - } - Vacant(entry) => { - entry.insert( - if request.is_untiled_auto() { - ImageResult::UntiledAuto(CachedImageInfo { - texture_cache_handle: TextureCacheHandle::invalid(), - dirty_rect: DirtyRect::All, - manual_eviction: false, - is_fully_transparent: false, - }) - } else { - ImageResult::Multi(ResourceClassCache::new()) - } - ) - } - }; - - match *storage { - ImageResult::UntiledAuto(ref mut entry) => entry, - ImageResult::Multi(ref mut entries) => { - entries.entry(request.into()) - .or_insert(CachedImageInfo { - texture_cache_handle: TextureCacheHandle::invalid(), - dirty_rect: DirtyRect::All, - manual_eviction: false, - is_fully_transparent: false, - }) - }, - ImageResult::Err(_) => panic!("Errors should already have been handled"), - } -} - - pub fn get_blob_tiling( tiling: Option, size: DeviceIntSize, @@ -2241,7 +2153,7 @@ impl ResourceCache { warn!("Tiled blob images aren't supported yet"); RasterizedBlobImage { rasterized_rect: desc.size.into(), - data: None, + data: Arc::new(vec![0; desc.compute_total_size() as usize]) } } else { let blob_handler = self.blob_image_handler.as_mut().unwrap(); @@ -2251,26 +2163,25 @@ impl ResourceCache { result.expect("Blob rasterization failed") }; - num_blobs += 1; assert_eq!(result.rasterized_rect.size, desc.size); - if let Some(ref data) = result.data { - assert_eq!(data.len(), desc.compute_total_size() as usize); - #[cfg(feature = "png")] - CaptureConfig::save_png( - root.join(format!("blobs/{}.png", num_blobs)), - desc.size, - desc.format, - data, - ); - let file_name = format!("{}.raw", num_blobs); - let short_path = format!("blobs/{}", file_name); - let full_path = path_blobs.clone().join(&file_name); - fs::File::create(full_path) - .expect(&format!("Unable to create {}", short_path)) - .write_all(data) - .unwrap(); - other_paths.insert(key, short_path); - } + assert_eq!(result.data.len(), desc.compute_total_size() as usize); + + num_blobs += 1; + #[cfg(feature = "png")] + CaptureConfig::save_png( + root.join(format!("blobs/{}.png", num_blobs)), + desc.size, + desc.format, + &result.data, + ); + let file_name = format!("{}.raw", num_blobs); + let short_path = format!("blobs/{}", file_name); + let full_path = path_blobs.clone().join(&file_name); + fs::File::create(full_path) + .expect(&format!("Unable to create {}", short_path)) + .write_all(&result.data) + .unwrap(); + other_paths.insert(key, short_path); } CachedImageData::External(ref ext) => { let short_path = format!("externals/{}", external_images.len() + 1); @@ -2281,7 +2192,6 @@ impl ResourceCache { external: ext.clone(), }); } - CachedImageData::Empty => {} } } diff --git a/gfx/wr/webrender/src/texture_cache.rs b/gfx/wr/webrender/src/texture_cache.rs index 6108864b688f..f55fd93c86f6 100644 --- a/gfx/wr/webrender/src/texture_cache.rs +++ b/gfx/wr/webrender/src/texture_cache.rs @@ -913,12 +913,6 @@ impl TextureCache { ) { debug_assert!(self.now.is_valid()); - if let Some(CachedImageData::Empty) = data { - self.mark_unused(handle); - *handle = TextureCacheHandle::invalid(); - return; - } - // Determine if we need to allocate texture cache memory // for this item. We need to reallocate if any of the following // is true: @@ -1852,9 +1846,6 @@ impl TextureCacheUpdate { CachedImageData::Blob => { panic!("The vector image should have been rasterized."); } - CachedImageData::Empty => { - panic!("The entry should have been cleared instead."); - } CachedImageData::External(ext_image) => match ext_image.image_type { ExternalImageType::TextureHandle(_) => { panic!("External texture handle should not go through texture_cache."); diff --git a/gfx/wr/webrender_api/src/image.rs b/gfx/wr/webrender_api/src/image.rs index 7d9f199ae0f4..86d4f1d7baea 100644 --- a/gfx/wr/webrender_api/src/image.rs +++ b/gfx/wr/webrender_api/src/image.rs @@ -490,10 +490,7 @@ pub struct RasterizedBlobImage { /// image or tile. pub rasterized_rect: DeviceIntRect, /// Backing store. The format is stored out of band in `BlobImageDescriptor`. - /// - /// None means the image only has fully transparent content. We can skip storing - /// and rendering it. - pub data: Option>>, + pub data: Arc>, } /// Error code for when blob rasterization failed. diff --git a/gfx/wr/wrench/src/blob.rs b/gfx/wr/wrench/src/blob.rs index 1f5be0fdfdda..23b5ce9f84dc 100644 --- a/gfx/wr/wrench/src/blob.rs +++ b/gfx/wr/wrench/src/blob.rs @@ -98,7 +98,7 @@ fn render_blob( } Ok(RasterizedBlobImage { - data: Some(Arc::new(texels)), + data: Arc::new(texels), rasterized_rect, }) }