| author | Glenn Watson <git@intuitionlibrary.com> |
| Thu, 30 Jan 2020 09:44:45 +0000 | |
| changeset 512116 | 784fdbec47d2351b211f1fceae1d68974ea21798 |
| parent 512115 | 236b8297fd5d66bebcb478e4dffe5ad7d2376a4b |
| child 512117 | aed68d2d967db45a05cba610f7783f773864264d |
| push id | 37072 |
| push user | csabou@mozilla.com |
| push date | Thu, 30 Jan 2020 15:44:43 +0000 |
| treeherder | mozilla-central@f97c48da9cee [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | kvark |
| bugs | 1606251 |
| milestone | 74.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -1,16 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{ColorF, DebugFlags, DocumentLayer, FontRenderMode, PremultipliedColorF}; use api::units::*; use crate::batch::{BatchBuilder, AlphaBatchBuilder, AlphaBatchContainer}; -use crate::clip::{ClipStore, ClipChainStack}; +use crate::clip::{ClipStore, ClipChainStack, ClipDataHandle}; use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId}; use crate::composite::{CompositorKind, CompositeState}; use crate::debug_render::DebugItem; use crate::gpu_cache::{GpuCache, GpuCacheHandle}; use crate::gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind, ZBufferIdGenerator}; use crate::gpu_types::TransformData; use crate::internal_types::{FastHashMap, PlaneSplitter, SavedTargetIndex}; use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex, RecordedDirtyRegion}; @@ -127,16 +127,35 @@ pub struct FrameVisibilityState<'a> { pub gpu_cache: &'a mut GpuCache, pub scratch: &'a mut PrimitiveScratchBuffer, pub tile_cache: Option<Box<TileCacheInstance>>, 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<SurfaceIndex>, +} + +impl<'a> FrameVisibilityState<'a> { + pub fn push_surface( + &mut self, + surface_index: SurfaceIndex, + shared_clips: &[ClipDataHandle] + ) { + self.surface_stack.push(surface_index); + self.clip_chain_stack.push_surface(shared_clips); + } + + pub fn pop_surface(&mut self) { + self.surface_stack.pop().unwrap(); + self.clip_chain_stack.pop_surface(); + } } pub struct FrameBuildingContext<'a> { pub global_device_pixel_scale: DevicePixelScale, pub scene_properties: &'a SceneProperties, pub global_screen_world_rect: WorldRect, pub spatial_tree: &'a SpatialTree, pub max_local_clip: LayoutRect, @@ -338,16 +357,19 @@ impl FrameBuilder { clip_store: &mut scene.clip_store, scratch, 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( scene.root_pic_index, ROOT_SURFACE_INDEX, &global_screen_world_rect, &visibility_context, &mut visibility_state,
--- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -2294,63 +2294,89 @@ impl TileCacheInstance { /// Update the dependencies for each tile for a given primitive instance. pub fn update_prim_dependencies( &mut self, prim_instance: &PrimitiveInstance, prim_spatial_node_index: SpatialNodeIndex, prim_clip_chain: Option<&ClipChainInstance>, local_prim_rect: LayoutRect, - spatial_tree: &SpatialTree, + frame_context: &FrameVisibilityContext, data_stores: &DataStores, clip_store: &ClipStore, pictures: &[PicturePrimitive], resource_cache: &ResourceCache, opacity_binding_store: &OpacityBindingStorage, image_instances: &ImageInstanceStorage, - surface_index: SurfaceIndex, - surface_spatial_node_index: SpatialNodeIndex, + surface_stack: &[SurfaceIndex], ) -> bool { + // This primitive exists on the last element on the current surface stack. + let prim_surface_index = *surface_stack.last().unwrap(); + // If the primitive is completely clipped out by the clip chain, there // is no need to add it to any primitive dependencies. let prim_clip_chain = match prim_clip_chain { Some(prim_clip_chain) => prim_clip_chain, None => return false, }; self.map_local_to_surface.set_target_spatial_node( prim_spatial_node_index, - spatial_tree, + frame_context.spatial_tree, ); // Map the primitive local rect into picture space. let prim_rect = match self.map_local_to_surface.map(&local_prim_rect) { Some(rect) => rect, None => return false, }; // If the rect is invalid, no need to create dependencies. if prim_rect.size.is_empty_or_negative() { return false; } // If the primitive is directly drawn onto this picture cache surface, then // the pic_clip_rect is in the same space. If not, we need to map it from // the surface space into the picture cache space. - let on_picture_surface = surface_index == self.surface_index; + let on_picture_surface = prim_surface_index == self.surface_index; let pic_clip_rect = if on_picture_surface { prim_clip_chain.pic_clip_rect } else { - self.map_child_pic_to_surface.set_target_spatial_node( - surface_spatial_node_index, - spatial_tree, - ); - self.map_child_pic_to_surface - .map(&prim_clip_chain.pic_clip_rect) - .expect("bug: unable to map clip rect to picture cache space") + // We want to get the rect in the tile cache surface space that this primitive + // occupies, in order to enable correct invalidation regions. Each surface + // that exists in the chain between this primitive and the tile cache surface + // may have an arbitrary inflation factor (for example, in the case of a series + // of nested blur elements). To account for this, step through the current + // surface stack, mapping the primitive rect into each surface space, including + // the inflation factor from each intermediate surface. + let mut current_pic_clip_rect = prim_clip_chain.pic_clip_rect; + let mut current_spatial_node_index = frame_context + .surfaces[prim_surface_index.0] + .surface_spatial_node_index; + + for surface_index in surface_stack.iter().rev() { + let surface = &frame_context.surfaces[surface_index.0]; + + let map_local_to_surface = SpaceMapper::new_with_target( + surface.surface_spatial_node_index, + current_spatial_node_index, + surface.rect, + frame_context.spatial_tree, + ); + + current_pic_clip_rect = map_local_to_surface + .map(¤t_pic_clip_rect) + .expect("bug: unable to map") + .inflate(surface.inflation_factor, surface.inflation_factor); + + current_spatial_node_index = surface.surface_spatial_node_index; + } + + current_pic_clip_rect }; // Get the tile coordinates in the picture space. let (p0, p1) = self.get_tile_coords_for_rect(&pic_clip_rect); // If the primitive is outside the tiling rects, it's known to not // be visible. if p0.x == p1.x || p0.y == p1.y { @@ -2526,19 +2552,19 @@ impl TileCacheInstance { // primitive as an opaque backdrop rect. Several of these are conservative // checks and could be relaxed in future. However, these checks // are quick and capture the common cases of background rects and images. // Specifically, we currently require: // - The primitive is on the main picture cache surface. // - Same coord system as picture cache (ensures rects are axis-aligned). // - No clip masks exist. let same_coord_system = { - let prim_spatial_node = &spatial_tree + let prim_spatial_node = &frame_context.spatial_tree .spatial_nodes[prim_spatial_node_index.0 as usize]; - let surface_spatial_node = &spatial_tree + let surface_spatial_node = &frame_context.spatial_tree .spatial_nodes[self.spatial_node_index.0 as usize]; prim_spatial_node.coordinate_system_id == surface_spatial_node.coordinate_system_id }; same_coord_system && on_picture_surface } };
--- a/gfx/wr/webrender/src/prim_store/mod.rs +++ b/gfx/wr/webrender/src/prim_store/mod.rs @@ -1904,22 +1904,22 @@ impl PrimitiveStore { PictureRect::from_untyped(&pic.estimated_local_rect.to_untyped()), surface_index, frame_context, frame_state, ); // Push a new surface, supplying the list of clips that should be // ignored, since they are handled by clipping when drawing this surface. - frame_state.clip_chain_stack.push_surface(&tile_cache.shared_clips); + frame_state.push_surface(surface_index, &tile_cache.shared_clips); frame_state.tile_cache = Some(tile_cache); } _ => { if is_composite { - frame_state.clip_chain_stack.push_surface(&[]); + frame_state.push_surface(surface_index, &[]); } } } (prim_list, surface_index, pic.apply_local_clip_rect, world_culling_rect, is_composite) }; let surface = &frame_context.surfaces[surface_index.0 as usize]; @@ -2128,25 +2128,24 @@ impl PrimitiveStore { ); if let Some(ref mut tile_cache) = frame_state.tile_cache { if !tile_cache.update_prim_dependencies( prim_instance, cluster.spatial_node_index, clip_chain.as_ref(), prim_local_rect, - frame_context.spatial_tree, + frame_context, frame_state.data_stores, frame_state.clip_store, &self.pictures, frame_state.resource_cache, &self.opacity_bindings, &self.images, - surface_index, - surface.surface_spatial_node_index, + &frame_state.surface_stack, ) { prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID; // Ensure the primitive clip is popped - perhaps we can use // some kind of scope to do this automatically in future. frame_state.clip_chain_stack.pop_clip(); continue; } } @@ -2287,17 +2286,17 @@ impl PrimitiveStore { frame_state, ); } } } // Similar to above, pop either the clip chain or root entry off the current clip stack. if is_composite { - frame_state.clip_chain_stack.pop_surface(); + frame_state.pop_surface(); } let pic = &mut self.pictures[pic_index.0]; pic.prim_list = prim_list; // If the local rect changed (due to transforms in child primitives) then // invalidate the GPU cache location to re-upload the new local rect // and stretch size. Drop shadow filters also depend on the local rect