diff options
-rw-r--r-- | components/gfx_traits/lib.rs | 5 | ||||
-rw-r--r-- | components/layout/display_list/items.rs | 16 | ||||
-rw-r--r-- | components/layout/display_list/mod.rs | 1 | ||||
-rw-r--r-- | components/layout/display_list/webrender_helpers.rs | 53 | ||||
-rw-r--r-- | components/layout_2020/display_list/items.rs | 24 | ||||
-rw-r--r-- | components/layout_2020/display_list/mod.rs | 8 | ||||
-rw-r--r-- | components/layout_2020/display_list/webrender_helpers.rs | 26 | ||||
-rw-r--r-- | components/layout_2020/fragment.rs | 2 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/opaque_node.rs | 2 | ||||
-rw-r--r-- | components/layout_2020/query.rs | 9 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 6 | ||||
-rw-r--r-- | components/layout_thread_2020/lib.rs | 23 | ||||
-rw-r--r-- | components/metrics/lib.rs | 6 | ||||
-rw-r--r-- | tests/unit/metrics/paint_time.rs | 32 |
15 files changed, 62 insertions, 155 deletions
diff --git a/components/gfx_traits/lib.rs b/components/gfx_traits/lib.rs index a3a85499a9e..165059c7996 100644 --- a/components/gfx_traits/lib.rs +++ b/components/gfx_traits/lib.rs @@ -103,8 +103,3 @@ pub fn node_id_from_scroll_id(id: usize) -> Option<usize> { } None } - -pub trait DisplayList { - /// Returns true if this display list contains meaningful content. - fn is_contentful(&self) -> bool; -} diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs index de7e49d306e..f838a95bf08 100644 --- a/components/layout/display_list/items.rs +++ b/components/layout/display_list/items.rs @@ -137,22 +137,6 @@ impl DisplayList { } } -impl gfx_traits::DisplayList for DisplayList { - /// Analyze the display list to figure out if this may be the first - /// contentful paint (i.e. the display list contains items of type text, - /// image, non-white canvas or SVG). Used by metrics. - fn is_contentful(&self) -> bool { - for item in &self.list { - match item { - &DisplayItem::Text(_) | &DisplayItem::Image(_) => return true, - _ => (), - } - } - - false - } -} - /// Display list sections that make up a stacking context. Each section here refers /// to the steps in CSS 2.1 Appendix E. /// diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index 302728fbf22..257d9eb6ddc 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -8,7 +8,6 @@ pub use self::builder::IndexableText; pub use self::builder::StackingContextCollectionFlags; pub use self::builder::StackingContextCollectionState; pub use self::conversions::ToLayout; -pub use self::webrender_helpers::WebRenderDisplayListConverter; mod background; mod border; diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs index a27979a3189..993e2b38cef 100644 --- a/components/layout/display_list/webrender_helpers.rs +++ b/components/layout/display_list/webrender_helpers.rs @@ -17,10 +17,6 @@ use webrender_api::{ RasterSpace, ReferenceFrameKind, SpaceAndClipInfo, SpatialId, StackingContext, }; -pub trait WebRenderDisplayListConverter { - fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder; -} - struct ClipScrollState { clip_ids: Vec<Option<ClipId>>, spatial_ids: Vec<Option<SpatialId>>, @@ -28,17 +24,17 @@ struct ClipScrollState { active_spatial_id: SpatialId, } -trait WebRenderDisplayItemConverter { - fn convert_to_webrender( - &mut self, - clip_scroll_nodes: &[ClipScrollNode], - state: &mut ClipScrollState, - builder: &mut DisplayListBuilder, - ); -} +/// Contentful paint, for the purpose of +/// https://w3c.github.io/paint-timing/#first-contentful-paint +/// (i.e. the display list contains items of type text, +/// image, non-white canvas or SVG). Used by metrics. +pub struct IsContentful(pub bool); -impl WebRenderDisplayListConverter for DisplayList { - fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder { +impl DisplayList { + pub fn convert_to_webrender( + &mut self, + pipeline_id: PipelineId, + ) -> (DisplayListBuilder, IsContentful) { let mut clip_ids = vec![None; self.clip_scroll_nodes.len()]; let mut spatial_ids = vec![None; self.clip_scroll_nodes.len()]; @@ -67,21 +63,24 @@ impl WebRenderDisplayListConverter for DisplayList { 1024 * 1024, // 1 MB of space ); + let mut is_contentful = IsContentful(false); for item in &mut self.list { - item.convert_to_webrender(&self.clip_scroll_nodes, &mut state, &mut builder); + is_contentful.0 |= item + .convert_to_webrender(&self.clip_scroll_nodes, &mut state, &mut builder) + .0; } - builder + (builder, is_contentful) } } -impl WebRenderDisplayItemConverter for DisplayItem { +impl DisplayItem { fn convert_to_webrender( &mut self, clip_scroll_nodes: &[ClipScrollNode], state: &mut ClipScrollState, builder: &mut DisplayListBuilder, - ) { + ) -> IsContentful { // Note: for each time of a display item, if we register one of `clip_ids` or `spatial_ids`, // we also register the other one as inherited from the current state or the stack. // This is not an ideal behavior, but it is compatible with the old WebRender model @@ -109,15 +108,18 @@ impl WebRenderDisplayItemConverter for DisplayItem { DisplayItem::Rectangle(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_item(&WrDisplayItem::Rectangle(item.item)); + IsContentful(false) }, DisplayItem::Text(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_item(&WrDisplayItem::Text(item.item)); builder.push_iter(item.data.iter()); + IsContentful(true) }, DisplayItem::Image(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_item(&WrDisplayItem::Image(item.item)); + IsContentful(true) }, DisplayItem::Border(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); @@ -125,24 +127,29 @@ impl WebRenderDisplayItemConverter for DisplayItem { builder.push_stops(item.data.as_ref()); } builder.push_item(&WrDisplayItem::Border(item.item)); + IsContentful(false) }, DisplayItem::Gradient(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_stops(item.data.as_ref()); builder.push_item(&WrDisplayItem::Gradient(item.item)); + IsContentful(false) }, DisplayItem::RadialGradient(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_stops(item.data.as_ref()); builder.push_item(&WrDisplayItem::RadialGradient(item.item)); + IsContentful(false) }, DisplayItem::Line(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_item(&WrDisplayItem::Line(item.item)); + IsContentful(false) }, DisplayItem::BoxShadow(ref mut item) => { item.item.common = build_common_item_properties(&item.base, state); builder.push_item(&WrDisplayItem::BoxShadow(item.item)); + IsContentful(false) }, DisplayItem::PushTextShadow(ref mut item) => { let common = build_common_item_properties(&item.base, state); @@ -154,9 +161,11 @@ impl WebRenderDisplayItemConverter for DisplayItem { item.shadow, true, ); + IsContentful(false) }, DisplayItem::PopAllTextShadows(_) => { builder.push_item(&WrDisplayItem::PopAllShadows); + IsContentful(false) }, DisplayItem::Iframe(ref mut item) => { let common = build_common_item_properties(&item.base, state); @@ -170,6 +179,7 @@ impl WebRenderDisplayItemConverter for DisplayItem { item.iframe.to_webrender(), true, ); + IsContentful(false) }, DisplayItem::PushStackingContext(ref mut item) => { let stacking_context = &item.stacking_context; @@ -235,8 +245,12 @@ impl WebRenderDisplayItemConverter for DisplayItem { }; builder.push_item(&WrDisplayItem::PushStackingContext(wr_item)); + IsContentful(false) + }, + DisplayItem::PopStackingContext(_) => { + builder.pop_stacking_context(); + IsContentful(false) }, - DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(), DisplayItem::DefineClipScrollNode(ref mut item) => { let node = &clip_scroll_nodes[item.node_index.to_index()]; let item_rect = node.clip.main; @@ -298,6 +312,7 @@ impl WebRenderDisplayItemConverter for DisplayItem { unreachable!("Found DefineClipScrollNode for Placeholder type node."); }, }; + IsContentful(false) }, } } diff --git a/components/layout_2020/display_list/items.rs b/components/layout_2020/display_list/items.rs deleted file mode 100644 index 68ec3fcc188..00000000000 --- a/components/layout_2020/display_list/items.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -use euclid::Vector2D; -use gfx_traits; -use std::collections::HashMap; -use std::f32; -use webrender_api::units::LayoutPixel; -use webrender_api::ExternalScrollId; - -pub use style::dom::OpaqueNode; - -#[derive(Serialize)] -pub struct DisplayList {} - -impl gfx_traits::DisplayList for DisplayList { - fn is_contentful(&self) -> bool { - false - } -} - -/// The type of the scroll offset list. This is only populated if WebRender is in use. -pub type ScrollOffsetMap = HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>; diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs deleted file mode 100644 index dcdab26adb8..00000000000 --- a/components/layout_2020/display_list/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -pub use self::webrender_helpers::WebRenderDisplayListConverter; - -pub mod items; -mod webrender_helpers; diff --git a/components/layout_2020/display_list/webrender_helpers.rs b/components/layout_2020/display_list/webrender_helpers.rs deleted file mode 100644 index 23ca4138e3e..00000000000 --- a/components/layout_2020/display_list/webrender_helpers.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -use crate::display_list::items::DisplayList; -use msg::constellation_msg::PipelineId; -use webrender_api::units::LayoutSize; -use webrender_api::{self, DisplayListBuilder}; - -pub trait WebRenderDisplayListConverter { - fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder; -} - -impl WebRenderDisplayListConverter for DisplayList { - fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder { - let webrender_pipeline = pipeline_id.to_webrender(); - - let builder = DisplayListBuilder::with_capacity( - webrender_pipeline, - LayoutSize::zero(), - 1024 * 1024, // 1 MB of space - ); - - builder - } -} diff --git a/components/layout_2020/fragment.rs b/components/layout_2020/fragment.rs index f1fa89d141d..71e23b7ffaa 100644 --- a/components/layout_2020/fragment.rs +++ b/components/layout_2020/fragment.rs @@ -5,11 +5,11 @@ //! The `Fragment` type, which represents the leaves of the layout tree. use crate::context::LayoutContext; -use crate::display_list::items::OpaqueNode; use crate::ServoArc; use app_units::Au; use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutNode}; use serde::ser::{Serialize, SerializeStruct, Serializer}; +use style::dom::OpaqueNode; use style::logical_geometry::{LogicalMargin, LogicalRect}; use style::properties::ComputedValues; use style::selector_parser::RestyleDamage; diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index e08d962df22..4af20789529 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -4,12 +4,8 @@ #![deny(unsafe_code)] -#[macro_use] -extern crate serde; - pub mod context; pub mod data; -pub mod display_list; mod fragment; pub mod opaque_node; pub mod query; diff --git a/components/layout_2020/opaque_node.rs b/components/layout_2020/opaque_node.rs index 3d56ef21dae..36df7c640f4 100644 --- a/components/layout_2020/opaque_node.rs +++ b/components/layout_2020/opaque_node.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate::display_list::items::OpaqueNode; use libc::c_void; use script_traits::UntrustedNodeAddress; +use style::dom::OpaqueNode; pub trait OpaqueNodeMethods { fn to_untrusted_node_address(&self) -> UntrustedNodeAddress; diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index fc308005806..23816521c70 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -5,9 +5,9 @@ //! Utilities for querying the layout, as needed by the layout thread. use crate::context::LayoutContext; -use crate::display_list::items::{DisplayList, OpaqueNode, ScrollOffsetMap}; use app_units::Au; use euclid::default::{Point2D, Rect}; +use euclid::Vector2D; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; use script_layout_interface::rpc::TextIndexResponse; @@ -17,9 +17,12 @@ use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse, use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use script_traits::LayoutMsg as ConstellationMsg; use script_traits::UntrustedNodeAddress; +use std::collections::HashMap; use std::sync::{Arc, Mutex}; +use style::dom::OpaqueNode; use style::properties::PropertyId; use style::selector_parser::PseudoElement; +use webrender_api::units::LayoutPixel; use webrender_api::ExternalScrollId; /// Mutable data belonging to the LayoutThread. @@ -30,7 +33,7 @@ pub struct LayoutThreadData { pub constellation_chan: IpcSender<ConstellationMsg>, /// The root stacking context. - pub display_list: Option<DisplayList>, + pub display_list: Option<webrender_api::DisplayListBuilder>, /// A queued response for the union of the content boxes of a node. pub content_box_response: Option<Rect<Au>>, @@ -57,7 +60,7 @@ pub struct LayoutThreadData { pub style_response: StyleResponse, /// Scroll offsets of scrolling regions. - pub scroll_offsets: ScrollOffsetMap, + pub scroll_offsets: HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>, /// Index in a text fragment. We need this do determine the insertion point. pub text_index_response: TextIndexResponse, diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 887c31f4657..e24360db2dc 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -45,7 +45,7 @@ use layout::context::LayoutContext; use layout::context::RegisteredPainter; use layout::context::RegisteredPainters; use layout::display_list::items::{OpaqueNode, WebRenderImageInfo}; -use layout::display_list::{IndexableText, ToLayout, WebRenderDisplayListConverter}; +use layout::display_list::{IndexableText, ToLayout}; use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; use layout::incremental::{RelayoutMode, SpecialRestyleDamage}; @@ -1233,7 +1233,7 @@ impl LayoutThread { debug!("Layout done!"); // TODO: Avoid the temporary conversion and build webrender sc/dl directly! - let builder = display_list.convert_to_webrender(self.id); + let (builder, is_contentful) = display_list.convert_to_webrender(self.id); let viewport_size = Size2D::new( self.viewport_size.width.to_f32_px(), @@ -1250,7 +1250,7 @@ impl LayoutThread { // sending the display list to WebRender in order to set time related // Progressive Web Metrics. self.paint_time_metrics - .maybe_observe_paint_time(self, epoch, &*display_list); + .maybe_observe_paint_time(self, epoch, is_contentful.0); let mut txn = webrender_api::Transaction::new(); txn.set_display_list( diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 82919fa75c1..ec31d858b9f 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -37,8 +37,6 @@ use histogram::Histogram; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use layout::context::LayoutContext; -use layout::display_list::items::DisplayList; -use layout::display_list::WebRenderDisplayListConverter; use layout::query::{ process_content_box_request, process_content_boxes_request, LayoutRPCImpl, LayoutThreadData, }; @@ -1338,36 +1336,35 @@ impl LayoutThread { document.will_paint(); } - let mut display_list = DisplayList {}; - - debug!("Layout done!"); - - // TODO: Avoid the temporary conversion and build webrender sc/dl directly! - let builder = display_list.convert_to_webrender(self.id); - let viewport_size = Size2D::new( self.viewport_size.width.to_f32_px(), self.viewport_size.height.to_f32_px(), ); + let viewport_size = webrender_api::units::LayoutSize::from_untyped(viewport_size); + + let display_list = + webrender_api::DisplayListBuilder::new(self.id.to_webrender(), viewport_size); + let is_contentful = false; + + debug!("Layout done!"); + let mut epoch = self.epoch.get(); epoch.next(); self.epoch.set(epoch); - let viewport_size = webrender_api::units::LayoutSize::from_untyped(viewport_size); - // Observe notifications about rendered frames if needed right before // sending the display list to WebRender in order to set time related // Progressive Web Metrics. self.paint_time_metrics - .maybe_observe_paint_time(self, epoch, &display_list); + .maybe_observe_paint_time(self, epoch, is_contentful); let mut txn = webrender_api::Transaction::new(); txn.set_display_list( webrender_api::Epoch(epoch.0), None, viewport_size, - builder.finalize(), + display_list.finalize(), true, ); txn.generate_frame(); diff --git a/components/metrics/lib.rs b/components/metrics/lib.rs index bfe4ad831c0..1165c8f45ca 100644 --- a/components/metrics/lib.rs +++ b/components/metrics/lib.rs @@ -7,7 +7,7 @@ extern crate log; #[macro_use] extern crate malloc_size_of_derive; -use gfx_traits::{DisplayList, Epoch}; +use gfx_traits::Epoch; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; use profile_traits::time::TimerMetadata; @@ -306,7 +306,7 @@ impl PaintTimeMetrics { &self, profiler_metadata_factory: &T, epoch: Epoch, - display_list: &dyn DisplayList, + display_list_is_contentful: bool, ) where T: ProfilerMetadataFactory, { @@ -319,7 +319,7 @@ impl PaintTimeMetrics { epoch, ( profiler_metadata_factory.new_metadata(), - display_list.is_contentful(), + display_list_is_contentful, ), ); diff --git a/tests/unit/metrics/paint_time.rs b/tests/unit/metrics/paint_time.rs index c404e4d6e7b..ac8ade3842c 100644 --- a/tests/unit/metrics/paint_time.rs +++ b/tests/unit/metrics/paint_time.rs @@ -4,13 +4,10 @@ use gfx_traits::Epoch; use ipc_channel::ipc; -use layout::display_list::items::{BaseDisplayItem, CommonDisplayItem, DisplayItem, DisplayList}; use metrics::{PaintTimeMetrics, ProfilerMetadataFactory, ProgressiveWebMetric}; use msg::constellation_msg::TEST_PIPELINE_ID; use profile_traits::time::{ProfilerChan, TimerMetadata}; use servo_url::ServoUrl; -use webrender_api::units::{LayoutRect, LayoutSize}; -use webrender_api::{AlphaType, ColorF, ImageDisplayItem, ImageKey, ImageRendering}; struct DummyProfilerMetadataFactory {} impl ProfilerMetadataFactory for DummyProfilerMetadataFactory { @@ -49,7 +46,7 @@ fn test_paint_metrics_construction() { ); } -fn test_common(display_list: &DisplayList, epoch: Epoch) -> PaintTimeMetrics { +fn test_common(display_list_is_contentful: bool, epoch: Epoch) -> PaintTimeMetrics { let (sender, _) = ipc::channel().unwrap(); let profiler_chan = ProfilerChan(sender); let (layout_sender, _) = ipc::channel().unwrap(); @@ -66,7 +63,7 @@ fn test_common(display_list: &DisplayList, epoch: Epoch) -> PaintTimeMetrics { paint_time_metrics.maybe_observe_paint_time( &dummy_profiler_metadata_factory, epoch, - &*display_list, + display_list_is_contentful, ); // Should not set any metric until navigation start is set. @@ -95,12 +92,8 @@ fn test_common(display_list: &DisplayList, epoch: Epoch) -> PaintTimeMetrics { #[test] fn test_first_paint_setter() { - let empty_display_list = DisplayList { - list: Vec::new(), - clip_scroll_nodes: Vec::new(), - }; let epoch = Epoch(0); - let paint_time_metrics = test_common(&empty_display_list, epoch); + let paint_time_metrics = test_common(false, epoch); let now = time::precise_time_ns(); paint_time_metrics.maybe_set_metric(epoch, now); assert!( @@ -116,25 +109,8 @@ fn test_first_paint_setter() { #[test] fn test_first_contentful_paint_setter() { - let image = DisplayItem::Image(CommonDisplayItem::new( - BaseDisplayItem::empty(), - ImageDisplayItem { - bounds: LayoutRect::zero(), - common: layout::display_list::items::empty_common_item_properties(), - image_key: ImageKey::DUMMY, - stretch_size: LayoutSize::zero(), - tile_spacing: LayoutSize::zero(), - image_rendering: ImageRendering::Auto, - alpha_type: AlphaType::PremultipliedAlpha, - color: ColorF::WHITE, - }, - )); - let display_list = DisplayList { - list: vec![image], - clip_scroll_nodes: Vec::new(), - }; let epoch = Epoch(0); - let paint_time_metrics = test_common(&display_list, epoch); + let paint_time_metrics = test_common(true, epoch); let now = time::precise_time_ns(); paint_time_metrics.maybe_set_metric(epoch, now); assert!( |