diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 6e344e1cdc8..ba473abc410 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -6,7 +6,7 @@ use crate::dom_traversal::{Contents, NodeExt}; use crate::flow::construct::ContainsFloats; use crate::flow::float::FloatBox; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; -use crate::fragments::Fragment; +use crate::fragments::{Fragment, IsContentful}; use crate::geom; use crate::geom::flow_relative::Vec2; use crate::positioned::AbsolutelyPositionedBox; @@ -21,6 +21,7 @@ use style::context::SharedStyleContext; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style_traits::CSSPixel; +use webrender_api::DisplayListBuilder; pub struct BoxTreeRoot(BlockFormattingContext); pub struct FragmentTreeRoot(Vec); @@ -129,3 +130,13 @@ impl BoxTreeRoot { FragmentTreeRoot(flow_children.fragments) } } + +impl FragmentTreeRoot { + pub fn build_display_list(&self, builder: &mut DisplayListBuilder) -> IsContentful { + let mut is_contentful = IsContentful(false); + for fragment in &self.0 { + fragment.build_display_list(builder, &mut is_contentful) + } + is_contentful + } +} diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index ceb2fdf7971..ad1ebd41359 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -9,6 +9,7 @@ use servo_arc::Arc; use style::properties::ComputedValues; use style::values::computed::Length; use style::Zero; +use webrender_api::DisplayListBuilder; pub(crate) enum Fragment { Box(BoxFragment), @@ -123,3 +124,18 @@ impl CollapsedMargin { self.max_positive + self.min_negative } } + +/// 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 Fragment { + pub(crate) fn build_display_list( + &self, + builder: &mut DisplayListBuilder, + is_contentful: &mut IsContentful, + ) { + } +} diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index c33449d478a..1c0ee67a268 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -1108,7 +1108,9 @@ impl LayoutThread { } // Perform post-style recalculation layout passes. - self.perform_post_style_recalc_layout_passes(&data.reflow_goal, Some(&document)); + if let Some(root) = &*self.fragment_tree_root.borrow() { + self.perform_post_style_recalc_layout_passes(root, &data.reflow_goal, Some(&document)); + } self.first_reflow.set(false); self.respond_to_query_if_necessary(&data.reflow_goal, &mut *rw_data, &mut layout_context); @@ -1230,7 +1232,10 @@ impl LayoutThread { ); } - if let Some(author_shared_lock) = self.document_shared_lock.clone() { + if let Some(root) = &*self.fragment_tree_root.borrow() { + // Unwrap here should not panic since self.fragment_tree_root is only ever set to Some(_) + // in handle_reflow() where self.document_shared_lock is as well. + let author_shared_lock = self.document_shared_lock.clone().unwrap(); let author_guard = author_shared_lock.read(); let ua_or_user_guard = UA_STYLESHEETS.shared_lock.read(); let _guards = StylesheetGuards { @@ -1238,12 +1243,13 @@ impl LayoutThread { ua_or_user: &ua_or_user_guard, }; - self.perform_post_style_recalc_layout_passes(&ReflowGoal::TickAnimations, None); + self.perform_post_style_recalc_layout_passes(root, &ReflowGoal::TickAnimations, None); } } fn perform_post_style_recalc_layout_passes( &self, + fragment_tree: &layout::FragmentTreeRoot, reflow_goal: &ReflowGoal, document: Option<&ServoLayoutDocument>, ) { @@ -1261,16 +1267,13 @@ impl LayoutThread { document.will_paint(); } - let viewport_size = Size2D::new( + let viewport_size = webrender_api::units::LayoutSize::from_untyped(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 = + )); + let mut display_list = webrender_api::DisplayListBuilder::new(self.id.to_webrender(), viewport_size); - let is_contentful = false; + let is_contentful = fragment_tree.build_display_list(&mut display_list); debug!("Layout done!"); @@ -1282,7 +1285,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, is_contentful); + .maybe_observe_paint_time(self, epoch, is_contentful.0); let mut txn = webrender_api::Transaction::new(); txn.set_display_list(