Replace DisplayList::is_contentful with tracking during conversion to WR display lists

This commit is contained in:
Simon Sapin 2019-09-06 17:11:36 +02:00
parent 526619a78a
commit e9f7079c70
8 changed files with 53 additions and 42 deletions

View file

@ -103,8 +103,3 @@ pub fn node_id_from_scroll_id(id: usize) -> Option<usize> {
} }
None None
} }
pub trait DisplayList {
/// Returns true if this display list contains meaningful content.
fn is_contentful(&self) -> bool;
}

View file

@ -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 /// Display list sections that make up a stacking context. Each section here refers
/// to the steps in CSS 2.1 Appendix E. /// to the steps in CSS 2.1 Appendix E.
/// ///

View file

@ -24,8 +24,17 @@ struct ClipScrollState {
active_spatial_id: SpatialId, active_spatial_id: SpatialId,
} }
/// 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 DisplayList { impl DisplayList {
pub fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder { 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 clip_ids = vec![None; self.clip_scroll_nodes.len()];
let mut spatial_ids = vec![None; self.clip_scroll_nodes.len()]; let mut spatial_ids = vec![None; self.clip_scroll_nodes.len()];
@ -54,11 +63,14 @@ impl DisplayList {
1024 * 1024, // 1 MB of space 1024 * 1024, // 1 MB of space
); );
let mut is_contentful = IsContentful(false);
for item in &mut self.list { 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)
} }
} }
@ -68,7 +80,7 @@ impl DisplayItem {
clip_scroll_nodes: &[ClipScrollNode], clip_scroll_nodes: &[ClipScrollNode],
state: &mut ClipScrollState, state: &mut ClipScrollState,
builder: &mut DisplayListBuilder, builder: &mut DisplayListBuilder,
) { ) -> IsContentful {
// Note: for each time of a display item, if we register one of `clip_ids` or `spatial_ids`, // 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. // 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 // This is not an ideal behavior, but it is compatible with the old WebRender model
@ -96,15 +108,18 @@ impl DisplayItem {
DisplayItem::Rectangle(ref mut item) => { DisplayItem::Rectangle(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_item(&WrDisplayItem::Rectangle(item.item)); builder.push_item(&WrDisplayItem::Rectangle(item.item));
IsContentful(false)
}, },
DisplayItem::Text(ref mut item) => { DisplayItem::Text(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_item(&WrDisplayItem::Text(item.item)); builder.push_item(&WrDisplayItem::Text(item.item));
builder.push_iter(item.data.iter()); builder.push_iter(item.data.iter());
IsContentful(true)
}, },
DisplayItem::Image(ref mut item) => { DisplayItem::Image(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_item(&WrDisplayItem::Image(item.item)); builder.push_item(&WrDisplayItem::Image(item.item));
IsContentful(true)
}, },
DisplayItem::Border(ref mut item) => { DisplayItem::Border(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
@ -112,24 +127,29 @@ impl DisplayItem {
builder.push_stops(item.data.as_ref()); builder.push_stops(item.data.as_ref());
} }
builder.push_item(&WrDisplayItem::Border(item.item)); builder.push_item(&WrDisplayItem::Border(item.item));
IsContentful(false)
}, },
DisplayItem::Gradient(ref mut item) => { DisplayItem::Gradient(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_stops(item.data.as_ref()); builder.push_stops(item.data.as_ref());
builder.push_item(&WrDisplayItem::Gradient(item.item)); builder.push_item(&WrDisplayItem::Gradient(item.item));
IsContentful(false)
}, },
DisplayItem::RadialGradient(ref mut item) => { DisplayItem::RadialGradient(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_stops(item.data.as_ref()); builder.push_stops(item.data.as_ref());
builder.push_item(&WrDisplayItem::RadialGradient(item.item)); builder.push_item(&WrDisplayItem::RadialGradient(item.item));
IsContentful(false)
}, },
DisplayItem::Line(ref mut item) => { DisplayItem::Line(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_item(&WrDisplayItem::Line(item.item)); builder.push_item(&WrDisplayItem::Line(item.item));
IsContentful(false)
}, },
DisplayItem::BoxShadow(ref mut item) => { DisplayItem::BoxShadow(ref mut item) => {
item.item.common = build_common_item_properties(&item.base, state); item.item.common = build_common_item_properties(&item.base, state);
builder.push_item(&WrDisplayItem::BoxShadow(item.item)); builder.push_item(&WrDisplayItem::BoxShadow(item.item));
IsContentful(false)
}, },
DisplayItem::PushTextShadow(ref mut item) => { DisplayItem::PushTextShadow(ref mut item) => {
let common = build_common_item_properties(&item.base, state); let common = build_common_item_properties(&item.base, state);
@ -141,9 +161,11 @@ impl DisplayItem {
item.shadow, item.shadow,
true, true,
); );
IsContentful(false)
}, },
DisplayItem::PopAllTextShadows(_) => { DisplayItem::PopAllTextShadows(_) => {
builder.push_item(&WrDisplayItem::PopAllShadows); builder.push_item(&WrDisplayItem::PopAllShadows);
IsContentful(false)
}, },
DisplayItem::Iframe(ref mut item) => { DisplayItem::Iframe(ref mut item) => {
let common = build_common_item_properties(&item.base, state); let common = build_common_item_properties(&item.base, state);
@ -157,6 +179,7 @@ impl DisplayItem {
item.iframe.to_webrender(), item.iframe.to_webrender(),
true, true,
); );
IsContentful(false)
}, },
DisplayItem::PushStackingContext(ref mut item) => { DisplayItem::PushStackingContext(ref mut item) => {
let stacking_context = &item.stacking_context; let stacking_context = &item.stacking_context;
@ -222,8 +245,12 @@ impl DisplayItem {
}; };
builder.push_item(&WrDisplayItem::PushStackingContext(wr_item)); 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) => { DisplayItem::DefineClipScrollNode(ref mut item) => {
let node = &clip_scroll_nodes[item.node_index.to_index()]; let node = &clip_scroll_nodes[item.node_index.to_index()];
let item_rect = node.clip.main; let item_rect = node.clip.main;
@ -285,6 +312,7 @@ impl DisplayItem {
unreachable!("Found DefineClipScrollNode for Placeholder type node."); unreachable!("Found DefineClipScrollNode for Placeholder type node.");
}, },
}; };
IsContentful(false)
}, },
} }
} }

View file

@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use euclid::Vector2D; use euclid::Vector2D;
use gfx_traits;
use std::collections::HashMap; use std::collections::HashMap;
use std::f32; use std::f32;
use webrender_api::units::LayoutPixel; use webrender_api::units::LayoutPixel;
@ -14,11 +13,5 @@ pub use style::dom::OpaqueNode;
#[derive(Serialize)] #[derive(Serialize)]
pub struct DisplayList {} 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. /// The type of the scroll offset list. This is only populated if WebRender is in use.
pub type ScrollOffsetMap = HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>; pub type ScrollOffsetMap = HashMap<ExternalScrollId, Vector2D<f32, LayoutPixel>>;

View file

@ -7,8 +7,17 @@ use msg::constellation_msg::PipelineId;
use webrender_api::units::LayoutSize; use webrender_api::units::LayoutSize;
use webrender_api::{self, DisplayListBuilder}; use webrender_api::{self, 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 DisplayList { impl DisplayList {
pub fn convert_to_webrender(&mut self, pipeline_id: PipelineId) -> DisplayListBuilder { pub fn convert_to_webrender(
&mut self,
pipeline_id: PipelineId,
) -> (DisplayListBuilder, IsContentful) {
let webrender_pipeline = pipeline_id.to_webrender(); let webrender_pipeline = pipeline_id.to_webrender();
let builder = DisplayListBuilder::with_capacity( let builder = DisplayListBuilder::with_capacity(
@ -17,6 +26,8 @@ impl DisplayList {
1024 * 1024, // 1 MB of space 1024 * 1024, // 1 MB of space
); );
builder let is_contentful = IsContentful(false);
(builder, is_contentful)
} }
} }

View file

@ -1233,7 +1233,7 @@ impl LayoutThread {
debug!("Layout done!"); debug!("Layout done!");
// TODO: Avoid the temporary conversion and build webrender sc/dl directly! // 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( let viewport_size = Size2D::new(
self.viewport_size.width.to_f32_px(), 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 // sending the display list to WebRender in order to set time related
// Progressive Web Metrics. // Progressive Web Metrics.
self.paint_time_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(); let mut txn = webrender_api::Transaction::new();
txn.set_display_list( txn.set_display_list(

View file

@ -1342,7 +1342,7 @@ impl LayoutThread {
debug!("Layout done!"); debug!("Layout done!");
// TODO: Avoid the temporary conversion and build webrender sc/dl directly! // 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( let viewport_size = Size2D::new(
self.viewport_size.width.to_f32_px(), self.viewport_size.width.to_f32_px(),
@ -1359,7 +1359,7 @@ impl LayoutThread {
// sending the display list to WebRender in order to set time related // sending the display list to WebRender in order to set time related
// Progressive Web Metrics. // Progressive Web Metrics.
self.paint_time_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(); let mut txn = webrender_api::Transaction::new();
txn.set_display_list( txn.set_display_list(

View file

@ -7,7 +7,7 @@ extern crate log;
#[macro_use] #[macro_use]
extern crate malloc_size_of_derive; extern crate malloc_size_of_derive;
use gfx_traits::{DisplayList, Epoch}; use gfx_traits::Epoch;
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use profile_traits::time::TimerMetadata; use profile_traits::time::TimerMetadata;
@ -306,7 +306,7 @@ impl PaintTimeMetrics {
&self, &self,
profiler_metadata_factory: &T, profiler_metadata_factory: &T,
epoch: Epoch, epoch: Epoch,
display_list: &dyn DisplayList, display_list_is_contentful: bool,
) where ) where
T: ProfilerMetadataFactory, T: ProfilerMetadataFactory,
{ {
@ -319,7 +319,7 @@ impl PaintTimeMetrics {
epoch, epoch,
( (
profiler_metadata_factory.new_metadata(), profiler_metadata_factory.new_metadata(),
display_list.is_contentful(), display_list_is_contentful,
), ),
); );