diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs index 6ba05473039a..396e80ff82da 100644 --- a/gfx/wr/webrender/src/clip.rs +++ b/gfx/wr/webrender/src/clip.rs @@ -108,7 +108,7 @@ use crate::prim_store::{ClipData, ImageMaskData, SpaceMapper, VisibleMaskImageTi use crate::prim_store::{PointKey, SizeKey, RectangleKey}; use crate::render_task_cache::to_cache_size; use crate::resource_cache::{ImageRequest, ResourceCache}; -use crate::util::{clamp_to_scale_factor, extract_inner_rect_safe, project_rect, ScaleOffset}; +use crate::util::{clamp_to_scale_factor, extract_inner_rect_safe, project_rect, ScaleOffset, VecHelper}; use euclid::approxeq::ApproxEq; use std::{iter, ops, u32}; use smallvec::SmallVec; @@ -836,6 +836,25 @@ impl ClipChainStack { } } + pub fn clear(&mut self) { + self.clips.clear(); + self.clip_counts.clear(); + self.levels.clear(); + self.levels.push(ClipChainLevel { + shared_clips: Vec::new(), + first_clip_index: 0, + initial_clip_counts_len: 0, + }); + } + + pub fn take(&mut self) -> Self { + ClipChainStack { + levels: self.levels.take(), + clips: self.clips.take(), + clip_counts: self.clip_counts.take(), + } + } + /// Push a clip chain root onto the currently active list. pub fn push_clip( &mut self, diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs index 5347b863a972..93e01ec0ef59 100644 --- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -117,6 +117,8 @@ impl FrameGlobalResources { pub struct FrameScratchBuffer { surfaces: Vec, dirty_region_stack: Vec, + surface_stack: Vec, + clip_chain_stack: ClipChainStack, } impl Default for FrameScratchBuffer { @@ -124,6 +126,8 @@ impl Default for FrameScratchBuffer { FrameScratchBuffer { surfaces: Vec::new(), dirty_region_stack: Vec::new(), + surface_stack: Vec::new(), + clip_chain_stack: ClipChainStack::new(), } } } @@ -132,6 +136,8 @@ impl FrameScratchBuffer { pub fn begin_frame(&mut self) { self.surfaces.clear(); self.dirty_region_stack.clear(); + self.surface_stack.clear(); + self.clip_chain_stack.clear(); } pub fn recycle(&mut self, recycler: &mut Recycler) { @@ -165,6 +171,10 @@ pub struct FrameVisibilityContext<'a> { } pub struct FrameVisibilityState<'a> { + pub clip_chain_stack: ClipChainStack, + /// A stack of currently active off-screen surfaces during the + /// visibility frame traversal. + pub surface_stack: Vec, pub clip_store: &'a mut ClipStore, pub resource_cache: &'a mut ResourceCache, pub gpu_cache: &'a mut GpuCache, @@ -172,12 +182,8 @@ pub struct FrameVisibilityState<'a> { pub tile_cache: Option>, pub retained_tiles: &'a mut RetainedTiles, pub data_stores: &'a mut DataStores, - pub clip_chain_stack: ClipChainStack, pub render_tasks: &'a mut RenderTaskGraph, pub composite_state: &'a mut CompositeState, - /// A stack of currently active off-screen surfaces during the - /// visibility frame traversal. - pub surface_stack: Vec, } impl<'a> FrameVisibilityState<'a> { @@ -399,6 +405,8 @@ impl FrameBuilder { }; let mut visibility_state = FrameVisibilityState { + clip_chain_stack: scratch.frame.clip_chain_stack.take(), + surface_stack: scratch.frame.surface_stack.take(), resource_cache, gpu_cache, clip_store: &mut scene.clip_store, @@ -406,12 +414,8 @@ impl FrameBuilder { tile_cache: None, retained_tiles: &mut retained_tiles, data_stores, - clip_chain_stack: ClipChainStack::new(), render_tasks, composite_state, - /// Try to avoid allocating during frame traversal - it's unlikely to have a - /// surface stack depth of > 16 in most cases. - surface_stack: Vec::with_capacity(16), }; scene.prim_store.update_visibility( @@ -448,6 +452,9 @@ impl FrameBuilder { visibility_state.resource_cache.destroy_compositor_surface(external_surface.native_surface_id) } } + + visibility_state.scratch.frame.clip_chain_stack = visibility_state.clip_chain_stack.take(); + visibility_state.scratch.frame.surface_stack = visibility_state.surface_stack.take(); } let mut frame_state = FrameBuildingState {