diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index a9adf4906593..c2e1a08c30bb 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -1634,10 +1634,14 @@ pub struct TileCacheParams { pub shared_clip_leaf_id: Option, // Virtual surface sizes are always square, so this represents both the width and height pub virtual_surface_size: i32, - // The number of compositor surfaces that are being requested for this tile cache. + // The number of Image surfaces that are being requested for this tile cache. // This is only a suggestion - the tile cache will clamp this as a reasonable number // and only promote a limited number of surfaces. - pub overlay_surface_count: usize, + pub image_surface_count: usize, + // The number of YuvImage surfaces that are being requested for this tile cache. + // This is only a suggestion - the tile cache will clamp this as a reasonable number + // and only promote a limited number of surfaces. + pub yuv_image_surface_count: usize, } /// Defines which sub-slice (effectively a z-index) a primitive exists on within @@ -1852,6 +1856,11 @@ pub struct TileCacheInstance { pub underlays: Vec, /// "Region" (actually a spanning rect) containing all overlay promoted surfaces pub overlay_region: PictureRect, + /// The number YuvImage prims in this cache, provided in our TileCacheParams. + pub yuv_images_count: usize, + /// The remaining number of YuvImage prims we will see this frame. We prioritize + /// promoting these before promoting any Image prims. + pub yuv_images_remaining: usize, } enum SurfacePromotionResult { @@ -1863,7 +1872,7 @@ impl TileCacheInstance { pub fn new(params: TileCacheParams) -> Self { // Determine how many sub-slices we need. Clamp to an arbitrary limit to ensure // we don't create a huge number of OS compositor tiles and sub-slices. - let sub_slice_count = params.overlay_surface_count.min(MAX_COMPOSITOR_SURFACES) + 1; + let sub_slice_count = (params.image_surface_count + params.yuv_image_surface_count).min(MAX_COMPOSITOR_SURFACES) + 1; let mut sub_slices = Vec::with_capacity(sub_slice_count); for _ in 0 .. sub_slice_count { @@ -1916,6 +1925,8 @@ impl TileCacheInstance { backdrop_surface: None, underlays: Vec::new(), overlay_region: PictureRect::zero(), + yuv_images_count: params.yuv_image_surface_count, + yuv_images_remaining: 0, } } @@ -1956,7 +1967,7 @@ impl TileCacheInstance { // Determine how many sub-slices we need, based on how many compositor surface prims are // in the supplied primitive list. - let required_sub_slice_count = params.overlay_surface_count.min(MAX_COMPOSITOR_SURFACES) + 1; + let required_sub_slice_count = (params.image_surface_count + params.yuv_image_surface_count).min(MAX_COMPOSITOR_SURFACES) + 1; if self.sub_slices.len() != required_sub_slice_count { self.tile_rect = TileRect::zero(); @@ -1997,6 +2008,9 @@ impl TileCacheInstance { // Since the slice flags may have changed, ensure we re-evaluate the // appropriate tile size for this cache next update. self.frames_until_size_eval = 0; + + // Update the number of YuvImage prims we have in the scene. + self.yuv_images_count = params.yuv_image_surface_count; } /// Destroy any manually managed resources before this picture cache is @@ -2060,6 +2074,7 @@ impl TileCacheInstance { self.deferred_dirty_tests.clear(); self.underlays.clear(); self.overlay_region = PictureRect::zero(); + self.yuv_images_remaining = self.yuv_images_count; for sub_slice in &mut self.sub_slices { sub_slice.reset(); @@ -3151,18 +3166,23 @@ impl TileCacheInstance { } let mut promote_to_surface = false; - match self.can_promote_to_surface(image_key.common.flags, - prim_clip_chain, - prim_spatial_node_index, - is_root_tile_cache, - sub_slice_index, - CompositorSurfaceKind::Overlay, - pic_coverage_rect, - frame_context) { - SurfacePromotionResult::Failed => { - } - SurfacePromotionResult::Success => { - promote_to_surface = true; + + // Only consider promoting Images if all of our YuvImages have been + // processed (whether they were promoted or not). + if self.yuv_images_remaining == 0 { + match self.can_promote_to_surface(image_key.common.flags, + prim_clip_chain, + prim_spatial_node_index, + is_root_tile_cache, + sub_slice_index, + CompositorSurfaceKind::Overlay, + pic_coverage_rect, + frame_context) { + SurfacePromotionResult::Failed => { + } + SurfacePromotionResult::Success => { + promote_to_surface = true; + } } } @@ -3211,6 +3231,15 @@ impl TileCacheInstance { PrimitiveInstanceKind::YuvImage { data_handle, ref mut compositor_surface_kind, .. } => { let prim_data = &data_stores.yuv_image[data_handle]; + // Note if this is one of the YuvImages we were considering for + // surface promotion. We only care for primitives that were added + // to us, indicated by is_root_tile_cache. Those are the only ones + // that were added to the TileCacheParams that configured the + // current scene. + if is_root_tile_cache && prim_data.common.flags.contains(PrimitiveFlags::PREFER_COMPOSITOR_SURFACE) { + self.yuv_images_remaining -= 1; + } + let clip_on_top = prim_clip_chain.needs_mask; let prefer_underlay = clip_on_top || !cfg!(target_os = "macos"); let promotion_attempts = if prefer_underlay { @@ -3405,10 +3434,10 @@ impl TileCacheInstance { }; // Calculate the screen rect in local space. When we calculate backdrops, we - // care only that they cover the visible rect, and don't have any overlapping - // prims in the visible rect. - let visible_local_rect = self.local_rect.intersection(&self.screen_rect_in_pic_space).unwrap_or_default(); - if pic_coverage_rect.intersects(&visible_local_rect) { + // care only that they cover the visible rect (based off the local clip), and + // don't have any overlapping prims in the visible rect. + let visible_local_clip_rect = self.local_clip_rect.intersection(&self.screen_rect_in_pic_space).unwrap_or_default(); + if pic_coverage_rect.intersects(&visible_local_clip_rect) { self.found_prims_after_backdrop = true; } @@ -3498,7 +3527,7 @@ impl TileCacheInstance { } if let Some(kind) = backdrop_candidate.kind { - if backdrop_candidate.opaque_rect.contains_box(&visible_local_rect) { + if backdrop_candidate.opaque_rect.contains_box(&visible_local_clip_rect) { self.found_prims_after_backdrop = false; self.backdrop.kind = Some(kind); self.backdrop.backdrop_rect = backdrop_candidate.opaque_rect; @@ -4738,9 +4767,12 @@ pub struct PrimitiveList { /// List of primitives grouped into clusters. pub clusters: Vec, pub child_pictures: Vec, - /// The number of preferred compositor surfaces that were found when - /// adding prims to this list, which might be rendered as overlays - pub overlay_surface_count: usize, + /// The number of Image compositor surfaces that were found when + /// adding prims to this list, which might be rendered as overlays. + pub image_surface_count: usize, + /// The number of YuvImage compositor surfaces that were found when + /// adding prims to this list, which might be rendered as overlays. + pub yuv_image_surface_count: usize, pub needs_scissor_rect: bool, } @@ -4753,7 +4785,8 @@ impl PrimitiveList { PrimitiveList { clusters: Vec::new(), child_pictures: Vec::new(), - overlay_surface_count: 0, + image_surface_count: 0, + yuv_image_surface_count: 0, needs_scissor_rect: false, } } @@ -4761,7 +4794,8 @@ impl PrimitiveList { pub fn merge(&mut self, other: PrimitiveList) { self.clusters.extend(other.clusters); self.child_pictures.extend(other.child_pictures); - self.overlay_surface_count += other.overlay_surface_count; + self.image_surface_count += other.image_surface_count; + self.yuv_image_surface_count += other.yuv_image_surface_count; self.needs_scissor_rect |= other.needs_scissor_rect; } @@ -4794,7 +4828,7 @@ impl PrimitiveList { // be allocating more subslices than we actually need, but it // gives us maximum flexibility. if prim_flags.contains(PrimitiveFlags::PREFER_COMPOSITOR_SURFACE) { - self.overlay_surface_count += 1; + self.yuv_image_surface_count += 1; } } PrimitiveInstanceKind::Image { .. } => { @@ -4804,7 +4838,7 @@ impl PrimitiveList { // it's a little bit of work, as scene building doesn't have access // to the opacity state of an image key at this point. if prim_flags.contains(PrimitiveFlags::PREFER_COMPOSITOR_SURFACE) { - self.overlay_surface_count += 1; + self.image_surface_count += 1; } } _ => {} diff --git a/gfx/wr/webrender/src/tile_cache.rs b/gfx/wr/webrender/src/tile_cache.rs index d652f8c5f295..cf605d40d22b 100644 --- a/gfx/wr/webrender/src/tile_cache.rs +++ b/gfx/wr/webrender/src/tile_cache.rs @@ -618,7 +618,8 @@ fn create_tile_cache( shared_clip_node_id, shared_clip_leaf_id, virtual_surface_size: frame_builder_config.compositor_kind.get_virtual_surface_size(), - overlay_surface_count: prim_list.overlay_surface_count, + image_surface_count: prim_list.image_surface_count, + yuv_image_surface_count: prim_list.yuv_image_surface_count, }); let pic_index = prim_store.pictures.alloc().init(PicturePrimitive::new_image(