From a71585e957ce8ea8530d0222f5b4a79988bedf35 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Mon, 13 Mar 2017 13:40:04 +0100 Subject: [PATCH] Remove ServoScrollRootId Remove the concept of ServoScrollRootId and just wrap up external ids into ScrollLayerId. This will allow API clients to specify ids without having to do complicated bookkeeping when building display lists. In addition, this makes the code much simpler. This is a major API break because clips cannot share the same id. This is only possible because now Servo does not need to split scroll layers / clips. --- Cargo.lock | 14 ++-- webrender/Cargo.toml | 2 +- webrender/src/clip_scroll_node.rs | 19 +++-- webrender/src/clip_scroll_tree.rs | 112 ++++++--------------------- webrender/src/frame.rs | 14 +--- webrender/src/frame_builder.rs | 8 +- webrender/src/render_backend.rs | 6 +- webrender_traits/Cargo.toml | 2 +- webrender_traits/src/api.rs | 24 +++--- webrender_traits/src/display_item.rs | 52 ++++++------- webrender_traits/src/display_list.rs | 21 ++--- wrench/src/wrench.rs | 9 +-- wrench/src/yaml_frame_reader.rs | 41 ++++------ wrench/src/yaml_frame_writer.rs | 65 +++++++++++----- 14 files changed, 159 insertions(+), 230 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e37f883e38..7e1dd0c3ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,8 +21,8 @@ dependencies = [ "serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.24.0", - "webrender_traits 0.25.0", + "webrender 0.25.0", + "webrender_traits 0.26.0", "yaml-rust 0.3.4 (git+https://github.com/vvuk/yaml-rust)", ] @@ -886,7 +886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "webrender" -version = "0.24.0" +version = "0.25.0" dependencies = [ "angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)", "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -909,12 +909,12 @@ dependencies = [ "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender_traits 0.25.0", + "webrender_traits 0.26.0", ] [[package]] name = "webrender_traits" -version = "0.25.0" +version = "0.26.0" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -947,8 +947,8 @@ dependencies = [ "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "servo-glutin 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webrender 0.24.0", - "webrender_traits 0.25.0", + "webrender 0.25.0", + "webrender_traits 0.26.0", ] [[package]] diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index fe01433b37..ef576dde0c 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender" -version = "0.24.0" +version = "0.25.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender/src/clip_scroll_node.rs b/webrender/src/clip_scroll_node.rs index ed6a3c07ea..1adf6a2cdb 100644 --- a/webrender/src/clip_scroll_node.rs +++ b/webrender/src/clip_scroll_node.rs @@ -13,7 +13,7 @@ use util::TransformedRect; use webrender_traits::{ClipRegion, LayerPixel, LayerPoint, LayerRect, LayerSize}; use webrender_traits::{LayerToScrollTransform, LayerToWorldTransform, PipelineId}; use webrender_traits::{ScrollEventPhase, ScrollLayerId, ScrollLayerRect, ScrollLocation}; -use webrender_traits::{ServoScrollRootId, WorldPoint, WorldPoint4D}; +use webrender_traits::{WorldPoint, WorldPoint4D}; #[cfg(target_os = "macos")] const CAN_OVERSCROLL: bool = true; @@ -38,17 +38,12 @@ pub struct ClipInfo { /// which depends on the screen rectangle and the transformation of all of /// the parents. pub xf_rect: Option, - - /// An external identifier that is used to scroll this clipping node - /// from the API. - pub scroll_root_id: Option, } impl ClipInfo { pub fn new(clip_region: &ClipRegion, clip_store: &mut VertexDataStore, - packed_layer_index: PackedLayerIndex, - scroll_root_id: Option) + packed_layer_index: PackedLayerIndex,) -> ClipInfo { // We pass true here for the MaskCacheInfo because this type of // mask needs an extra clip for the clip rectangle. @@ -58,7 +53,6 @@ impl ClipInfo { clip_source: clip_source, packed_layer_index: packed_layer_index, xf_rect: None, - scroll_root_id: scroll_root_id, } } @@ -195,6 +189,15 @@ impl ClipScrollNode { } pub fn set_scroll_origin(&mut self, origin: &LayerPoint) -> bool { + match self.node_type { + NodeType::ReferenceFrame(_) => { + warn!("Tried to scroll a reference frame."); + return false; + } + NodeType::Clip(_) => {} + }; + + let scrollable_height = self.scrollable_height(); let scrollable_width = self.scrollable_width(); if scrollable_height <= 0. && scrollable_width <= 0. { diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index 4e3d7df17c..541ab7db9b 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -7,15 +7,14 @@ use fnv::FnvHasher; use std::collections::{HashMap, HashSet}; use std::hash::BuildHasherDefault; use webrender_traits::{LayerPoint, LayerRect, LayerToScrollTransform, LayerToWorldTransform}; -use webrender_traits::{PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerInfo}; -use webrender_traits::{ScrollLayerRect, ScrollLayerState, ScrollLocation, ServoScrollRootId}; -use webrender_traits::{WorldPoint, as_scroll_parent_rect}; +use webrender_traits::{PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerRect}; +use webrender_traits::{ScrollLayerState, ScrollLocation, WorldPoint, as_scroll_parent_rect}; pub type ScrollStates = HashMap>; pub struct ClipScrollTree { pub nodes: HashMap>, - pub pending_scroll_offsets: HashMap<(PipelineId, ServoScrollRootId), LayerPoint>, + pub pending_scroll_offsets: HashMap, /// The ScrollLayerId of the currently scrolling node. Used to allow the same /// node to scroll even if a touch operation leaves the boundaries of that node. @@ -90,7 +89,7 @@ impl ClipScrollTree { } } - if let ScrollLayerInfo::ReferenceFrame(_) = scroll_layer_id.info { + if scroll_layer_id.is_reference_frame() { return None; } @@ -109,15 +108,10 @@ impl ClipScrollTree { pub fn get_scroll_node_state(&self) -> Vec { let mut result = vec![]; - for (_, node) in self.nodes.iter() { + for (id, node) in self.nodes.iter() { match node.node_type { - NodeType::Clip(ref info) if info.scroll_root_id.is_some() => { - result.push(ScrollLayerState { - pipeline_id: node.pipeline_id, - scroll_root_id: info.scroll_root_id.unwrap(), - scroll_offset: node.scrolling.offset, - }) - } + NodeType::Clip(_) => result.push( + ScrollLayerState { id: *id, scroll_offset: node.scrolling.offset }), _ => {}, } } @@ -129,7 +123,7 @@ impl ClipScrollTree { let mut scroll_states = HashMap::with_hasher(Default::default()); for (layer_id, old_node) in &mut self.nodes.drain() { - if !self.pipelines_to_discard.contains(&layer_id.pipeline_id) { + if !self.pipelines_to_discard.contains(&layer_id.pipeline_id()) { scroll_states.insert(layer_id, old_node.scrolling); } } @@ -138,40 +132,24 @@ impl ClipScrollTree { scroll_states } - pub fn scroll_nodes(&mut self, - origin: LayerPoint, - pipeline_id: PipelineId, - scroll_root_id: ServoScrollRootId) - -> bool { - if self.nodes.is_empty() { - self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin); + pub fn scroll_nodes(&mut self, origin: LayerPoint, id: ScrollLayerId) -> bool { + if id.is_reference_frame() { + warn!("Tried to scroll a reference frame."); return false; } - let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0)); - - let mut scrolled_a_node = false; - let mut found_node = false; - for (layer_id, node) in self.nodes.iter_mut() { - if layer_id.pipeline_id != pipeline_id { - continue; - } - - match node.node_type { - NodeType::Clip(ref info) if info.scroll_root_id != Some(scroll_root_id) => continue, - NodeType::ReferenceFrame(..) => continue, - NodeType::Clip(_) => {}, - } - - found_node = true; - scrolled_a_node |= node.set_scroll_origin(&origin); + if self.nodes.is_empty() { + self.pending_scroll_offsets.insert(id, origin); + return false; } - if !found_node { - self.pending_scroll_offsets.insert((pipeline_id, scroll_root_id), origin); + let origin = LayerPoint::new(origin.x.max(0.0), origin.y.max(0.0)); + if let Some(node) = self.nodes.get_mut(&id) { + return node.set_scroll_origin(&origin); } - scrolled_a_node + self.pending_scroll_offsets.insert(id, origin); + false } pub fn scroll(&mut self, @@ -244,37 +222,7 @@ impl ClipScrollTree { scroll_layer_id }; - // TODO(mrobinson): Once we remove the concept of shared scroll root ids we can remove - // this entirely and just scroll the node based on the ScrollLayerId. - let scroll_root_id = { - let node = self.nodes.get_mut(&scroll_layer_id).unwrap(); - let scroll_root_id = match node.node_type { - NodeType::Clip(ref info) => info.scroll_root_id, - NodeType::ReferenceFrame(..) => unreachable!("Tried to scroll a reference frame."), - }; - - if scroll_root_id.is_none() { - return node.scroll(scroll_location, phase); - } - - scroll_root_id - }; - - let mut scrolled_a_node = false; - for (layer_id, node) in self.nodes.iter_mut() { - if layer_id.pipeline_id != scroll_layer_id.pipeline_id { - continue; - } - - match node.node_type { - NodeType::Clip(ref info) if info.scroll_root_id == scroll_root_id => { } - _ => continue, - } - - let scrolled_this_node = node.scroll(scroll_location, phase); - scrolled_a_node = scrolled_a_node || scrolled_this_node; - } - scrolled_a_node + self.nodes.get_mut(&scroll_layer_id).unwrap().scroll(scroll_location, phase) } pub fn update_all_node_transforms(&mut self, pan: LayerPoint) { @@ -351,16 +299,7 @@ impl ClipScrollTree { node.finalize(&scrolling_state); - let scroll_root_id = match node.node_type { - NodeType::Clip(ref info) if info.scroll_root_id.is_some() => - info.scroll_root_id.unwrap(), - _ => continue, - }; - - - let pipeline_id = scroll_layer_id.pipeline_id; - if let Some(pending_offset) = - self.pending_scroll_offsets.remove(&(pipeline_id, scroll_root_id)) { + if let Some(pending_offset) = self.pending_scroll_offsets.remove(&scroll_layer_id) { node.set_scroll_origin(&pending_offset); } } @@ -373,10 +312,9 @@ impl ClipScrollTree { pipeline_id: PipelineId, parent_id: Option) -> ScrollLayerId { - let reference_frame_id = ScrollLayerId { - pipeline_id: pipeline_id, - info: ScrollLayerInfo::ReferenceFrame(self.current_reference_frame_id), - }; + + let reference_frame_id = + ScrollLayerId::ReferenceFrame(self.current_reference_frame_id, pipeline_id); self.current_reference_frame_id += 1; let node = ClipScrollNode::new_reference_frame(parent_id, @@ -403,7 +341,7 @@ impl ClipScrollTree { self.pipelines_to_discard.insert(pipeline_id); match self.current_scroll_layer_id { - Some(id) if id.pipeline_id == pipeline_id => self.current_scroll_layer_id = None, + Some(id) if id.pipeline_id() == pipeline_id => self.current_scroll_layer_id = None, _ => {} } } diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index d5c1f421fa..0d8ed3cf01 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -20,8 +20,8 @@ use webrender_traits::{AuxiliaryLists, ClipDisplayItem, ClipRegion, ColorF, Devi use webrender_traits::{DeviceUintSize, DisplayItem, Epoch, FilterOp, ImageDisplayItem, LayerPoint}; use webrender_traits::{LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform}; use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId}; -use webrender_traits::{ScrollLayerState, ScrollLocation, ScrollPolicy, ServoScrollRootId}; -use webrender_traits::{SpecificDisplayItem, StackingContext, TileOffset, WorldPoint}; +use webrender_traits::{ScrollLayerState, ScrollLocation, ScrollPolicy, SpecificDisplayItem}; +use webrender_traits::{StackingContext, TileOffset, WorldPoint}; #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] pub struct FrameId(pub u32); @@ -231,12 +231,8 @@ impl Frame { } /// Returns true if any nodes actually changed position or false otherwise. - pub fn scroll_nodes(&mut self, - origin: LayerPoint, - pipeline_id: PipelineId, - scroll_root_id: ServoScrollRootId) - -> bool { - self.clip_scroll_tree.scroll_nodes(origin, pipeline_id, scroll_root_id) + pub fn scroll_nodes(&mut self, origin: LayerPoint, id: ScrollLayerId) -> bool { + self.clip_scroll_tree.scroll_nodes(origin, id) } /// Returns true if any nodes actually changed position or false otherwise. @@ -349,7 +345,6 @@ impl Frame { pipeline_id, &clip_rect, &item.content_size, - item.scroll_root_id, clip, &mut self.clip_scroll_tree); @@ -522,7 +517,6 @@ impl Frame { pipeline_id, &LayerRect::new(LayerPoint::zero(), iframe_rect.size), &iframe_clip.main.size, - Some(ServoScrollRootId(0)), iframe_clip, &mut self.clip_scroll_tree); diff --git a/webrender/src/frame_builder.rs b/webrender/src/frame_builder.rs index 704d226eab..51ab2f3e99 100644 --- a/webrender/src/frame_builder.rs +++ b/webrender/src/frame_builder.rs @@ -33,8 +33,7 @@ use webrender_traits::{BoxShadowClipMode, ClipRegion, ColorF, DeviceIntPoint, De use webrender_traits::{DeviceIntSize, DeviceUintRect, DeviceUintSize, ExtendMode, FontKey}; use webrender_traits::{FontRenderMode, GlyphOptions, ImageKey, ImageRendering, ItemRange}; use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId}; -use webrender_traits::{RepeatMode, ScrollLayerId, ServoScrollRootId, TileOffset, WebGLContextId}; -use webrender_traits::YuvColorSpace; +use webrender_traits::{RepeatMode, ScrollLayerId, TileOffset, WebGLContextId, YuvColorSpace}; #[derive(Debug, Clone)] struct ImageBorderSegment { @@ -309,7 +308,6 @@ impl FrameBuilder { pipeline_id, &viewport_rect, content_size, - Some(ServoScrollRootId(0)), &ClipRegion::simple(&viewport_rect), clip_scroll_tree); topmost_scroll_layer_id @@ -321,13 +319,11 @@ impl FrameBuilder { pipeline_id: PipelineId, local_viewport_rect: &LayerRect, content_size: &LayerSize, - scroll_root_id: Option, clip_region: &ClipRegion, clip_scroll_tree: &mut ClipScrollTree) { let clip_info = ClipInfo::new(clip_region, &mut self.prim_store.gpu_data32, - PackedLayerIndex(self.packed_layers.len()), - scroll_root_id); + PackedLayerIndex(self.packed_layers.len())); let node = ClipScrollNode::new(pipeline_id, parent_id, local_viewport_rect, diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index e83bfd2cbd..84cc5883fb 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -260,12 +260,12 @@ impl RenderBackend { None => self.notify_compositor_of_new_scroll_frame(false), } } - ApiMsg::ScrollLayersWithScrollId(origin, pipeline_id, scroll_root_id) => { - profile_scope!("ScrollLayersWithScrollId"); + ApiMsg::ScrollLayerWithId(origin, id) => { + profile_scope!("ScrollLayerWithScrollId"); let frame = { let counters = &mut profile_counters.texture_cache; profile_counters.total_time.profile(|| { - if self.frame.scroll_nodes(origin, pipeline_id, scroll_root_id) { + if self.frame.scroll_nodes(origin, id) { Some(self.render(counters)) } else { None diff --git a/webrender_traits/Cargo.toml b/webrender_traits/Cargo.toml index b695dfd257..5b14e03b70 100644 --- a/webrender_traits/Cargo.toml +++ b/webrender_traits/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "webrender_traits" -version = "0.25.0" +version = "0.26.0" authors = ["Glenn Watson "] license = "MPL-2.0" repository = "https://github.com/servo/webrender" diff --git a/webrender_traits/src/api.rs b/webrender_traits/src/api.rs index c0b21ac859..15a3f545d2 100644 --- a/webrender_traits/src/api.rs +++ b/webrender_traits/src/api.rs @@ -6,14 +6,12 @@ use byteorder::{LittleEndian, WriteBytesExt}; use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender}; use offscreen_gl_context::{GLContextAttributes, GLLimits}; use std::cell::Cell; -use {ColorF, ImageDescriptor}; -use {FontKey, ImageKey, NativeFontHandle, ServoScrollRootId}; -use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand}; -use {DeviceIntSize, LayoutPoint, LayoutSize, WorldPoint}; -use {DeviceIntPoint, DeviceUintRect, DeviceUintSize, LayoutTransform}; -use {BuiltDisplayList, BuiltDisplayListDescriptor, AuxiliaryLists, AuxiliaryListsDescriptor}; use std::fmt; use std::marker::PhantomData; +use {AuxiliaryLists, AuxiliaryListsDescriptor, BuiltDisplayList, BuiltDisplayListDescriptor}; +use {ColorF, DeviceIntPoint, DeviceIntSize, DeviceUintRect, DeviceUintSize, FontKey}; +use {GlyphDimensions, GlyphKey, ImageData, ImageDescriptor, ImageKey, LayoutPoint, LayoutSize}; +use {LayoutTransform, NativeFontHandle, ScrollLayerId, WebGLCommand, WebGLContextId, WorldPoint}; pub type TileSize = u16; @@ -48,7 +46,7 @@ pub enum ApiMsg { SetRootPipeline(PipelineId), SetWindowParameters(DeviceUintSize, DeviceUintRect), Scroll(ScrollLocation, WorldPoint, ScrollEventPhase), - ScrollLayersWithScrollId(LayoutPoint, PipelineId, ServoScrollRootId), + ScrollLayerWithId(LayoutPoint, ScrollLayerId), TickScrollingBounce, TranslatePointToLayerSpace(WorldPoint, MsgSender<(LayoutPoint, PipelineId)>), GetScrollLayerState(MsgSender>), @@ -79,7 +77,7 @@ impl fmt::Debug for ApiMsg { &ApiMsg::SetRootDisplayList(..) => { write!(f, "ApiMsg::SetRootDisplayList") } &ApiMsg::SetRootPipeline(..) => { write!(f, "ApiMsg::SetRootPipeline") } &ApiMsg::Scroll(..) => { write!(f, "ApiMsg::Scroll") } - &ApiMsg::ScrollLayersWithScrollId(..) => { write!(f, "ApiMsg::ScrollLayersWithScrollId") } + &ApiMsg::ScrollLayerWithId(..) => { write!(f, "ApiMsg::ScrollLayerWithId") } &ApiMsg::TickScrollingBounce => { write!(f, "ApiMsg::TickScrollingBounce") } &ApiMsg::TranslatePointToLayerSpace(..) => { write!(f, "ApiMsg::TranslatePointToLayerSpace") } &ApiMsg::GetScrollLayerState(..) => { write!(f, "ApiMsg::GetScrollLayerState") } @@ -310,11 +308,8 @@ impl RenderApi { self.api_sender.send(msg).unwrap(); } - pub fn scroll_layers_with_scroll_root_id(&self, - new_scroll_origin: LayoutPoint, - pipeline_id: PipelineId, - scroll_root_id: ServoScrollRootId) { - let msg = ApiMsg::ScrollLayersWithScrollId(new_scroll_origin, pipeline_id, scroll_root_id); + pub fn scroll_layer_with_id(&self, new_scroll_origin: LayoutPoint, id: ScrollLayerId) { + let msg = ApiMsg::ScrollLayerWithId(new_scroll_origin, id); self.api_sender.send(msg).unwrap(); } @@ -436,8 +431,7 @@ pub enum ScrollEventPhase { #[derive(Clone, Deserialize, Serialize)] pub struct ScrollLayerState { - pub pipeline_id: PipelineId, - pub scroll_root_id: ServoScrollRootId, + pub id: ScrollLayerId, pub scroll_offset: LayoutPoint, } diff --git a/webrender_traits/src/display_item.rs b/webrender_traits/src/display_item.rs index 1d97a89335..e562249c55 100644 --- a/webrender_traits/src/display_item.rs +++ b/webrender_traits/src/display_item.rs @@ -46,7 +46,6 @@ pub struct ClipDisplayItem { pub content_size: LayoutSize, pub id: ScrollLayerId, pub parent_id: ScrollLayerId, - pub scroll_root_id: Option, } #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] @@ -509,48 +508,45 @@ impl ComplexClipRegion { } } -#[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct ServoScrollRootId(pub usize); - #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct ScrollLayerId { - pub pipeline_id: PipelineId, - pub info: ScrollLayerInfo, +pub enum ScrollLayerId { + Clip(usize, PipelineId), + ClipExternalId(usize, PipelineId), + ReferenceFrame(usize, PipelineId), } impl ScrollLayerId { pub fn root_scroll_layer(pipeline_id: PipelineId) -> ScrollLayerId { - ScrollLayerId { - pipeline_id: pipeline_id, - info: ScrollLayerInfo::Scrollable(0), - } + ScrollLayerId::Clip(0, pipeline_id) } pub fn root_reference_frame(pipeline_id: PipelineId) -> ScrollLayerId { - ScrollLayerId { - pipeline_id: pipeline_id, - info: ScrollLayerInfo::ReferenceFrame(0), + ScrollLayerId::ReferenceFrame(0, pipeline_id) + } + + pub fn new(id: usize, pipeline_id: PipelineId) -> ScrollLayerId { + ScrollLayerId::ClipExternalId(id, pipeline_id) + } + + pub fn pipeline_id(&self) -> PipelineId { + match *self { + ScrollLayerId::Clip(_, pipeline_id) => pipeline_id, + ScrollLayerId::ClipExternalId(_, pipeline_id) => pipeline_id, + ScrollLayerId::ReferenceFrame(_, pipeline_id) => pipeline_id, } } pub fn is_reference_frame(&self) -> bool { - match self.info { - ScrollLayerInfo::Scrollable(..) => false, - ScrollLayerInfo::ReferenceFrame(..) => true, + match *self { + ScrollLayerId::ReferenceFrame(..) => true, + _ => false, } } - pub fn new(pipeline_id: PipelineId, index: usize) -> ScrollLayerId { - ScrollLayerId { - pipeline_id: pipeline_id, - info: ScrollLayerInfo::Scrollable(index), + pub fn external_id(&self) -> Option { + match *self { + ScrollLayerId::ClipExternalId(id, _) => Some(id), + _ => None, } } } - -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub enum ScrollLayerInfo { - Scrollable(usize), - ReferenceFrame(usize), -} diff --git a/webrender_traits/src/display_list.rs b/webrender_traits/src/display_list.rs index 2f25385e8f..eff999ab17 100644 --- a/webrender_traits/src/display_list.rs +++ b/webrender_traits/src/display_list.rs @@ -11,8 +11,8 @@ use {FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem, Gradie use {IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange}; use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, MixBlendMode, PipelineId}; use {PropertyBinding, PushStackingContextDisplayItem, RadialGradient, RadialGradientDisplayItem}; -use {RectangleDisplayItem, ScrollLayerId, ScrollPolicy, ServoScrollRootId, SpecificDisplayItem}; -use {StackingContext, TextDisplayItem, WebGLContextId, WebGLDisplayItem, YuvColorSpace}; +use {RectangleDisplayItem, ScrollLayerId, ScrollPolicy, SpecificDisplayItem, StackingContext}; +use {TextDisplayItem, WebGLContextId, WebGLDisplayItem, YuvColorSpace}; use YuvImageDisplayItem; #[derive(Clone, Deserialize, Serialize)] @@ -341,17 +341,20 @@ impl DisplayListBuilder { pub fn define_clip(&mut self, clip: ClipRegion, content_size: LayoutSize, - scroll_root_id: Option) + id: Option) -> ScrollLayerId { - let scroll_layer_id = self.next_scroll_layer_id; - self.next_scroll_layer_id += 1; + let id = match id { + Some(id) => id, + None => { + self.next_scroll_layer_id += 1; + ScrollLayerId::Clip(self.next_scroll_layer_id - 1, self.pipeline_id) + } + }; - let id = ScrollLayerId::new(self.pipeline_id, scroll_layer_id); let item = SpecificDisplayItem::Clip(ClipDisplayItem { content_size: content_size, id: id, parent_id: *self.clip_stack.last().unwrap(), - scroll_root_id: scroll_root_id, }); self.push_item(item, clip.main, clip); @@ -361,8 +364,8 @@ impl DisplayListBuilder { pub fn push_scroll_layer(&mut self, clip: ClipRegion, content_size: LayoutSize, - scroll_root_id: Option) { - let id = self.define_clip(clip, content_size, scroll_root_id); + id: Option) { + let id = self.define_clip(clip, content_size, id); self.clip_stack.push(id); } diff --git a/wrench/src/wrench.rs b/wrench/src/wrench.rs index ab11c0d8ca..c80dcc9cd2 100644 --- a/wrench/src/wrench.rs +++ b/wrench/src/wrench.rs @@ -364,8 +364,7 @@ impl Wrench { pub fn send_lists(&mut self, frame_number: u32, display_list: DisplayListBuilder, - scroll_offsets: &HashMap) { - let pipeline_id = display_list.pipeline_id; + scroll_offsets: &HashMap) { let root_background_color = Some(ColorF::new(1.0, 1.0, 1.0, 1.0)); self.api.set_root_display_list(root_background_color, Epoch(frame_number), @@ -373,10 +372,8 @@ impl Wrench { display_list.finalize(), false); - for (scroll_root_id, offset) in scroll_offsets { - self.api.scroll_layers_with_scroll_root_id(*offset, - pipeline_id, - *scroll_root_id); + for (id, offset) in scroll_offsets { + self.api.scroll_layer_with_id(*offset, *id); } self.api.generate_frame(None); diff --git a/wrench/src/yaml_frame_reader.rs b/wrench/src/yaml_frame_reader.rs index f635bdf039..ff99db820c 100644 --- a/wrench/src/yaml_frame_reader.rs +++ b/wrench/src/yaml_frame_reader.rs @@ -49,15 +49,7 @@ pub struct YamlFrameReader { /// A HashMap of offsets which specify what scroll offsets particular /// scroll layers should be initialized with. - scroll_offsets: HashMap, - - /// A HashMap of offsets which specify what scroll offsets particular - /// scroll layers should be initialized with. - clip_id_mapping: HashMap, - - /// Current scroll root id used to generate new scroll root ids - /// for scroll layers. - current_scroll_root_id: usize, + scroll_offsets: HashMap, } impl YamlFrameReader { @@ -72,8 +64,6 @@ impl YamlFrameReader { queue_depth: 1, include_only: vec![], scroll_offsets: HashMap::new(), - clip_id_mapping: HashMap::new(), - current_scroll_root_id: 1, } } @@ -93,7 +83,6 @@ impl YamlFrameReader { pub fn reset(&mut self) { self.scroll_offsets.clear(); - self.clip_id_mapping.clear(); } pub fn build(&mut self, wrench: &mut Wrench) { @@ -583,7 +572,7 @@ impl YamlFrameReader { let yaml_clip_id = item["clip_id"].as_i64(); if let Some(yaml_id) = yaml_clip_id { - let id = self.clip_id_mapping[&(yaml_id as u32)]; + let id = ScrollLayerId::new(yaml_id as usize, self.builder().pipeline_id); self.builder().push_clip_id(id); } @@ -592,7 +581,7 @@ impl YamlFrameReader { "image" => self.handle_image(wrench, &full_clip_region, &item), "text" | "glyphs" => self.handle_text(wrench, &full_clip_region, &item), "scroll_layer" => self.add_scroll_layer_from_yaml(wrench, &item), - "clip" => { self.add_clip_from_yaml(wrench, &item); } + "clip" => { self.handle_clip_from_yaml(wrench, &item); } "border" => self.handle_border(wrench, &full_clip_region, &item), "gradient" => self.handle_gradient(wrench, &full_clip_region, &item), "radial_gradient" => self.handle_radial_gradient(wrench, &full_clip_region, &item), @@ -609,7 +598,7 @@ impl YamlFrameReader { } pub fn add_scroll_layer_from_yaml(&mut self, wrench: &mut Wrench, yaml: &Yaml) { - let id = self.add_clip_from_yaml(wrench, yaml); + let id = self.handle_clip_from_yaml(wrench, yaml); self.builder().push_clip_id(id); if !yaml["items"].is_badvalue() { @@ -618,25 +607,22 @@ impl YamlFrameReader { self.builder().pop_clip_id(); } - pub fn add_clip_from_yaml(&mut self, wrench: &mut Wrench, yaml: &Yaml) -> ScrollLayerId { + pub fn handle_clip_from_yaml(&mut self, wrench: &mut Wrench, yaml: &Yaml) -> ScrollLayerId { let bounds = yaml["bounds"].as_rect().expect("scroll layer must have bounds"); let content_size = yaml["content-size"].as_size() .expect("scroll layer must have content size"); let clip = self.to_clip_region(&yaml["clip"], &bounds, wrench) .unwrap_or(ClipRegion::simple(&bounds)); + let id = yaml["id"].as_i64().map(|id| + ScrollLayerId::new(id as usize, self.builder().pipeline_id)); + + let id = self.builder().define_clip(clip, content_size, id); - let scroll_root_id = ServoScrollRootId(self.current_scroll_root_id); if let Some(size) = yaml["scroll-offset"].as_point() { - let entry = self.scroll_offsets.entry(scroll_root_id).or_insert_with(LayerPoint::zero); - *entry = LayerPoint::new(size.x, size.y); + self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); } - let id = self.builder().define_clip(clip, content_size, Some(scroll_root_id)); - if let Some(yaml_id) = yaml["id"].as_i64() { - assert!(!self.clip_id_mapping.contains_key(&(yaml_id as u32))); - self.clip_id_mapping.insert(yaml_id as u32, id); - } - return id + id } pub fn add_stacking_context_from_yaml(&mut self, @@ -670,9 +656,8 @@ impl YamlFrameReader { if is_root { if let Some(size) = yaml["scroll-offset"].as_point() { - let entry = self.scroll_offsets.entry(ServoScrollRootId(0)) - .or_insert_with(LayerPoint::zero); - *entry = LayerPoint::new(size.x, size.y); + let id = ScrollLayerId::root_scroll_layer(self.builder().pipeline_id); + self.scroll_offsets.insert(id, LayerPoint::new(size.x, size.y)); } } diff --git a/wrench/src/yaml_frame_writer.rs b/wrench/src/yaml_frame_writer.rs index 969084b4b5..7221a5d61f 100644 --- a/wrench/src/yaml_frame_writer.rs +++ b/wrench/src/yaml_frame_writer.rs @@ -18,6 +18,7 @@ use super::CURRENT_FRAME_NUMBER; use time; use webrender; use webrender_traits::*; +use webrender_traits::SpecificDisplayItem::*; use yaml_helper::{mix_blend_mode_to_string, scroll_policy_to_string}; use yaml_rust::{Yaml, YamlEmitter}; @@ -66,14 +67,6 @@ fn color_node(parent: &mut Table, key: &str, value: ColorF) { yaml_node(parent, key, Yaml::String(color_to_string(value))); } -fn clip_id_node(parent: &mut Table, key: &str, clip_id: &ScrollLayerId) { - if let ScrollLayerInfo::Scrollable(id) = clip_id.info { - usize_node(parent, key, id); - return; - } - unreachable!("Should not have ReferenceFrame ids in the display list."); -} - fn point_node(parent: &mut Table, key: &str, value: &TypedPoint2D) { f32_vec_node(parent, key, &[value.x, value.y]); } @@ -332,7 +325,7 @@ impl YamlFrameWriter { let mut root_dl_table = new_table(); { let mut iter = dl.all_display_items().iter(); - self.write_dl(&mut root_dl_table, &mut iter, &aux); + self.write_display_list(&mut root_dl_table, &mut iter, &aux, &mut ClipIdMapper::new()); } @@ -360,7 +353,7 @@ impl YamlFrameWriter { let dl = scene.display_lists.get(&pipeline_id).unwrap(); let aux = scene.pipeline_auxiliary_lists.get(&pipeline_id).unwrap(); let mut iter = dl.iter(); - self.write_dl(&mut pipeline, &mut iter, &aux); + self.write_display_list(&mut pipeline, &mut iter, &aux, &mut ClipIdMapper::new()); pipelines.push(Yaml::Hash(pipeline)); } @@ -497,16 +490,16 @@ impl YamlFrameWriter { } } - fn write_dl_items(&mut self, - list: &mut Vec, - dl_iter: &mut slice::Iter, - aux: &AuxiliaryLists) { - use webrender_traits::SpecificDisplayItem::*; - while let Some(ref base) = dl_iter.next() { + fn write_display_list_items(&mut self, + list: &mut Vec, + list_iterator: &mut slice::Iter, + aux: &AuxiliaryLists, + clip_id_mapper: &mut ClipIdMapper) { + while let Some(ref base) = list_iterator.next() { let mut v = new_table(); rect_node(&mut v, "bounds", &base.rect); yaml_node(&mut v, "clip", self.make_clip_node(&base.clip, aux)); - clip_id_node(&mut v, "clip_id", &base.scroll_layer_id); + usize_node(&mut v, "clip_id", clip_id_mapper.map(&base.scroll_layer_id)); match base.item { Rectangle(item) => { @@ -741,12 +734,12 @@ impl YamlFrameWriter { PushStackingContext(item) => { str_node(&mut v, "type", "stacking_context"); write_sc(&mut v, &item.stacking_context); - self.write_dl(&mut v, dl_iter, aux); + self.write_display_list(&mut v, list_iterator, aux, clip_id_mapper); }, Clip(item) => { str_node(&mut v, "type", "clip"); size_node(&mut v, "content-size", &item.content_size); - clip_id_node(&mut v, "id", &item.id); + usize_node(&mut v, "id", clip_id_mapper.add_id(item.id)); } PopStackingContext => return, } @@ -756,9 +749,13 @@ impl YamlFrameWriter { } } - fn write_dl(&mut self, parent: &mut Table, dl_iter: &mut slice::Iter, aux: &AuxiliaryLists) { + fn write_display_list(&mut self, + parent: &mut Table, + list_iterator: &mut slice::Iter, + aux: &AuxiliaryLists, + clip_id_mapper: &mut ClipIdMapper) { let mut list = vec![]; - self.write_dl_items(&mut list, dl_iter, aux); + self.write_display_list_items(&mut list, list_iterator, aux, clip_id_mapper); parent.insert(Yaml::String("items".to_owned()), Yaml::Array(list)); } } @@ -843,3 +840,29 @@ impl webrender::ApiRecordingReceiver for YamlFrameWriterReceiver { } } } + +/// This structure allows mapping both Clip and ClipExternalId ScrollLayerIds +/// onto one set of numeric ids. This prevents ids from clashing in the yaml output. +struct ClipIdMapper { + hash_map: HashMap, + current_clip_id: usize, +} + +impl ClipIdMapper { + fn new() -> ClipIdMapper { + ClipIdMapper { + hash_map: HashMap::new(), + current_clip_id: 1, + } + } + + fn add_id(&mut self, id: ScrollLayerId) -> usize { + self.hash_map.insert(id, self.current_clip_id); + self.current_clip_id += 1; + self.current_clip_id - 1 + } + + fn map(&self, id: &ScrollLayerId) -> usize { + *self.hash_map.get(id).unwrap() + } +}