Bug 1946361 - Fallback to a transparent image for missing snapshots. r=gw
A followup patch will add debug prefs to panic or use pink instead of transparent for the fallback image. Differential Revision: https://phabricator.services.mozilla.com/D237007
This commit is contained in:
@@ -93,5 +93,5 @@ pub fn resolve_cached_render_task(
|
|||||||
let rt_cache_entry = resource_cache
|
let rt_cache_entry = resource_cache
|
||||||
.get_cached_render_task(&handle);
|
.get_cached_render_task(&handle);
|
||||||
|
|
||||||
resource_cache.get_texture_cache_item(&rt_cache_entry.handle)
|
resource_cache.get_texture_cache_item(&rt_cache_entry.handle).unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -501,6 +501,21 @@ pub struct ResourceCache {
|
|||||||
|
|
||||||
/// A pool of render targets for use by the render task graph
|
/// A pool of render targets for use by the render task graph
|
||||||
render_target_pool: Vec<RenderTarget>,
|
render_target_pool: Vec<RenderTarget>,
|
||||||
|
|
||||||
|
/// An empty (1x1 transparent) image used when a stacking context snapshot
|
||||||
|
/// is missing.
|
||||||
|
///
|
||||||
|
/// For now it acts as a catch-all solution for cases where WebRender fails
|
||||||
|
/// to produce a texture cache item for a snapshotted tacking context.
|
||||||
|
/// These cases include:
|
||||||
|
/// - Empty stacking contexts.
|
||||||
|
/// - Stacking contexts that are more aggressively culled out than they
|
||||||
|
/// should, for example when they are in a perspective transform that
|
||||||
|
/// cannot be projected to screen space.
|
||||||
|
/// - Likely other cases we have not found yet.
|
||||||
|
/// Over time it would be better to handle each of these cases explicitly
|
||||||
|
/// and make it a hard error to fail to snapshot a stacking context.
|
||||||
|
fallback_handle: TextureCacheHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourceCache {
|
impl ResourceCache {
|
||||||
@@ -538,6 +553,7 @@ impl ResourceCache {
|
|||||||
image_templates_memory: 0,
|
image_templates_memory: 0,
|
||||||
font_templates_memory: 0,
|
font_templates_memory: 0,
|
||||||
render_target_pool: Vec::new(),
|
render_target_pool: Vec::new(),
|
||||||
|
fallback_handle: TextureCacheHandle::invalid(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1342,7 +1358,19 @@ impl ResourceCache {
|
|||||||
pub fn get_cached_image(&self, request: ImageRequest) -> Result<CacheItem, ()> {
|
pub fn get_cached_image(&self, request: ImageRequest) -> Result<CacheItem, ()> {
|
||||||
debug_assert_eq!(self.state, State::QueryResources);
|
debug_assert_eq!(self.state, State::QueryResources);
|
||||||
let image_info = self.get_image_info(request)?;
|
let image_info = self.get_image_info(request)?;
|
||||||
Ok(self.get_texture_cache_item(&image_info.texture_cache_handle))
|
|
||||||
|
if let Ok(item) = self.get_texture_cache_item(&image_info.texture_cache_handle) {
|
||||||
|
// Common path.
|
||||||
|
return Ok(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.resources.image_templates
|
||||||
|
.get(request.key)
|
||||||
|
.map_or(false, |img| img.data.is_snapshot()) {
|
||||||
|
return self.get_texture_cache_item(&self.fallback_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
panic!("Requested image missing from the texture cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cached_render_task(
|
pub fn get_cached_render_task(
|
||||||
@@ -1364,8 +1392,12 @@ impl ResourceCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_texture_cache_item(&self, handle: &TextureCacheHandle) -> CacheItem {
|
pub fn get_texture_cache_item(&self, handle: &TextureCacheHandle) -> Result<CacheItem, ()> {
|
||||||
self.texture_cache.get(handle)
|
if let Some(item) = self.texture_cache.try_get(handle) {
|
||||||
|
return Ok(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image_properties(&self, image_key: ImageKey) -> Option<ImageProperties> {
|
pub fn get_image_properties(&self, image_key: ImageKey) -> Option<ImageProperties> {
|
||||||
@@ -1480,6 +1512,29 @@ impl ResourceCache {
|
|||||||
|
|
||||||
fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
|
fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
|
||||||
profile_scope!("update_texture_cache");
|
profile_scope!("update_texture_cache");
|
||||||
|
|
||||||
|
if self.fallback_handle == TextureCacheHandle::invalid() {
|
||||||
|
self.texture_cache.update(
|
||||||
|
&mut self.fallback_handle,
|
||||||
|
ImageDescriptor {
|
||||||
|
size: size2(1, 1),
|
||||||
|
stride: None,
|
||||||
|
format: ImageFormat::BGRA8,
|
||||||
|
flags: ImageDescriptorFlags::empty(),
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
TextureFilter::Linear,
|
||||||
|
Some(CachedImageData::Raw(Arc::new(vec![0, 0, 0, 0]))),
|
||||||
|
[0.0; 4],
|
||||||
|
DirtyRect::All,
|
||||||
|
gpu_cache,
|
||||||
|
None,
|
||||||
|
UvRectKind::Rect,
|
||||||
|
Eviction::Manual,
|
||||||
|
TargetShader::Default,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for request in self.pending_image_requests.drain() {
|
for request in self.pending_image_requests.drain() {
|
||||||
let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
|
let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
|
||||||
debug_assert!(image_template.data.uses_texture_cache());
|
debug_assert!(image_template.data.uses_texture_cache());
|
||||||
|
|||||||
@@ -1016,6 +1016,36 @@ impl TextureCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_get(&self, handle: &TextureCacheHandle) -> Option<CacheItem> {
|
||||||
|
let (texture_id, uv_rect, swizzle, uv_rect_handle, user_data) = self.try_get_cache_location(handle)?;
|
||||||
|
Some(CacheItem {
|
||||||
|
uv_rect_handle,
|
||||||
|
texture_id: TextureSource::TextureCache(
|
||||||
|
texture_id,
|
||||||
|
swizzle,
|
||||||
|
),
|
||||||
|
uv_rect,
|
||||||
|
user_data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_get_cache_location(
|
||||||
|
&self,
|
||||||
|
handle: &TextureCacheHandle,
|
||||||
|
) -> Option<(CacheTextureId, DeviceIntRect, Swizzle, GpuCacheHandle, [f32; 4])> {
|
||||||
|
let entry = self.get_entry_opt(handle)?;
|
||||||
|
|
||||||
|
debug_assert_eq!(entry.last_access, self.now);
|
||||||
|
let origin = entry.details.describe();
|
||||||
|
Some((
|
||||||
|
entry.texture_id,
|
||||||
|
DeviceIntRect::from_origin_and_size(origin, entry.size),
|
||||||
|
entry.swizzle,
|
||||||
|
entry.uv_rect_handle,
|
||||||
|
entry.user_data,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// A more detailed version of get(). This allows access to the actual
|
/// A more detailed version of get(). This allows access to the actual
|
||||||
/// device rect of the cache allocation.
|
/// device rect of the cache allocation.
|
||||||
///
|
///
|
||||||
|
|||||||
7
gfx/wr/wrench/reftests/image/empty.yaml
Normal file
7
gfx/wr/wrench/reftests/image/empty.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
root:
|
||||||
|
items:
|
||||||
|
-
|
||||||
|
bounds: [200, 200, 1000, 1000]
|
||||||
|
type: "stacking-context"
|
||||||
|
items:
|
||||||
@@ -26,3 +26,9 @@ fuzzy(1,160000) == image-filter-stretch-tile.yaml green-alpha-ref.yaml
|
|||||||
== snapshot-filters-02.yaml snapshot-filters-02-ref.yaml
|
== snapshot-filters-02.yaml snapshot-filters-02-ref.yaml
|
||||||
fuzzy(3,3000) == snapshot-shadow.yaml snapshot-shadow-ref.yaml
|
fuzzy(3,3000) == snapshot-shadow.yaml snapshot-shadow-ref.yaml
|
||||||
== snapshot-multiframe.yaml snapshot-multiframe-ref.yaml
|
== snapshot-multiframe.yaml snapshot-multiframe-ref.yaml
|
||||||
|
== snapshot-empty.yaml empty.yaml
|
||||||
|
# TODO: At the moment snapshot-perspective-01.yaml renders incorrectly, so the
|
||||||
|
# reftest acts more as a crash test. When bug 1941577 is fixed the reftest
|
||||||
|
# reference should be updated to reflect that something needs to be rendered
|
||||||
|
# instead of leaving the snapshot empty.
|
||||||
|
== snapshot-perspective-01.yaml empty.yaml
|
||||||
|
|||||||
17
gfx/wr/wrench/reftests/image/snapshot-empty.yaml
Normal file
17
gfx/wr/wrench/reftests/image/snapshot-empty.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
root:
|
||||||
|
items:
|
||||||
|
-
|
||||||
|
bounds: [200, 200, 1000, 1000]
|
||||||
|
type: "stacking-context"
|
||||||
|
perspective: 256
|
||||||
|
items:
|
||||||
|
-
|
||||||
|
bounds: [0, 0, 100, 100]
|
||||||
|
type: "stacking-context"
|
||||||
|
snapshot:
|
||||||
|
name: "snap0"
|
||||||
|
area: [0, 0, 100, 100]
|
||||||
|
items:
|
||||||
|
- image: snapshot(snap0)
|
||||||
|
bounds: [10, 10, 200, 200]
|
||||||
33
gfx/wr/wrench/reftests/image/snapshot-perspective-01.yaml
Normal file
33
gfx/wr/wrench/reftests/image/snapshot-perspective-01.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
root:
|
||||||
|
items:
|
||||||
|
-
|
||||||
|
bounds: [200, 200, 1000, 1000]
|
||||||
|
type: "stacking-context"
|
||||||
|
perspective: 256
|
||||||
|
items:
|
||||||
|
-
|
||||||
|
bounds: [128, 128, 256, 256]
|
||||||
|
type: "stacking-context"
|
||||||
|
transform: rotate-x(-60) rotate-y(-120)
|
||||||
|
snapshot:
|
||||||
|
name: "snap0"
|
||||||
|
area: [0, 0, 100, 200]
|
||||||
|
items:
|
||||||
|
- type: clip
|
||||||
|
id: 101
|
||||||
|
complex:
|
||||||
|
- rect: [0, 0, 100, 200]
|
||||||
|
radius: [32, 32]
|
||||||
|
- type: clip-chain
|
||||||
|
id: 201
|
||||||
|
clips: [101]
|
||||||
|
-
|
||||||
|
bounds: [0, 0, 100, 200]
|
||||||
|
type: rect
|
||||||
|
color: blue
|
||||||
|
clip-chain: 201
|
||||||
|
- image: snapshot(snap0)
|
||||||
|
bounds: [300, 0, 100, 200]
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user