From f11b8c7b696f2cb80b569d09de7643d349e6b62a Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 14 Feb 2018 15:12:11 +0100 Subject: [PATCH] Convert ClipIds for Clips into indices in the ClipScrollTree During display list flattening, we convert ClipIds for the clipping node into ClipChainIndex (as well as allocating space for them in the ClipChain array in the ClipScrollTree). This allows us to avoid doing a HashMap lookup for the ClipChain for every primitive run. It also moves us a little closer to a universal representation of ClipChains (both API-defined ClipChains and ones derived from the hierarchy of the ClipScroll tree). This causes the amount of time spend doing HashMap lookups to decrease in the profile, though they are still done for the positioning node. A second patch will reduce HashMap lookups for positioning nodes as well. --- webrender/src/batch.rs | 6 +- webrender/src/border.rs | 13 ++- webrender/src/box_shadow.rs | 13 ++- webrender/src/clip.rs | 106 +++++++++++++++++++++ webrender/src/clip_scroll_node.rs | 51 ++++------ webrender/src/clip_scroll_tree.rs | 93 ++++++++++++------ webrender/src/frame.rs | 151 +++++++++++++++++++++--------- webrender/src/frame_builder.rs | 100 +++++++++++--------- webrender/src/hit_test.rs | 106 +++++++++++++-------- webrender/src/picture.rs | 10 +- webrender/src/prim_store.rs | 67 ++++++------- webrender/src/render_task.rs | 103 +------------------- 12 files changed, 475 insertions(+), 344 deletions(-) diff --git a/webrender/src/batch.rs b/webrender/src/batch.rs index 8b13157fce..cc971e11bd 100644 --- a/webrender/src/batch.rs +++ b/webrender/src/batch.rs @@ -7,7 +7,7 @@ use api::{DeviceUintRect, DeviceUintPoint, DeviceUintSize, ExternalImageType, Fi use api::{DeviceIntPoint, LayerPoint, SubpixelDirection, YuvColorSpace, YuvFormat}; use api::{LayerToWorldTransform, WorldPixel}; use border::{BorderCornerInstance, BorderCornerSide, BorderEdgeKind}; -use clip::{ClipSource, ClipStore}; +use clip::{ClipSource, ClipStore, ClipWorkItem}; use clip_scroll_tree::{CoordinateSystemId}; use euclid::{TypedTransform3D, vec3}; use glyph_rasterizer::GlyphFormat; @@ -20,9 +20,7 @@ use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive use plane_split::{BspSplitter, Polygon, Splitter}; use prim_store::{ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore}; use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun}; -use render_task::{ClipWorkItem}; -use render_task::{RenderTaskAddress, RenderTaskId}; -use render_task::{RenderTaskKind, RenderTaskTree}; +use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree}; use renderer::{BlendMode, ImageBufferKind}; use renderer::BLOCKS_PER_UV_RECT; use resource_cache::{CacheItem, GlyphFetchResult, ImageRequest, ResourceCache}; diff --git a/webrender/src/border.rs b/webrender/src/border.rs index 677b76b0b0..6e809bcd82 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -2,15 +2,14 @@ * 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::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF}; -use api::{LayerPoint, LayerRect, LayerPrimitiveInfo, LayerSize}; -use api::{NormalBorder, RepeatMode, TexelRect}; +use api::{BorderRadius, BorderSide, BorderStyle, BorderWidths, ColorF, LayerPoint}; +use api::{LayerPrimitiveInfo, LayerRect, LayerSize, NormalBorder, RepeatMode, TexelRect}; use clip::ClipSource; use ellipse::Ellipse; use frame_builder::FrameBuilder; use gpu_cache::GpuDataRequest; -use prim_store::{BorderPrimitiveCpu, BrushSegment, BrushSegmentDescriptor}; -use prim_store::{BrushClipMaskKind, EdgeAaSegmentMask, PrimitiveContainer}; +use prim_store::{BorderPrimitiveCpu, BrushClipMaskKind, BrushSegment, BrushSegmentDescriptor}; +use prim_store::{EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain}; use util::{lerp, pack_as_float}; #[repr(u8)] @@ -286,7 +285,7 @@ impl FrameBuilder { info: &LayerPrimitiveInfo, border: &NormalBorder, widths: &BorderWidths, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, corner_instances: [BorderCornerInstance; 4], edges: [BorderEdgeKind; 4], clip_sources: Vec, @@ -354,7 +353,7 @@ impl FrameBuilder { info: &LayerPrimitiveInfo, border: &NormalBorder, widths: &BorderWidths, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, ) { // The border shader is quite expensive. For simple borders, we can just draw // the border with a few rectangles. This generally gives better batching, and diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index 3b47b21e68..9b66cf37ee 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -2,16 +2,15 @@ * 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, LayerPoint, LayerRect, LayerSize, LayerVector2D}; -use api::{BorderRadius, BoxShadowClipMode, LayoutSize, LayerPrimitiveInfo}; -use api::{ClipMode, ClipAndScrollInfo, ComplexClipRegion, LocalClip}; -use api::{PipelineId}; +use api::{BorderRadius, BoxShadowClipMode, ClipMode, ColorF, ComplexClipRegion, LayerPoint}; +use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, LocalClip}; +use api::PipelineId; use app_units::Au; use clip::ClipSource; use frame_builder::FrameBuilder; use gpu_types::BrushImageKind; -use prim_store::{PrimitiveContainer}; -use prim_store::{BrushMaskKind, BrushKind, BrushPrimitive}; +use prim_store::{BrushKind, BrushMaskKind, BrushPrimitive, PrimitiveContainer}; +use prim_store::ScrollNodeAndClipChain; use picture::PicturePrimitive; use util::RectHelpers; use render_task::MAX_BLUR_STD_DEVIATION; @@ -53,7 +52,7 @@ impl FrameBuilder { pub fn add_box_shadow( &mut self, pipeline_id: PipelineId, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, prim_info: &LayerPrimitiveInfo, box_offset: &LayerVector2D, color: &ColorF, diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index ead309140f..59ed948ac2 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -6,12 +6,15 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS use api::{ImageRendering, LayerRect, LayerToWorldTransform, LayoutPoint, LayoutVector2D}; use api::LocalClip; use border::{BorderCornerClipSource, ensure_no_corner_overlap}; +use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId}; use ellipse::Ellipse; use freelist::{FreeList, FreeListHandle, WeakFreeListHandle}; use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks}; +use gpu_types::ClipScrollNodeIndex; use prim_store::{ClipData, ImageMaskData}; use resource_cache::{ImageRequest, ResourceCache}; use util::{MaxRect, MatrixHelpers, calculate_screen_bounding_rect, extract_inner_rect_safe}; +use std::rc::Rc; pub type ClipStore = FreeList; pub type ClipSourcesHandle = FreeListHandle; @@ -349,3 +352,106 @@ pub fn rounded_rectangle_contains_point(point: &LayoutPoint, true } + +pub type ClipChainNodeRef = Option>; + +#[derive(Debug, Clone)] +pub struct ClipChainNode { + pub work_item: ClipWorkItem, + pub local_clip_rect: LayerRect, + pub screen_outer_rect: DeviceIntRect, + pub screen_inner_rect: DeviceIntRect, + pub prev: ClipChainNodeRef, +} + +#[derive(Debug, Clone)] +pub struct ClipChain { + pub parent_index: Option, + pub combined_outer_screen_rect: DeviceIntRect, + pub combined_inner_screen_rect: DeviceIntRect, + pub nodes: ClipChainNodeRef, +} + +impl ClipChain { + pub fn empty(screen_rect: &DeviceIntRect) -> ClipChain { + ClipChain { + parent_index: None, + combined_inner_screen_rect: *screen_rect, + combined_outer_screen_rect: *screen_rect, + nodes: None, + } + } + + pub fn new_with_added_node( + &self, + work_item: ClipWorkItem, + local_clip_rect: LayerRect, + screen_outer_rect: DeviceIntRect, + screen_inner_rect: DeviceIntRect, + ) -> ClipChain { + // If the new node's inner rectangle completely surrounds our outer rectangle, + // we can discard the new node entirely since it isn't going to affect anything. + if screen_inner_rect.contains_rect(&self.combined_outer_screen_rect) { + return self.clone(); + } + + let new_node = ClipChainNode { + work_item, + local_clip_rect, + screen_outer_rect, + screen_inner_rect, + prev: None, + }; + + let mut new_chain = self.clone(); + new_chain.add_node(new_node); + new_chain + } + + pub fn add_node(&mut self, mut new_node: ClipChainNode) { + new_node.prev = self.nodes.clone(); + + // If this clip's outer rectangle is completely enclosed by the clip + // chain's inner rectangle, then the only clip that matters from this point + // on is this clip. We can disconnect this clip from the parent clip chain. + if self.combined_inner_screen_rect.contains_rect(&new_node.screen_outer_rect) { + new_node.prev = None; + } + + self.combined_outer_screen_rect = + self.combined_outer_screen_rect.intersection(&new_node.screen_outer_rect) + .unwrap_or_else(DeviceIntRect::zero); + self.combined_inner_screen_rect = + self.combined_inner_screen_rect.intersection(&new_node.screen_inner_rect) + .unwrap_or_else(DeviceIntRect::zero); + + self.nodes = Some(Rc::new(new_node)); + } +} + +pub struct ClipChainNodeIter { + pub current: ClipChainNodeRef, +} + +impl Iterator for ClipChainNodeIter { + type Item = Rc; + + fn next(&mut self) -> ClipChainNodeRef { + let previous = self.current.clone(); + self.current = match self.current { + Some(ref item) => item.prev.clone(), + None => return None, + }; + previous + } +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "capture", derive(Serialize))] +#[cfg_attr(feature = "replay", derive(Deserialize))] +pub struct ClipWorkItem { + pub scroll_node_data_index: ClipScrollNodeIndex, + pub clip_sources: ClipSourcesWeakHandle, + pub coordinate_system_id: CoordinateSystemId, +} + diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index 7df3993107..4940f1a503 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -6,13 +6,12 @@ use api::{ClipId, DevicePixelScale, ExternalScrollId, LayerPixel, LayerPoint, La use api::{LayerSize, LayerToWorldTransform, LayerTransform, LayerVector2D, LayoutTransform}; use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollEventPhase}; use api::{ScrollLocation, ScrollNodeIdType, ScrollSensitivity, StickyOffsetBounds, WorldPoint}; -use clip::{ClipSourcesHandle, ClipStore}; -use clip_scroll_tree::{CoordinateSystemId, TransformUpdateState}; +use clip::{ClipChain, ClipSourcesHandle, ClipStore, ClipWorkItem}; +use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId, TransformUpdateState}; use euclid::SideOffsets2D; use geometry::ray_intersects_rect; use gpu_cache::GpuCache; use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData}; -use render_task::{ClipChain, ClipWorkItem}; use resource_cache::ResourceCache; use scene::SceneProperties; use spring::{DAMPING, STIFFNESS, Spring}; @@ -56,7 +55,10 @@ pub enum NodeType { ReferenceFrame(ReferenceFrameInfo), /// Other nodes just do clipping, but no transformation. - Clip(ClipSourcesHandle), + Clip { + handle: ClipSourcesHandle, + clip_chain_index: ClipChainIndex + }, /// Transforms it's content, but doesn't clip it. Can also be adjusted /// by scroll events or setting scroll offsets. @@ -106,9 +108,6 @@ pub struct ClipScrollNode { /// The type of this node and any data associated with that node type. pub node_type: NodeType, - /// The ClipChain that will be used if this node is used as the 'clipping node.' - pub clip_chain: Option, - /// True if this node is transformed by an invertible transform. If not, display items /// transformed by this node will not be displayed and display items not transformed by this /// node will not be clipped by clips that are transformed by this node. @@ -128,7 +127,7 @@ pub struct ClipScrollNode { } impl ClipScrollNode { - fn new( + pub fn new( pipeline_id: PipelineId, parent_id: Option, rect: &LayerRect, @@ -142,7 +141,6 @@ impl ClipScrollNode { children: Vec::new(), pipeline_id, node_type: node_type, - clip_chain: None, invertible: true, coordinate_system_id: CoordinateSystemId(0), coordinate_system_relative_transform: TransformOrOffset::zero(), @@ -170,15 +168,6 @@ impl ClipScrollNode { Self::new(pipeline_id, Some(parent_id), frame_rect, node_type) } - pub fn new_clip_node( - pipeline_id: PipelineId, - parent_id: ClipId, - handle: ClipSourcesHandle, - clip_rect: LayerRect, - ) -> Self { - Self::new(pipeline_id, Some(parent_id), &clip_rect, NodeType::Clip(handle)) - } - pub fn new_reference_frame( parent_id: Option, frame_rect: &LayerRect, @@ -271,7 +260,6 @@ impl ClipScrollNode { self.invertible = false; self.world_content_transform = LayerToWorldTransform::identity(); self.world_viewport_transform = LayerToWorldTransform::identity(); - self.clip_chain = None; } pub fn push_gpu_node_data(&mut self, node_data: &mut Vec) { @@ -304,6 +292,7 @@ impl ClipScrollNode { resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, scene_properties: &SceneProperties, + clip_chains: &mut Vec, ) { // If any of our parents was not rendered, we are not rendered either and can just // quit here. @@ -331,6 +320,7 @@ impl ClipScrollNode { clip_store, resource_cache, gpu_cache, + clip_chains, ); } @@ -341,11 +331,11 @@ impl ClipScrollNode { clip_store: &mut ClipStore, resource_cache: &mut ResourceCache, gpu_cache: &mut GpuCache, + clip_chains: &mut Vec, ) { - let clip_sources_handle = match self.node_type { - NodeType::Clip(ref handle) => handle, + let (clip_sources_handle, clip_chain_index) = match self.node_type { + NodeType::Clip { ref handle, clip_chain_index } => (handle, clip_chain_index), _ => { - self.clip_chain = Some(state.parent_clip_chain.clone()); self.invertible = true; return; } @@ -364,29 +354,22 @@ impl ClipScrollNode { "Clipping node didn't have outer rect." ); - // If this clip's inner rectangle completely surrounds the existing clip - // chain's outer rectangle, we can discard this clip entirely since it isn't - // going to affect anything. - if screen_inner_rect.contains_rect(&state.parent_clip_chain.combined_outer_screen_rect) { - self.clip_chain = Some(state.parent_clip_chain.clone()); - return; - } - let work_item = ClipWorkItem { scroll_node_data_index: self.node_data_index, clip_sources: clip_sources_handle.weak(), coordinate_system_id: state.current_coordinate_system_id, }; - let clip_chain = state.parent_clip_chain.new_with_added_node( + let mut clip_chain = clip_chains[state.parent_clip_chain_index.0].new_with_added_node( work_item, self.coordinate_system_relative_transform.apply(&local_outer_rect), screen_outer_rect, screen_inner_rect, ); - self.clip_chain = Some(clip_chain.clone()); - state.parent_clip_chain = clip_chain; + clip_chain.parent_index = Some(state.parent_clip_chain_index); + clip_chains[clip_chain_index.0] = clip_chain; + state.parent_clip_chain_index = clip_chain_index; } pub fn update_transform( @@ -621,7 +604,7 @@ impl ClipScrollNode { state.nearest_scrolling_ancestor_viewport .translate(&translation); } - NodeType::Clip(..) => { } + NodeType::Clip{ .. } => { } NodeType::ScrollFrame(ref scrolling) => { state.parent_accumulated_scroll_offset = scrolling.offset + state.parent_accumulated_scroll_offset; diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index c82bcb9278..89a0a85919 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -2,17 +2,15 @@ * 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::{ClipChainId, ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint}; -use api::{LayerRect, LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping}; -use api::{ScrollEventPhase, ScrollLocation, ScrollNodeIdType}; -use api::{ScrollNodeState, WorldPoint}; -use clip::ClipStore; +use api::{ClipId, DeviceIntRect, DevicePixelScale, ExternalScrollId, LayerPoint, LayerRect}; +use api::{LayerToWorldTransform, LayerVector2D, PipelineId, ScrollClamping, ScrollEventPhase}; +use api::{ScrollLocation, ScrollNodeIdType, ScrollNodeState, WorldPoint}; +use clip::{ClipChain, ClipSourcesHandle, ClipStore}; use clip_scroll_node::{ClipScrollNode, NodeType, ScrollFrameInfo, StickyFrameInfo}; use gpu_cache::GpuCache; use gpu_types::{ClipScrollNodeIndex, ClipScrollNodeData}; use internal_types::{FastHashMap, FastHashSet}; use print_tree::{PrintTree, PrintTreePrinter}; -use render_task::ClipChain; use resource_cache::ResourceCache; use scene::SceneProperties; use util::TransformOrOffset; @@ -44,11 +42,14 @@ impl CoordinateSystemId { } pub struct ClipChainDescriptor { - pub id: ClipChainId, - pub parent: Option, + pub index: ClipChainIndex, + pub parent: Option, pub clips: Vec, } +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ClipChainIndex(pub usize); + pub struct ClipScrollTree { pub nodes: FastHashMap, @@ -57,8 +58,9 @@ pub struct ClipScrollTree { /// the children of ClipChains later in the list. pub clip_chains_descriptors: Vec, - /// A HashMap of built ClipChains that are described by `clip_chains_descriptors`. - pub clip_chains: FastHashMap, + /// A vector of all ClipChains in this ClipScrollTree including those from + /// ClipChainDescriptors and also those defined by the clipping node hierarchy. + pub clip_chains: Vec, pub pending_scroll_offsets: FastHashMap, @@ -90,7 +92,9 @@ pub struct TransformUpdateState { pub parent_accumulated_scroll_offset: LayerVector2D, pub nearest_scrolling_ancestor_offset: LayerVector2D, pub nearest_scrolling_ancestor_viewport: LayerRect, - pub parent_clip_chain: ClipChain, + + /// The index of the current parent's clip chain. + pub parent_clip_chain_index: ClipChainIndex, /// An id for keeping track of the axis-aligned space of this node. This is used in /// order to to track what kinds of clip optimizations can be done for a particular @@ -113,7 +117,7 @@ impl ClipScrollTree { ClipScrollTree { nodes: FastHashMap::default(), clip_chains_descriptors: Vec::new(), - clip_chains: FastHashMap::default(), + clip_chains: vec![ClipChain::empty(&DeviceIntRect::zero())], pending_scroll_offsets: FastHashMap::default(), currently_scrolling_node_id: None, root_reference_frame_id: ClipId::root_reference_frame(dummy_pipeline), @@ -211,7 +215,7 @@ impl ClipScrollTree { } self.pipelines_to_discard.clear(); - self.clip_chains.clear(); + self.clip_chains = vec![ClipChain::empty(&DeviceIntRect::zero())]; self.clip_chains_descriptors.clear(); scroll_states } @@ -321,6 +325,8 @@ impl ClipScrollTree { return; } + self.clip_chains[0] = ClipChain::empty(screen_rect); + let root_reference_frame_id = self.root_reference_frame_id(); let mut state = TransformUpdateState { parent_reference_frame_transform: LayerToWorldTransform::create_translation( @@ -331,7 +337,7 @@ impl ClipScrollTree { parent_accumulated_scroll_offset: LayerVector2D::zero(), nearest_scrolling_ancestor_offset: LayerVector2D::zero(), nearest_scrolling_ancestor_viewport: LayerRect::zero(), - parent_clip_chain: ClipChain::empty(screen_rect), + parent_clip_chain_index: ClipChainIndex(0), current_coordinate_system_id: CoordinateSystemId::root(), coordinate_system_relative_transform: TransformOrOffset::zero(), invertible: true, @@ -384,6 +390,7 @@ impl ClipScrollTree { resource_cache, gpu_cache, scene_properties, + &mut self.clip_chains, ); node.push_gpu_node_data(gpu_node_data); @@ -417,21 +424,28 @@ impl ClipScrollTree { // ClipScrollNode clipping nodes. Here we start the ClipChain with a clone of the // parent's node, if necessary. let mut chain = match descriptor.parent { - Some(id) => self.clip_chains[&id].clone(), + Some(index) => self.clip_chains[index.0].clone(), None => ClipChain::empty(screen_rect), }; // Now we walk through each ClipScrollNode in the vector of clip nodes and // extract their ClipChain nodes to construct the final list. for clip_id in &descriptor.clips { - if let Some(ref node_chain) = self.nodes[&clip_id].clip_chain { - if let Some(ref nodes) = node_chain.nodes { - chain.add_node((**nodes).clone()); + let node_clip_chain_index = match self.nodes[&clip_id].node_type { + NodeType::Clip { clip_chain_index, .. } => clip_chain_index, + _ => { + warn!("Tried to create a clip chain with non-clipping node."); + continue; } + }; + + if let Some(ref nodes) = self.clip_chains[node_clip_chain_index.0].nodes { + chain.add_node((**nodes).clone()); } } - self.clip_chains.insert(descriptor.id, chain); + chain.parent_index = descriptor.parent; + self.clip_chains[descriptor.index.0] = chain; } } @@ -466,6 +480,20 @@ impl ClipScrollTree { } } + pub fn add_clip_node( + &mut self, + id: ClipId, + parent_id: ClipId, + handle: ClipSourcesHandle, + clip_rect: LayerRect, + ) -> ClipChainIndex { + let clip_chain_index = self.allocate_clip_chain(); + let node_type = NodeType::Clip { handle, clip_chain_index }; + let node = ClipScrollNode::new(id.pipeline_id(), Some(parent_id), &clip_rect, node_type); + self.add_node(node, id); + clip_chain_index + } + pub fn add_sticky_frame( &mut self, id: ClipId, @@ -484,11 +512,12 @@ impl ClipScrollTree { pub fn add_clip_chain_descriptor( &mut self, - id: ClipChainId, - parent: Option, + parent: Option, clips: Vec - ) { - self.clip_chains_descriptors.push(ClipChainDescriptor { id, parent, clips }); + ) -> ClipChainIndex { + let index = self.allocate_clip_chain(); + self.clip_chains_descriptors.push(ClipChainDescriptor { index, parent, clips }); + index } pub fn add_node(&mut self, node: ClipScrollNode, id: ClipId) { @@ -515,11 +544,11 @@ impl ClipScrollTree { let node = self.nodes.get(id).unwrap(); match node.node_type { - NodeType::Clip(ref clip_sources_handle) => { + NodeType::Clip { ref handle, .. } => { pt.new_level("Clip".to_owned()); pt.add_item(format!("id: {:?}", id)); - let clips = clip_store.get(&clip_sources_handle).clips(); + let clips = clip_store.get(&handle).clips(); pt.new_level(format!("Clip Sources [{}]", clips.len())); for source in clips { pt.add_item(format!("{:?}", source)); @@ -581,11 +610,15 @@ impl ClipScrollTree { } } - pub fn get_clip_chain(&self, id: &ClipId) -> Option<&ClipChain> { - match id { - &ClipId::ClipChain(clip_chain_id) => Some(&self.clip_chains[&clip_chain_id]), - _ => self.nodes[id].clip_chain.as_ref(), - } + pub fn allocate_clip_chain(&mut self) -> ClipChainIndex { + debug_assert!(!self.clip_chains.is_empty()); + let new_clip_chain =self.clip_chains[0].clone(); + self.clip_chains.push(new_clip_chain); + ClipChainIndex(self.clip_chains.len() - 1) + } + + pub fn get_clip_chain(&self, index: ClipChainIndex) -> &ClipChain { + &self.clip_chains[index.0] } } diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 2f7fff636c..99c948a5d6 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -3,21 +3,22 @@ * 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::{BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion}; -use api::{DevicePixelScale, DeviceUintRect, DeviceUintSize, DisplayItemRef, DocumentLayer, Epoch}; -use api::{ExternalScrollId, FilterOp, IframeDisplayItem, ImageDisplayItem, ItemRange, LayerPoint}; +use api::{BuiltDisplayListIter, ClipId, ColorF, ComplexClipRegion, DevicePixelScale}; +use api::{DeviceUintRect, DeviceUintSize, DisplayItemRef, DocumentLayer, Epoch, ExternalScrollId}; +use api::{FilterOp, IframeDisplayItem, ImageDisplayItem, ItemRange, LayerPoint}; use api::{LayerPrimitiveInfo, LayerRect, LayerSize, LayerVector2D, LayoutSize, PipelineId}; use api::{ScrollClamping, ScrollEventPhase, ScrollFrameDisplayItem, ScrollLocation}; use api::{ScrollNodeIdType, ScrollNodeState, ScrollPolicy, ScrollSensitivity, SpecificDisplayItem}; use api::{StackingContext, TileOffset, TransformStyle, WorldPoint}; use clip::ClipRegion; use clip_scroll_node::StickyFrameInfo; -use clip_scroll_tree::{ClipScrollTree, ScrollStates}; +use clip_scroll_tree::{ClipChainIndex, ClipScrollTree, ScrollStates}; use euclid::rect; use frame_builder::{FrameBuilder, FrameBuilderConfig, ScrollbarInfo}; use gpu_cache::GpuCache; use hit_test::HitTester; use internal_types::{FastHashMap, FastHashSet, RenderedDocument}; +use prim_store::ScrollNodeAndClipChain; use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters}; use resource_cache::{FontInstanceMap,ResourceCache, TiledImageMap}; use scene::{Scene, StackingContextHelpers, ScenePipeline, SceneProperties}; @@ -36,6 +37,53 @@ static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { a: 0.6, }; +/// A data structure that keeps track of mapping between API clip ids and the indices +/// used internally in the ClipScrollTree to avoid having to do HashMap lookups. This +/// also includes a small LRU cache. Currently the cache is small (1 entry), but in the +/// future we could use uluru here to do something more involved. +pub struct ClipIdToIndexMapper { + map: FastHashMap, + cached_index: Option<(ClipId, ClipChainIndex)>, +} + +impl ClipIdToIndexMapper { + fn new() -> ClipIdToIndexMapper { + ClipIdToIndexMapper { + map: FastHashMap::default(), + cached_index: None, + } + } + + pub fn add(&mut self, id: ClipId, index: ClipChainIndex) { + debug_assert!(!self.map.contains_key(&id)); + self.map.insert(id, index); + } + + pub fn map_to_parent_clip_chain(&mut self, id: ClipId, parent_id: &ClipId) { + let parent_chain_index = self.map_clip_id(parent_id); + self.add(id, parent_chain_index); + } + + pub fn map_clip_id(&mut self, id: &ClipId) -> ClipChainIndex { + match self.cached_index { + Some((cached_id, cached_index)) if cached_id == *id => return cached_index, + _ => {} + } + + self.map[id] + } + + pub fn map_clip_id_and_cache_result(&mut self, id: &ClipId) -> ClipChainIndex { + let index = self.map_clip_id(id); + self.cached_index = Some((*id, index)); + index + } + + pub fn simple_scroll_and_clip_chain(&mut self, id: &ClipId) -> ScrollNodeAndClipChain { + ScrollNodeAndClipChain::new(*id, self.map_clip_id(&id)) + } +} + struct FlattenContext<'a> { scene: &'a Scene, builder: FrameBuilder, @@ -45,6 +93,7 @@ struct FlattenContext<'a> { pipeline_epochs: Vec<(PipelineId, Epoch)>, replacements: Vec<(ClipId, ClipId)>, output_pipelines: &'a FastHashSet, + id_to_index_mapper: ClipIdToIndexMapper, } impl<'a> FlattenContext<'a> { @@ -104,13 +153,23 @@ impl<'a> FlattenContext<'a> { let root_reference_frame_id = ClipId::root_reference_frame(pipeline_id); let root_scroll_frame_id = ClipId::root_scroll_node(pipeline_id); + let root_clip_chain_index = + self.id_to_index_mapper.map_clip_id_and_cache_result(&root_reference_frame_id); + let root_reference_frame_clip_and_scroll = ScrollNodeAndClipChain::new( + root_reference_frame_id, + root_clip_chain_index, + ); + self.builder.push_stacking_context( pipeline_id, CompositeOps::default(), TransformStyle::Flat, true, true, - ClipAndScrollInfo::simple(root_scroll_frame_id), + ScrollNodeAndClipChain::new( + ClipId::root_scroll_node(pipeline_id), + root_clip_chain_index, + ), self.output_pipelines, ); @@ -122,7 +181,7 @@ impl<'a> FlattenContext<'a> { let root_bounds = LayerRect::new(LayerPoint::zero(), *frame_size); let info = LayerPrimitiveInfo::new(root_bounds); self.builder.add_solid_rectangle( - ClipAndScrollInfo::simple(root_reference_frame_id), + root_reference_frame_clip_and_scroll, &info, bg_color, None, @@ -142,7 +201,7 @@ impl<'a> FlattenContext<'a> { let scrollbar_rect = LayerRect::new(LayerPoint::zero(), LayerSize::new(10.0, 70.0)); let container_rect = LayerRect::new(LayerPoint::zero(), *frame_size); self.builder.add_scroll_bar( - ClipAndScrollInfo::simple(root_reference_frame_id), + root_reference_frame_clip_and_scroll, &LayerPrimitiveInfo::new(scrollbar_rect), DEFAULT_SCROLLBAR_COLOR, ScrollbarInfo(root_scroll_frame_id, container_rect), @@ -184,19 +243,13 @@ impl<'a> FlattenContext<'a> { } } - fn flatten_clip( - &mut self, - pipeline_id: PipelineId, - parent_id: &ClipId, - new_clip_id: &ClipId, - clip_region: ClipRegion, - ) { + fn flatten_clip(&mut self, parent_id: &ClipId, new_clip_id: &ClipId, clip_region: ClipRegion) { self.builder.add_clip_node( *new_clip_id, *parent_id, - pipeline_id, clip_region, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); } @@ -205,7 +258,7 @@ impl<'a> FlattenContext<'a> { item: &DisplayItemRef, info: &ScrollFrameDisplayItem, pipeline_id: PipelineId, - clip_and_scroll: &ClipAndScrollInfo, + clip_and_scroll: &ScrollNodeAndClipChain, reference_frame_relative_offset: &LayerVector2D, ) { let complex_clips = self.get_complex_clips(pipeline_id, item.complex_clip().0); @@ -229,9 +282,9 @@ impl<'a> FlattenContext<'a> { self.builder.add_clip_node( info.clip_id, clip_and_scroll.scroll_node_id, - pipeline_id, clip_region, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); self.builder.add_scroll_frame( @@ -243,6 +296,7 @@ impl<'a> FlattenContext<'a> { &content_rect.size, info.scroll_sensitivity, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); } @@ -250,7 +304,8 @@ impl<'a> FlattenContext<'a> { &mut self, traversal: &mut BuiltDisplayListIter<'a>, pipeline_id: PipelineId, - context_scroll_node_id: ClipId, + unreplaced_scroll_id: ClipId, + clip_and_scroll: ScrollNodeAndClipChain, mut reference_frame_relative_offset: LayerVector2D, bounds: &LayerRect, stacking_context: &StackingContext, @@ -279,7 +334,7 @@ impl<'a> FlattenContext<'a> { if stacking_context.scroll_policy == ScrollPolicy::Fixed { self.replacements.push(( - context_scroll_node_id, + unreplaced_scroll_id, self.builder.current_reference_frame_id(), )); } @@ -296,30 +351,33 @@ impl<'a> FlattenContext<'a> { ); let reference_frame_bounds = LayerRect::new(LayerPoint::zero(), bounds.size); - let mut parent_id = self.apply_scroll_frame_id_replacement(context_scroll_node_id); self.builder.push_reference_frame( reference_frame_id, - Some(parent_id), + Some(clip_and_scroll.scroll_node_id), pipeline_id, &reference_frame_bounds, stacking_context.transform, stacking_context.perspective, reference_frame_relative_offset, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); - self.replacements.push((context_scroll_node_id, reference_frame_id)); + self.replacements.push((unreplaced_scroll_id, reference_frame_id)); reference_frame_relative_offset = LayerVector2D::zero(); } - let sc_scroll_node_id = self.apply_scroll_frame_id_replacement(context_scroll_node_id); - + // We apply the replacements one more time in case we need to set it to a replacement + // that we just pushed above. + let new_scroll_node = self.apply_scroll_frame_id_replacement(unreplaced_scroll_id); + let stacking_context_clip_and_scroll = + self.id_to_index_mapper.simple_scroll_and_clip_chain(&new_scroll_node); self.builder.push_stacking_context( pipeline_id, composition_operations, stacking_context.transform_style, is_backface_visible, false, - ClipAndScrollInfo::simple(sc_scroll_node_id), + stacking_context_clip_and_scroll, self.output_pipelines, ); @@ -345,8 +403,7 @@ impl<'a> FlattenContext<'a> { &mut self, item: &DisplayItemRef, info: &IframeDisplayItem, - parent_pipeline_id: PipelineId, - clip_and_scroll: &ClipAndScrollInfo, + clip_and_scroll: &ScrollNodeAndClipChain, reference_frame_relative_offset: &LayerVector2D, ) { let iframe_pipeline_id = info.pipeline_id; @@ -358,12 +415,12 @@ impl<'a> FlattenContext<'a> { self.builder.add_clip_node( info.clip_id, clip_and_scroll.scroll_node_id, - parent_pipeline_id, ClipRegion::create_for_clip_node_with_local_clip( &item.local_clip(), &reference_frame_relative_offset ), self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); self.pipeline_epochs.push((iframe_pipeline_id, pipeline.epoch)); @@ -380,6 +437,7 @@ impl<'a> FlattenContext<'a> { None, origin, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); self.builder.add_scroll_frame( @@ -391,6 +449,7 @@ impl<'a> FlattenContext<'a> { &pipeline.content_size, ScrollSensitivity::ScriptAndInputEvents, self.clip_scroll_tree, + &mut self.id_to_index_mapper, ); self.flatten_root(&mut pipeline.display_list.iter(), iframe_pipeline_id, &iframe_rect.size); @@ -404,7 +463,11 @@ impl<'a> FlattenContext<'a> { pipeline_id: PipelineId, reference_frame_relative_offset: LayerVector2D, ) -> Option> { - let mut clip_and_scroll = item.clip_and_scroll(); + let clip_and_scroll = item.clip_and_scroll(); + let mut clip_and_scroll = ScrollNodeAndClipChain::new( + clip_and_scroll.scroll_node_id, + self.id_to_index_mapper.map_clip_id_and_cache_result(&clip_and_scroll.clip_node_id()), + ); let unreplaced_scroll_id = clip_and_scroll.scroll_node_id; clip_and_scroll.scroll_node_id = @@ -557,6 +620,7 @@ impl<'a> FlattenContext<'a> { &mut subtraversal, pipeline_id, unreplaced_scroll_id, + clip_and_scroll, reference_frame_relative_offset, &item.rect(), &info.stacking_context, @@ -569,7 +633,6 @@ impl<'a> FlattenContext<'a> { self.flatten_iframe( &item, info, - pipeline_id, &clip_and_scroll, &reference_frame_relative_offset ); @@ -582,16 +645,16 @@ impl<'a> FlattenContext<'a> { info.image_mask, &reference_frame_relative_offset, ); - self.flatten_clip( - pipeline_id, - &clip_and_scroll.scroll_node_id, - &info.id, - clip_region, - ); + self.flatten_clip(&clip_and_scroll.scroll_node_id, &info.id, clip_region); } SpecificDisplayItem::ClipChain(ref info) => { let items = self.get_clip_chain_items(pipeline_id, item.clip_chain_items()); - self.clip_scroll_tree.add_clip_chain_descriptor(info.id, info.parent, items); + let parent = info.parent.map(|id| + self.id_to_index_mapper.map_clip_id(&ClipId::ClipChain(id)) + ); + let clip_chain_index = + self.clip_scroll_tree.add_clip_chain_descriptor(parent, items); + self.id_to_index_mapper.add(ClipId::ClipChain(info.id), clip_chain_index); }, SpecificDisplayItem::ScrollFrame(ref info) => { self.flatten_scroll_frame( @@ -610,12 +673,14 @@ impl<'a> FlattenContext<'a> { info.horizontal_offset_bounds, info.previously_applied_offset, ); + let parent_id = clip_and_scroll.scroll_node_id; self.clip_scroll_tree.add_sticky_frame( info.id, - clip_and_scroll.scroll_node_id, /* parent id */ + parent_id, frame_rect, sticky_frame_info ); + self.id_to_index_mapper.map_to_parent_clip_chain(info.id, &parent_id); } // Do nothing; these are dummy items for the display list parser @@ -650,7 +715,7 @@ impl<'a> FlattenContext<'a> { /// takes care of the decomposition required by the internal tiling of the image. fn decompose_image( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, prim_info: &LayerPrimitiveInfo, info: &ImageDisplayItem, image_size: DeviceUintSize, @@ -696,7 +761,7 @@ impl<'a> FlattenContext<'a> { fn decompose_image_row( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, prim_info: &LayerPrimitiveInfo, info: &ImageDisplayItem, image_size: DeviceUintSize, @@ -742,7 +807,7 @@ impl<'a> FlattenContext<'a> { fn decompose_tiled_image( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, prim_info: &LayerPrimitiveInfo, info: &ImageDisplayItem, image_size: DeviceUintSize, @@ -878,7 +943,7 @@ impl<'a> FlattenContext<'a> { fn add_tile_primitive( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, prim_info: &LayerPrimitiveInfo, info: &ImageDisplayItem, tile_offset: TileOffset, @@ -1056,6 +1121,7 @@ impl FrameContext { pipeline_epochs: Vec::new(), replacements: Vec::new(), output_pipelines, + id_to_index_mapper: ClipIdToIndexMapper::new(), }; roller.builder.push_root( @@ -1063,6 +1129,7 @@ impl FrameContext { &root_pipeline.viewport_size, &root_pipeline.content_size, roller.clip_scroll_tree, + &mut roller.id_to_index_mapper, ); roller.builder.setup_viewport_offset( diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index 8611d6e32d..a72fbb85c0 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -2,35 +2,34 @@ * 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::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipAndScrollInfo}; -use api::{ClipId, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale}; -use api::{DeviceUintPoint, DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode}; -use api::{ExternalScrollId, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey}; -use api::{ImageRendering, ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize}; -use api::{LayerTransform, LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation}; -use api::{LineStyle, LocalClip, PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode}; -use api::{ScrollSensitivity, Shadow, TexelRect, TileOffset, TransformStyle, WorldPoint}; -use api::{WorldToLayerTransform, YuvColorSpace, YuvData}; +use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayList, ClipId, ColorF}; +use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale, DeviceUintPoint}; +use api::{DeviceUintRect, DeviceUintSize, DocumentLayer, Epoch, ExtendMode, ExternalScrollId}; +use api::{FontRenderMode, GlyphInstance, GlyphOptions, GradientStop, ImageKey, ImageRendering}; +use api::{ItemRange, LayerPoint, LayerPrimitiveInfo, LayerRect, LayerSize, LayerTransform}; +use api::{LayerVector2D, LayoutTransform, LayoutVector2D, LineOrientation, LineStyle, LocalClip}; +use api::{PipelineId, PremultipliedColorF, PropertyBinding, RepeatMode, ScrollSensitivity, Shadow}; +use api::{TexelRect, TileOffset, TransformStyle, WorldPoint, WorldToLayerTransform, YuvColorSpace}; +use api::YuvData; use app_units::Au; use border::ImageBorderSegment; -use clip::{ClipRegion, ClipSource, ClipSources, ClipStore}; +use clip::{ClipChain, ClipRegion, ClipSource, ClipSources, ClipStore}; use clip_scroll_node::{ClipScrollNode, NodeType}; -use clip_scroll_tree::ClipScrollTree; +use clip_scroll_tree::{ClipScrollTree, ClipChainIndex}; use euclid::{SideOffsets2D, vec2}; -use frame::FrameId; +use frame::{FrameId, ClipIdToIndexMapper}; use glyph_rasterizer::FontInstance; use gpu_cache::GpuCache; use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType}; use hit_test::{HitTester, HitTestingItem, HitTestingRun}; use internal_types::{FastHashMap, FastHashSet}; use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface}; -use prim_store::{BrushKind, BrushPrimitive, ImageCacheKey}; -use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, ImageSource, PrimitiveKind}; -use prim_store::{PrimitiveContainer, PrimitiveIndex}; -use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu}; -use prim_store::{BrushSegmentDescriptor, PrimitiveRun, TextRunPrimitiveCpu}; +use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, GradientPrimitiveCpu}; +use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer}; +use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore}; +use prim_store::{RadialGradientPrimitiveCpu, ScrollNodeAndClipChain, TextRunPrimitiveCpu}; use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters}; -use render_task::{ClearMode, ClipChain, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree}; +use render_task::{ClearMode, RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree}; use resource_cache::{ImageRequest, ResourceCache}; use scene::{ScenePipeline, SceneProperties}; use std::{mem, usize, f32}; @@ -90,10 +89,10 @@ pub struct FrameBuilder { // A stack of the current shadow primitives. // The sub-Vec stores a buffer of fast-path primitives to be appended on pop. - shadow_prim_stack: Vec<(PrimitiveIndex, Vec<(PrimitiveIndex, ClipAndScrollInfo)>)>, + shadow_prim_stack: Vec<(PrimitiveIndex, Vec<(PrimitiveIndex, ScrollNodeAndClipChain)>)>, // If we're doing any fast-path shadows, we buffer the "real" // content here, to be appended when the shadow stack is empty. - pending_shadow_contents: Vec<(PrimitiveIndex, ClipAndScrollInfo, LayerPrimitiveInfo)>, + pending_shadow_contents: Vec<(PrimitiveIndex, ScrollNodeAndClipChain, LayerPrimitiveInfo)>, scrollbar_prims: Vec, @@ -150,14 +149,14 @@ impl PictureState { } pub struct PrimitiveRunContext<'a> { - pub clip_chain: Option<&'a ClipChain>, + pub clip_chain: &'a ClipChain, pub scroll_node: &'a ClipScrollNode, pub clip_chain_rect_index: ClipChainRectIndex, } impl<'a> PrimitiveRunContext<'a> { pub fn new( - clip_chain: Option<&'a ClipChain>, + clip_chain: &'a ClipChain, scroll_node: &'a ClipScrollNode, clip_chain_rect_index: ClipChainRectIndex, ) -> Self { @@ -252,7 +251,7 @@ impl FrameBuilder { pub fn add_primitive_to_hit_testing_list( &mut self, info: &LayerPrimitiveInfo, - clip_and_scroll: ClipAndScrollInfo + clip_and_scroll: ScrollNodeAndClipChain ) { let tag = match info.tag { Some(tag) => tag, @@ -276,7 +275,7 @@ impl FrameBuilder { pub fn add_primitive_to_draw_list( &mut self, prim_index: PrimitiveIndex, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, ) { // Add primitive to the top-most Picture on the stack. // TODO(gw): Let's consider removing the extra indirection @@ -294,7 +293,7 @@ impl FrameBuilder { /// to the draw list. pub fn add_primitive( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, clip_sources: Vec, container: PrimitiveContainer, @@ -313,7 +312,7 @@ impl FrameBuilder { transform_style: TransformStyle, is_backface_visible: bool, is_pipeline_root: bool, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, output_pipelines: &FastHashSet, ) { // Construct the necessary set of Picture primitives @@ -640,6 +639,7 @@ impl FrameBuilder { source_perspective: Option, origin_in_parent_reference_frame: LayerVector2D, clip_scroll_tree: &mut ClipScrollTree, + id_to_index_mapper: &mut ClipIdToIndexMapper, ) { let node = ClipScrollNode::new_reference_frame( parent_id, @@ -651,6 +651,12 @@ impl FrameBuilder { ); clip_scroll_tree.add_node(node, reference_frame_id); self.reference_frame_stack.push(reference_frame_id); + + match parent_id { + Some(ref parent_id) => + id_to_index_mapper.map_to_parent_clip_chain(reference_frame_id, parent_id), + _ => id_to_index_mapper.add(reference_frame_id, ClipChainIndex(0)), + } } pub fn current_reference_frame_id(&self) -> ClipId { @@ -682,6 +688,7 @@ impl FrameBuilder { viewport_size: &LayerSize, content_size: &LayerSize, clip_scroll_tree: &mut ClipScrollTree, + id_to_index_mapper: &mut ClipIdToIndexMapper, ) -> ClipId { let viewport_rect = LayerRect::new(LayerPoint::zero(), *viewport_size); self.push_reference_frame( @@ -693,6 +700,7 @@ impl FrameBuilder { None, LayerVector2D::zero(), clip_scroll_tree, + id_to_index_mapper, ); let topmost_scrolling_node_id = ClipId::root_scroll_node(pipeline_id); @@ -707,6 +715,7 @@ impl FrameBuilder { content_size, ScrollSensitivity::ScriptAndInputEvents, clip_scroll_tree, + id_to_index_mapper, ); topmost_scrolling_node_id @@ -716,18 +725,23 @@ impl FrameBuilder { &mut self, new_node_id: ClipId, parent_id: ClipId, - pipeline_id: PipelineId, clip_region: ClipRegion, clip_scroll_tree: &mut ClipScrollTree, + id_to_index_mapper: &mut ClipIdToIndexMapper, ) { let clip_rect = clip_region.main; let clip_sources = ClipSources::from(clip_region); - debug_assert!(clip_sources.has_clips()); + debug_assert!(clip_sources.has_clips()); let handle = self.clip_store.insert(clip_sources); - let node = ClipScrollNode::new_clip_node(pipeline_id, parent_id, handle, clip_rect); - clip_scroll_tree.add_node(node, new_node_id); + let clip_chain_index = clip_scroll_tree.add_clip_node( + new_node_id, + parent_id, + handle, + clip_rect + ); + id_to_index_mapper.add(new_node_id, clip_chain_index); } pub fn add_scroll_frame( @@ -740,6 +754,7 @@ impl FrameBuilder { content_size: &LayerSize, scroll_sensitivity: ScrollSensitivity, clip_scroll_tree: &mut ClipScrollTree, + id_to_index_mapper: &mut ClipIdToIndexMapper, ) { let node = ClipScrollNode::new_scroll_frame( pipeline_id, @@ -751,6 +766,7 @@ impl FrameBuilder { ); clip_scroll_tree.add_node(node, new_node_id); + id_to_index_mapper.map_to_parent_clip_chain(new_node_id, &parent_id); } pub fn pop_reference_frame(&mut self) { @@ -760,7 +776,7 @@ impl FrameBuilder { pub fn push_shadow( &mut self, shadow: Shadow, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, ) { let pipeline_id = self.sc_stack.last().unwrap().pipeline_id; @@ -804,7 +820,7 @@ impl FrameBuilder { pub fn add_solid_rectangle( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, color: ColorF, segments: Option, @@ -833,7 +849,7 @@ impl FrameBuilder { pub fn add_clear_rectangle( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, ) { let prim = BrushPrimitive::new( @@ -851,7 +867,7 @@ impl FrameBuilder { pub fn add_scroll_bar( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, color: ColorF, scrollbar_info: ScrollbarInfo, @@ -883,7 +899,7 @@ impl FrameBuilder { pub fn add_line( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, wavy_line_thickness: f32, orientation: LineOrientation, @@ -970,7 +986,7 @@ impl FrameBuilder { pub fn add_border( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, border_item: &BorderDisplayItem, gradient_stops: ItemRange, @@ -1222,7 +1238,7 @@ impl FrameBuilder { pub fn add_gradient( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, start_point: LayerPoint, end_point: LayerPoint, @@ -1292,7 +1308,7 @@ impl FrameBuilder { fn add_radial_gradient_impl( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, start_center: LayerPoint, start_radius: f32, @@ -1331,7 +1347,7 @@ impl FrameBuilder { pub fn add_radial_gradient( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, start_center: LayerPoint, start_radius: f32, @@ -1380,7 +1396,7 @@ impl FrameBuilder { pub fn add_text( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, run_offset: LayoutVector2D, info: &LayerPrimitiveInfo, font: &FontInstance, @@ -1536,7 +1552,7 @@ impl FrameBuilder { pub fn add_image( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, stretch_size: LayerSize, mut tile_spacing: LayerSize, @@ -1616,7 +1632,7 @@ impl FrameBuilder { pub fn add_yuv_image( &mut self, - clip_and_scroll: ClipAndScrollInfo, + clip_and_scroll: ScrollNodeAndClipChain, info: &LayerPrimitiveInfo, yuv_data: YuvData, color_space: YuvColorSpace, diff --git a/webrender/src/hit_test.rs b/webrender/src/hit_test.rs index 55b9fa90b8..d4b7b2b689 100644 --- a/webrender/src/hit_test.rs +++ b/webrender/src/hit_test.rs @@ -2,13 +2,14 @@ * 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::{BorderRadius, ClipAndScrollInfo, ClipId, ClipMode, HitTestFlags, HitTestItem}; -use api::{HitTestResult, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect}; -use api::{LayerToWorldTransform, LocalClip, PipelineId, WorldPoint}; +use api::{BorderRadius, ClipId, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag}; +use api::{LayerPoint, LayerPrimitiveInfo, LayerRect, LayerToWorldTransform, LocalClip, PipelineId}; +use api::WorldPoint; use clip::{ClipSource, ClipStore, Contains, rounded_rectangle_contains_point}; use clip_scroll_node::{ClipScrollNode, NodeType}; -use clip_scroll_tree::ClipScrollTree; +use clip_scroll_tree::{ClipChainIndex, ClipScrollTree}; use internal_types::FastHashMap; +use prim_store::ScrollNodeAndClipChain; /// A copy of important clip scroll node data to use during hit testing. This a copy of /// data from the ClipScrollTree that will persist as a new frame is under construction, @@ -33,11 +34,21 @@ pub struct HitTestClipScrollNode { /// handled the same way during hit testing. Once we represent all ClipChains /// using ClipChainDescriptors, we can get rid of this and just use the /// ClipChainDescriptor here. +#[derive(Clone)] struct HitTestClipChainDescriptor { - parent: Option, + parent: Option, clips: Vec, } +impl HitTestClipChainDescriptor { + fn empty() -> HitTestClipChainDescriptor { + HitTestClipChainDescriptor { + parent: None, + clips: Vec::new(), + } + } +} + #[derive(Clone)] pub struct HitTestingItem { rect: LayerRect, @@ -56,7 +67,7 @@ impl HitTestingItem { } #[derive(Clone)] -pub struct HitTestingRun(pub Vec, pub ClipAndScrollInfo); +pub struct HitTestingRun(pub Vec, pub ScrollNodeAndClipChain); enum HitTestRegion { Rectangle(LayerRect), @@ -78,7 +89,7 @@ impl HitTestRegion { pub struct HitTester { runs: Vec, nodes: FastHashMap, - clip_chains: FastHashMap, + clip_chains: Vec, } impl HitTester { @@ -90,7 +101,7 @@ impl HitTester { let mut hit_tester = HitTester { runs: runs.clone(), nodes: FastHashMap::default(), - clip_chains: FastHashMap::default(), + clip_chains: Vec::new(), }; hit_tester.read_clip_scroll_tree(clip_scroll_tree, clip_store); hit_tester @@ -102,6 +113,11 @@ impl HitTester { clip_store: &ClipStore ) { self.nodes.clear(); + self.clip_chains.clear(); + self.clip_chains.resize( + clip_scroll_tree.clip_chains.len(), + HitTestClipChainDescriptor::empty() + ); for (id, node) in &clip_scroll_tree.nodes { self.nodes.insert(*id, HitTestClipScrollNode { @@ -111,52 +127,50 @@ impl HitTester { node_origin: node.local_viewport_rect.origin, }); - self.clip_chains.insert(*id, HitTestClipChainDescriptor { - parent: node.parent, - clips: vec![*id], - }); + if let NodeType::Clip { clip_chain_index, .. } = node.node_type { + let clip_chain = self.clip_chains.get_mut(clip_chain_index.0).unwrap(); + clip_chain.parent = + clip_scroll_tree.get_clip_chain(clip_chain_index).parent_index; + clip_chain.clips = vec![*id]; + } } for descriptor in &clip_scroll_tree.clip_chains_descriptors { - self.clip_chains.insert( - ClipId::ClipChain(descriptor.id), - HitTestClipChainDescriptor { - parent: descriptor.parent.map(|id| ClipId::ClipChain(id)), - clips: descriptor.clips.clone(), - } - ); + let clip_chain = self.clip_chains.get_mut(descriptor.index.0).unwrap(); + clip_chain.parent = clip_scroll_tree.get_clip_chain(descriptor.index).parent_index; + clip_chain.clips = descriptor.clips.clone(); } } fn is_point_clipped_in_for_clip_chain( &self, point: WorldPoint, - chain_id: &ClipId, + clip_chain_index: ClipChainIndex, test: &mut HitTest ) -> bool { - if let Some(result) = test.clip_chain_cache.get(&chain_id) { - return *result; + if let Some(result) = test.get_from_clip_chain_cache(clip_chain_index) { + return result; } - let descriptor = &self.clip_chains[&chain_id]; + let descriptor = &self.clip_chains[clip_chain_index.0]; let parent_clipped_in = match descriptor.parent { None => true, - Some(ref parent) => self.is_point_clipped_in_for_clip_chain(point, parent, test), + Some(parent) => self.is_point_clipped_in_for_clip_chain(point, parent, test), }; if !parent_clipped_in { - test.clip_chain_cache.insert(*chain_id, false); + test.set_in_clip_chain_cache(clip_chain_index, false); return false; } for clip_node in &descriptor.clips { if !self.is_point_clipped_in_for_node(point, clip_node, test) { - test.clip_chain_cache.insert(*chain_id, false); + test.set_in_clip_chain_cache(clip_chain_index, false); return false; } } - test.clip_chain_cache.insert(*chain_id, true); + test.set_in_clip_chain_cache(clip_chain_index, true); true } @@ -197,7 +211,9 @@ impl HitTester { let mut result = HitTestResult::default(); for &HitTestingRun(ref items, ref clip_and_scroll) in self.runs.iter().rev() { - let scroll_node = &self.nodes[&clip_and_scroll.scroll_node_id]; + let scroll_node_id = clip_and_scroll.scroll_node_id; + let scroll_node = &self.nodes[&scroll_node_id]; + let pipeline_id = scroll_node_id.pipeline_id(); match (test.pipeline_id, clip_and_scroll.scroll_node_id.pipeline_id()) { (Some(id), node_id) if node_id != id => continue, _ => {}, @@ -215,12 +231,11 @@ impl HitTester { continue; } - let clip_id = &clip_and_scroll.clip_node_id(); + let clip_chain_index = clip_and_scroll.clip_chain_index; + clipped_in |= + self.is_point_clipped_in_for_clip_chain(point, clip_chain_index, &mut test); if !clipped_in { - clipped_in = self.is_point_clipped_in_for_clip_chain(point, clip_id, &mut test); - if !clipped_in { - break; - } + break; } // We need to trigger a lookup against the root reference frame here, because @@ -228,7 +243,7 @@ impl HitTester { // hierarchy. If we don't have a valid point for this test, we are likely // in a situation where the reference frame has an univertible transform, but the // item's clip does not. - let root_reference_frame = ClipId::root_reference_frame(clip_id.pipeline_id()); + let root_reference_frame = ClipId::root_reference_frame(pipeline_id); if !self.is_point_clipped_in_for_node(point, &root_reference_frame, &mut test) { continue; } @@ -238,7 +253,7 @@ impl HitTester { }; result.items.push(HitTestItem { - pipeline: clip_and_scroll.clip_node_id().pipeline_id(), + pipeline: pipeline_id, tag: item.tag, point_in_viewport, point_relative_to_item: point_in_layer - item.rect.origin.to_vector(), @@ -259,7 +274,7 @@ fn get_regions_for_clip_scroll_node( clip_store: &ClipStore ) -> Vec { let clips = match node.node_type { - NodeType::Clip(ref handle) => clip_store.get(handle).clips(), + NodeType::Clip{ ref handle, .. } => clip_store.get(handle).clips(), _ => return Vec::new(), }; @@ -280,7 +295,7 @@ pub struct HitTest { point: WorldPoint, flags: HitTestFlags, node_cache: FastHashMap>, - clip_chain_cache: FastHashMap, + clip_chain_cache: Vec>, } impl HitTest { @@ -294,8 +309,23 @@ impl HitTest { point, flags, node_cache: FastHashMap::default(), - clip_chain_cache: FastHashMap::default(), + clip_chain_cache: Vec::new(), + } + } + + pub fn get_from_clip_chain_cache(&mut self, index: ClipChainIndex) -> Option { + if index.0 >= self.clip_chain_cache.len() { + None + } else { + self.clip_chain_cache[index.0] + } + } + + pub fn set_in_clip_chain_cache(&mut self, index: ClipChainIndex, value: bool) { + if index.0 >= self.clip_chain_cache.len() { + self.clip_chain_cache.resize(index.0 + 1, None); } + self.clip_chain_cache[index.0] = Some(value); } pub fn get_absolute_point(&self, hit_tester: &HitTester) -> WorldPoint { diff --git a/webrender/src/picture.rs b/webrender/src/picture.rs index 2bc77803eb..8abf253d82 100644 --- a/webrender/src/picture.rs +++ b/webrender/src/picture.rs @@ -2,15 +2,15 @@ * 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, ClipAndScrollInfo, FilterOp, MixBlendMode}; -use api::{DeviceIntPoint, DeviceIntRect, LayerToWorldScale, PipelineId}; -use api::{BoxShadowClipMode, LayerPoint, LayerRect, LayerVector2D, Shadow}; -use api::{ClipId, PremultipliedColorF}; +use api::{BoxShadowClipMode, ClipId, ColorF, DeviceIntPoint, DeviceIntRect, FilterOp, LayerPoint}; +use api::{LayerRect, LayerToWorldScale, LayerVector2D, MixBlendMode, PipelineId}; +use api::{PremultipliedColorF, Shadow}; use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowCacheKey}; use frame_builder::{FrameContext, FrameState, PictureState}; use gpu_cache::GpuDataRequest; use gpu_types::{BrushImageKind, PictureType}; use prim_store::{BrushKind, BrushPrimitive, PrimitiveIndex, PrimitiveRun, PrimitiveRunLocalRect}; +use prim_store::ScrollNodeAndClipChain; use render_task::{ClearMode, RenderTask, RenderTaskCacheKey}; use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation}; use resource_cache::CacheItem; @@ -230,7 +230,7 @@ impl PicturePrimitive { pub fn add_primitive( &mut self, prim_index: PrimitiveIndex, - clip_and_scroll: ClipAndScrollInfo + clip_and_scroll: ScrollNodeAndClipChain ) { if let Some(ref mut run) = self.runs.last_mut() { if run.clip_and_scroll == clip_and_scroll && diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index df94e9bcf6..c153e5bd5a 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -2,25 +2,24 @@ * 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::{AlphaType, BorderRadius, BuiltDisplayList, ClipAndScrollInfo, ClipMode}; -use api::{ColorF, DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch}; -use api::{ComplexClipRegion, ExtendMode, FontRenderMode}; +use api::{AlphaType, BorderRadius, BuiltDisplayList, ClipId, ClipMode, ColorF, ComplexClipRegion}; +use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode, FontRenderMode}; use api::{GlyphInstance, GlyphKey, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag}; use api::{LayerPoint, LayerRect, LayerSize, LayerToWorldTransform, LayerVector2D, LineOrientation}; -use api::{LineStyle, PremultipliedColorF}; -use api::{WorldToLayerTransform, YuvColorSpace, YuvFormat}; +use api::{LineStyle, PremultipliedColorF, WorldToLayerTransform, YuvColorSpace, YuvFormat}; use border::{BorderCornerInstance, BorderEdgeKind}; -use clip_scroll_tree::{CoordinateSystemId}; +use clip_scroll_tree::{ClipChainIndex, CoordinateSystemId}; use clip_scroll_node::ClipScrollNode; -use clip::{ClipSource, ClipSourcesHandle}; +use clip::{ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipSource}; +use clip::{ClipSourcesHandle, ClipWorkItem}; use frame_builder::{FrameContext, FrameState, PictureContext, PictureState, PrimitiveRunContext}; use glyph_rasterizer::{FontInstance, FontTransform}; use gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpuBlocks}; use gpu_types::{ClipChainRectIndex}; use picture::{PictureKind, PicturePrimitive}; -use render_task::{BlitSource, ClipChain, ClipChainNode, ClipChainNodeIter, ClipChainNodeRef, ClipWorkItem}; -use render_task::{RenderTask, RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId}; +use render_task::{BlitSource, RenderTask, RenderTaskCacheKey, RenderTaskCacheKeyKind}; +use render_task::RenderTaskId; use renderer::{MAX_VERTEX_TEXTURE_WIDTH}; use resource_cache::{CacheItem, ImageProperties, ImageRequest, ResourceCache}; use segment::SegmentBuilder; @@ -32,11 +31,23 @@ use util::recycle_vec; const MIN_BRUSH_SPLIT_AREA: f32 = 128.0 * 128.0; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ScrollNodeAndClipChain { + pub scroll_node_id: ClipId, + pub clip_chain_index: ClipChainIndex, +} + +impl ScrollNodeAndClipChain { + pub fn new(scroll_node_id: ClipId, clip_chain_index: ClipChainIndex) -> ScrollNodeAndClipChain { + ScrollNodeAndClipChain { scroll_node_id, clip_chain_index } + } +} + #[derive(Debug)] pub struct PrimitiveRun { pub base_prim_index: PrimitiveIndex, pub count: usize, - pub clip_and_scroll: ClipAndScrollInfo, + pub clip_and_scroll: ScrollNodeAndClipChain, } #[derive(Debug, Copy, Clone)] @@ -1602,12 +1613,9 @@ impl PrimitiveStore { } }; - let mut combined_outer_rect = match prim_run_context.clip_chain { - Some(ref chain) => prim_screen_rect.intersection(&chain.combined_outer_screen_rect), - None => Some(prim_screen_rect), - }; - - let clip_chain = prim_run_context.clip_chain.map_or(None, |x| x.nodes.clone()); + let mut combined_outer_rect = + prim_screen_rect.intersection(&prim_run_context.clip_chain.combined_outer_screen_rect); + let clip_chain = prim_run_context.clip_chain.nodes.clone(); let prim_coordinate_system_id = prim_run_context.scroll_node.coordinate_system_id; let transform = &prim_run_context.scroll_node.world_content_transform; @@ -1828,12 +1836,8 @@ impl PrimitiveStore { frame_context.device_pixel_scale, ); - let clip_bounds = match prim_run_context.clip_chain { - Some(ref node) => node.combined_outer_screen_rect, - None => frame_context.screen_rect, - }; metadata.screen_rect = screen_bounding_rect - .intersection(&clip_bounds) + .intersection(&prim_run_context.clip_chain.combined_outer_screen_rect) .map(|clipped| { ScreenRect { clipped, @@ -1903,7 +1907,7 @@ impl PrimitiveStore { .nodes[&run.clip_and_scroll.scroll_node_id]; let clip_chain = frame_context .clip_scroll_tree - .get_clip_chain(&run.clip_and_scroll.clip_node_id()); + .get_clip_chain(run.clip_and_scroll.clip_chain_index); if pic_context.perform_culling { if !scroll_node.invertible { @@ -1911,16 +1915,12 @@ impl PrimitiveStore { continue; } - match clip_chain { - Some(ref chain) if chain.combined_outer_screen_rect.is_empty() => { - debug!("{:?} {:?}: clipped out", run.base_prim_index, pic_context.pipeline_id); - continue; - } - _ => {}, + if clip_chain.combined_outer_screen_rect.is_empty() { + debug!("{:?} {:?}: clipped out", run.base_prim_index, pic_context.pipeline_id); + continue; } } - let parent_relative_transform = pic_context .inv_world_transform .map(|inv_parent| { @@ -2050,14 +2050,9 @@ fn convert_clip_chain_to_clip_vector( fn get_local_clip_rect_for_nodes( scroll_node: &ClipScrollNode, - clip_chain: Option<&ClipChain>, + clip_chain: &ClipChain, ) -> Option { - let clip_chain_nodes = match clip_chain { - Some(ref clip_chain) => clip_chain.nodes.clone(), - None => return None, - }; - - let local_rect = ClipChainNodeIter { current: clip_chain_nodes }.fold( + let local_rect = ClipChainNodeIter { current: clip_chain.nodes.clone() }.fold( None, |combined_local_clip_rect: Option, node| { if node.work_item.coordinate_system_id != scroll_node.coordinate_system_id { diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index 5ec00d078b..c5a6824129 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -2,14 +2,14 @@ * 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::{DeviceIntPoint, DeviceIntRect, DeviceIntSize}; -use api::{ImageDescriptor, ImageFormat, LayerRect, PremultipliedColorF}; +use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, ImageDescriptor, ImageFormat}; +use api::PremultipliedColorF; use box_shadow::BoxShadowCacheKey; -use clip::{ClipSourcesWeakHandle}; +use clip::ClipWorkItem; use clip_scroll_tree::CoordinateSystemId; use device::TextureFilter; use gpu_cache::GpuCache; -use gpu_types::{ClipScrollNodeIndex, PictureType}; +use gpu_types::PictureType; use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture}; use picture::ContentOrigin; use prim_store::{PrimitiveIndex, ImageCacheKey}; @@ -17,7 +17,6 @@ use prim_store::{PrimitiveIndex, ImageCacheKey}; use print_tree::{PrintTreePrinter}; use resource_cache::CacheItem; use std::{cmp, ops, usize, f32, i32}; -use std::rc::Rc; use texture_cache::{TextureCache, TextureCacheHandle}; use tiling::{RenderPass, RenderTargetIndex}; use tiling::{RenderTargetKind}; @@ -46,91 +45,6 @@ pub struct RenderTaskTree { next_saved: SavedTargetIndex, } -pub type ClipChainNodeRef = Option>; - -#[derive(Debug, Clone)] -pub struct ClipChainNode { - pub work_item: ClipWorkItem, - pub local_clip_rect: LayerRect, - pub screen_outer_rect: DeviceIntRect, - pub screen_inner_rect: DeviceIntRect, - pub prev: ClipChainNodeRef, -} - -#[derive(Debug, Clone)] -pub struct ClipChain { - pub combined_outer_screen_rect: DeviceIntRect, - pub combined_inner_screen_rect: DeviceIntRect, - pub nodes: ClipChainNodeRef, -} - -impl ClipChain { - pub fn empty(screen_rect: &DeviceIntRect) -> ClipChain { - ClipChain { - combined_inner_screen_rect: *screen_rect, - combined_outer_screen_rect: *screen_rect, - nodes: None, - } - } - - pub fn new_with_added_node( - &self, - work_item: ClipWorkItem, - local_clip_rect: LayerRect, - screen_outer_rect: DeviceIntRect, - screen_inner_rect: DeviceIntRect, - ) -> ClipChain { - let new_node = ClipChainNode { - work_item, - local_clip_rect, - screen_outer_rect, - screen_inner_rect, - prev: None, - }; - - let mut new_chain = self.clone(); - new_chain.add_node(new_node); - new_chain - } - - pub fn add_node(&mut self, mut new_node: ClipChainNode) { - new_node.prev = self.nodes.clone(); - - // If this clip's outer rectangle is completely enclosed by the clip - // chain's inner rectangle, then the only clip that matters from this point - // on is this clip. We can disconnect this clip from the parent clip chain. - if self.combined_inner_screen_rect.contains_rect(&new_node.screen_outer_rect) { - new_node.prev = None; - } - - self.combined_outer_screen_rect = - self.combined_outer_screen_rect.intersection(&new_node.screen_outer_rect) - .unwrap_or_else(DeviceIntRect::zero); - self.combined_inner_screen_rect = - self.combined_inner_screen_rect.intersection(&new_node.screen_inner_rect) - .unwrap_or_else(DeviceIntRect::zero); - - self.nodes = Some(Rc::new(new_node)); - } -} - -pub struct ClipChainNodeIter { - pub current: ClipChainNodeRef, -} - -impl Iterator for ClipChainNodeIter { - type Item = Rc; - - fn next(&mut self) -> ClipChainNodeRef { - let previous = self.current.clone(); - self.current = match self.current { - Some(ref item) => item.prev.clone(), - None => return None, - }; - previous - } -} - impl RenderTaskTree { pub fn new() -> Self { RenderTaskTree { @@ -231,15 +145,6 @@ pub enum RenderTaskLocation { TextureCache(SourceTexture, i32, DeviceIntRect), } -#[derive(Debug, Clone)] -#[cfg_attr(feature = "capture", derive(Serialize))] -#[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct ClipWorkItem { - pub scroll_node_data_index: ClipScrollNodeIndex, - pub clip_sources: ClipSourcesWeakHandle, - pub coordinate_system_id: CoordinateSystemId, -} - #[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))]