diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 826c48dc836..aa118066d49 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -30,9 +30,8 @@ use pixels::{CorsStatus, Image, PixelFormat}; use profile_traits::time::{self as profile_time, profile, ProfilerCategory}; use script_traits::CompositorEvent::{MouseButtonEvent, MouseMoveEvent, TouchEvent, WheelEvent}; use script_traits::{ - AnimationState, AnimationTickType, ConstellationControlMsg, LayoutControlMsg, MouseButton, - MouseEventType, ScrollState, TouchEventType, TouchId, WheelDelta, WindowSizeData, - WindowSizeType, + AnimationState, AnimationTickType, ConstellationControlMsg, MouseButton, MouseEventType, + ScrollState, TouchEventType, TouchId, WheelDelta, WindowSizeData, WindowSizeType, }; use servo_geometry::{DeviceIndependentPixel, FramebufferUintLength}; use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor}; @@ -1940,10 +1939,7 @@ impl IOCompositor { }); if let Some(pipeline) = details.pipeline.as_ref() { - let message = ConstellationControlMsg::ForLayoutFromConstellation( - LayoutControlMsg::SetScrollStates(scroll_states), - *pipeline_id, - ); + let message = ConstellationControlMsg::SetScrollStates(*pipeline_id, scroll_states); let _ = pipeline.script_chan.send(message); } } @@ -2154,11 +2150,14 @@ impl IOCompositor { to_remove.push(*id); if let Some(pipeline) = self.pipeline(*id) { // and inform layout with the measured paint time. - let message = LayoutControlMsg::PaintMetric(epoch, paint_time); - let message = - ConstellationControlMsg::ForLayoutFromConstellation(message, *id); - if let Err(e) = pipeline.script_chan.send(message) { - warn!("Sending PaintMetric message to layout failed ({:?}).", e); + if let Err(e) = + pipeline + .script_chan + .send(ConstellationControlMsg::SetEpochPaintTime( + *id, epoch, paint_time, + )) + { + warn!("Sending RequestLayoutPaintMetric message to layout failed ({e:?})."); } } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 0192f58a4f4..705e8f5ee50 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -10,7 +10,6 @@ use std::borrow::ToOwned; use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::process; use std::sync::{Arc, Mutex}; @@ -63,13 +62,12 @@ use profile_traits::time::{ use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode}; use script_layout_interface::wrapper_traits::LayoutNode; use script_layout_interface::{ - node_id_from_scroll_id, Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, - OffsetParentResponse, Reflow, ReflowComplete, ReflowGoal, ScriptReflow, TrustedNodeAddress, + Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, OffsetParentResponse, Reflow, + ReflowComplete, ReflowGoal, ScriptReflow, TrustedNodeAddress, }; use script_traits::{ - ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg, - LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, - WindowSizeData, WindowSizeType, + ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutMsg as ConstellationMsg, + PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, WindowSizeData, WindowSizeType, }; use servo_arc::Arc as ServoArc; use servo_atoms::Atom; @@ -245,20 +243,6 @@ impl Drop for ScriptReflowResult { } impl Layout for LayoutThread { - fn handle_constellation_message( - &mut self, - constellation_message: script_traits::LayoutControlMsg, - ) { - match constellation_message { - LayoutControlMsg::SetScrollStates(new_scroll_states) => { - self.set_scroll_states(new_scroll_states); - }, - LayoutControlMsg::PaintMetric(epoch, paint_time) => { - self.paint_time_metrics.maybe_set_metric(epoch, paint_time); - }, - } - } - fn device(&self) -> &Device { self.stylist.device() } @@ -550,6 +534,17 @@ impl Layout for LayoutThread { || self.handle_reflow(&mut result), ); } + + fn set_scroll_states(&mut self, scroll_states: &[ScrollState]) { + *self.scroll_offsets.borrow_mut() = scroll_states + .iter() + .map(|scroll_state| (scroll_state.scroll_id, scroll_state.scroll_offset)) + .collect(); + } + + fn set_epoch_paint_time(&mut self, epoch: Epoch, paint_time: u64) { + self.paint_time_metrics.maybe_set_metric(epoch, paint_time); + } } impl LayoutThread { fn root_flow_for_query(&self) -> Option { @@ -1181,28 +1176,6 @@ impl LayoutThread { ); } - fn set_scroll_states(&mut self, new_scroll_states: Vec) { - let mut script_scroll_states = vec![]; - let mut layout_scroll_states = HashMap::new(); - for new_state in &new_scroll_states { - let offset = new_state.scroll_offset; - layout_scroll_states.insert(new_state.scroll_id, offset); - - if new_state.scroll_id.is_root() { - script_scroll_states.push((UntrustedNodeAddress::from_id(0), offset)) - } else if let Some(node_id) = node_id_from_scroll_id(new_state.scroll_id.0 as usize) { - script_scroll_states.push((UntrustedNodeAddress::from_id(node_id), offset)) - } - } - let _ = self - .script_chan - .send(ConstellationControlMsg::SetScrollState( - self.id, - script_scroll_states, - )); - *self.scroll_offsets.borrow_mut() = layout_scroll_states - } - /// Cancel animations for any nodes which have been removed from flow tree. /// TODO(mrobinson): We should look into a way of doing this during flow tree construction. /// This also doesn't yet handles nodes that have been reparented. diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 63af1c98349..4d518d78d77 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -50,13 +50,12 @@ use profile_traits::time::{ }; use script::layout_dom::{ServoLayoutDocument, ServoLayoutElement, ServoLayoutNode}; use script_layout_interface::{ - node_id_from_scroll_id, Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, - OffsetParentResponse, ReflowComplete, ReflowGoal, ScriptReflow, TrustedNodeAddress, + Layout, LayoutConfig, LayoutFactory, NodesFromPointQueryType, OffsetParentResponse, + ReflowComplete, ReflowGoal, ScriptReflow, TrustedNodeAddress, }; use script_traits::{ - ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutControlMsg, - LayoutMsg as ConstellationMsg, PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, - WindowSizeData, WindowSizeType, + ConstellationControlMsg, DrawAPaintImageResult, IFrameSizeMsg, LayoutMsg as ConstellationMsg, + PaintWorkletError, Painter, ScrollState, UntrustedNodeAddress, WindowSizeData, WindowSizeType, }; use servo_arc::Arc as ServoArc; use servo_atoms::Atom; @@ -221,20 +220,6 @@ impl Drop for ScriptReflowResult { } impl Layout for LayoutThread { - fn handle_constellation_message( - &mut self, - constellation_message: script_traits::LayoutControlMsg, - ) { - match constellation_message { - LayoutControlMsg::SetScrollStates(new_scroll_states) => { - self.set_scroll_states(new_scroll_states); - }, - LayoutControlMsg::PaintMetric(epoch, paint_time) => { - self.paint_time_metrics.maybe_set_metric(epoch, paint_time); - }, - } - } - fn device(&self) -> &Device { self.stylist.device() } @@ -469,6 +454,17 @@ impl Layout for LayoutThread { _painter: Box, ) { } + + fn set_scroll_states(&mut self, scroll_states: &[ScrollState]) { + *self.scroll_offsets.borrow_mut() = scroll_states + .iter() + .map(|scroll_state| (scroll_state.scroll_id, scroll_state.scroll_offset)) + .collect(); + } + + fn set_epoch_paint_time(&mut self, epoch: Epoch, paint_time: u64) { + self.paint_time_metrics.maybe_set_metric(epoch, paint_time); + } } impl LayoutThread { @@ -831,28 +827,6 @@ impl LayoutThread { ); } - fn set_scroll_states(&mut self, new_scroll_states: Vec) { - let mut script_scroll_states = vec![]; - let mut layout_scroll_states = HashMap::new(); - for new_state in &new_scroll_states { - let offset = new_state.scroll_offset; - layout_scroll_states.insert(new_state.scroll_id, offset); - - if new_state.scroll_id.is_root() { - script_scroll_states.push((UntrustedNodeAddress::from_id(0), offset)) - } else if let Some(node_id) = node_id_from_scroll_id(new_state.scroll_id.0 as usize) { - script_scroll_states.push((UntrustedNodeAddress::from_id(node_id), offset)) - } - } - let _ = self - .script_chan - .send(ConstellationControlMsg::SetScrollState( - self.id, - script_scroll_states, - )); - self.scroll_offsets = RefCell::new(layout_scroll_states); - } - fn perform_post_style_recalc_layout_passes( &self, fragment_tree: Arc, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 25fc32fcdb7..f3b13f8deb8 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -26,8 +26,8 @@ use std::rc::Rc; use std::result::Result; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::thread; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; -use std::{ptr, thread}; use background_hang_monitor_api::{ BackgroundHangMonitor, BackgroundHangMonitorExitSignal, HangAnnotation, MonitoredComponentId, @@ -36,6 +36,7 @@ use background_hang_monitor_api::{ use base::id::{ BrowsingContextId, HistoryStateId, PipelineId, PipelineNamespace, TopLevelBrowsingContextId, }; +use base::Epoch; use bluetooth_traits::BluetoothRequest; use canvas_traits::webgl::WebGLPipeline; use chrono::{DateTime, Local}; @@ -46,7 +47,6 @@ use devtools_traits::{ }; use embedder_traits::EmbedderMsg; use euclid::default::{Point2D, Rect}; -use euclid::Vector2D; use gfx::font_cache_thread::FontCacheThread; use headers::{HeaderMapExt, LastModified, ReferrerPolicy as ReferrerPolicyHeader}; use html5ever::{local_name, namespace_url, ns}; @@ -73,13 +73,15 @@ use parking_lot::Mutex; use percent_encoding::percent_decode; use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan}; use profile_traits::time::{self as profile_time, profile, ProfilerCategory}; -use script_layout_interface::{LayoutConfig, LayoutFactory, ReflowGoal, ScriptThreadFactory}; +use script_layout_interface::{ + node_id_from_scroll_id, LayoutConfig, LayoutFactory, ReflowGoal, ScriptThreadFactory, +}; use script_traits::webdriver_msg::WebDriverScriptCommand; use script_traits::{ CompositorEvent, ConstellationControlMsg, DiscardBrowsingContext, DocumentActivity, - EventResult, HistoryEntryReplacement, InitialScriptState, JsEvalResult, LayoutControlMsg, - LayoutMsg, LoadData, LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType, - NewLayoutInfo, Painter, ProgressiveWebMetricType, ScriptMsg, ScriptToConstellationChan, + EventResult, HistoryEntryReplacement, InitialScriptState, JsEvalResult, LayoutMsg, LoadData, + LoadOrigin, MediaSessionActionType, MouseButton, MouseEventType, NewLayoutInfo, Painter, + ProgressiveWebMetricType, ScriptMsg, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerSchedulerMsg, TouchEventType, TouchId, UntrustedNodeAddress, UpdatePipelineIdReason, WheelDelta, WindowSizeData, WindowSizeType, }; @@ -91,7 +93,6 @@ use style::thread_state::{self, ThreadState}; use time::precise_time_ns; use url::Position; use webgpu::WebGPUMsg; -use webrender_api::units::LayoutPixel; use webrender_api::DocumentId; use webrender_traits::WebRenderScriptApi; @@ -1836,11 +1837,6 @@ impl ScriptThread { .profile_event(ScriptThreadEventCategory::SetViewport, Some(id), || { self.handle_viewport(id, rect); }), - FromConstellation(ConstellationControlMsg::SetScrollState(id, scroll_state)) => { - self.profile_event(ScriptThreadEventCategory::SetScrollState, Some(id), || { - self.handle_set_scroll_state(id, &scroll_state); - }) - }, FromConstellation(ConstellationControlMsg::TickAllAnimations( pipeline_id, tick_type, @@ -2097,7 +2093,6 @@ impl ScriptThread { ExitScriptThread => None, SendEvent(id, ..) => Some(id), Viewport(id, ..) => Some(id), - SetScrollState(id, ..) => Some(id), GetTitle(id) => Some(id), SetDocumentActivity(id, ..) => Some(id), SetThrottled(id, ..) => Some(id), @@ -2123,7 +2118,8 @@ impl ScriptThread { ExitFullScreen(id, ..) => Some(id), MediaSessionAction(..) => None, SetWebGPUPort(..) => None, - ForLayoutFromConstellation(_, id) => Some(id), + SetScrollStates(id, ..) => Some(id), + SetEpochPaintTime(id, ..) => Some(id), }, MixedMessage::FromDevtools(_) => None, MixedMessage::FromScript(ref inner_msg) => match *inner_msg { @@ -2348,7 +2344,6 @@ impl ScriptThread { }, msg @ ConstellationControlMsg::AttachLayout(..) | msg @ ConstellationControlMsg::Viewport(..) | - msg @ ConstellationControlMsg::SetScrollState(..) | msg @ ConstellationControlMsg::Resize(..) | msg @ ConstellationControlMsg::ExitFullScreen(..) | msg @ ConstellationControlMsg::SendEvent(..) | @@ -2356,22 +2351,53 @@ impl ScriptThread { msg @ ConstellationControlMsg::ExitScriptThread => { panic!("should have handled {:?} already", msg) }, - ConstellationControlMsg::ForLayoutFromConstellation(msg, pipeline_id) => { - self.handle_layout_message_from_constellation(msg, pipeline_id) + ConstellationControlMsg::SetScrollStates(pipeline_id, scroll_states) => { + self.handle_set_scroll_states_msg(pipeline_id, scroll_states) + }, + ConstellationControlMsg::SetEpochPaintTime(pipeline_id, epoch, time) => { + self.handle_set_epoch_paint_time(pipeline_id, epoch, time) }, } } - fn handle_layout_message_from_constellation( + fn handle_set_scroll_states_msg( &self, - msg: LayoutControlMsg, pipeline_id: PipelineId, + scroll_states: Vec, ) { let Some(window) = self.documents.borrow().find_window(pipeline_id) else { - warn!("Received layout message pipeline {pipeline_id} closed: {msg:?}."); + warn!("Received scroll states for closed pipeline {pipeline_id}"); return; }; - window.layout_mut().handle_constellation_message(msg); + + self.profile_event( + ScriptThreadEventCategory::SetScrollState, + Some(pipeline_id), + || { + window.layout_mut().set_scroll_states(&scroll_states); + + let mut scroll_offsets = HashMap::new(); + for scroll_state in scroll_states.into_iter() { + let scroll_offset = scroll_state.scroll_offset; + if scroll_state.scroll_id.is_root() { + window.update_viewport_for_scroll(-scroll_offset.x, -scroll_offset.y); + } else if let Some(node_id) = + node_id_from_scroll_id(scroll_state.scroll_id.0 as usize) + { + scroll_offsets.insert(OpaqueNode(node_id), -scroll_offset); + } + } + window.set_scroll_offsets(scroll_offsets) + }, + ) + } + + fn handle_set_epoch_paint_time(&self, pipeline_id: PipelineId, epoch: Epoch, time: u64) { + let Some(window) = self.documents.borrow().find_window(pipeline_id) else { + warn!("Received set epoch paint time message for closed pipeline {pipeline_id}."); + return; + }; + window.layout_mut().set_epoch_paint_time(epoch, time); } fn handle_msg_from_webgpu_server(&self, msg: WebGPUMsg) { @@ -2763,32 +2789,6 @@ impl ScriptThread { warn!("Page rect message sent to nonexistent pipeline"); } - fn handle_set_scroll_state( - &self, - id: PipelineId, - scroll_states: &[(UntrustedNodeAddress, Vector2D)], - ) { - let window = match self.documents.borrow().find_window(id) { - Some(window) => window, - None => { - return warn!( - "Set scroll state message sent to nonexistent pipeline: {:?}", - id - ); - }, - }; - - let mut scroll_offsets = HashMap::new(); - for &(node_address, ref scroll_offset) in scroll_states { - if node_address == UntrustedNodeAddress(ptr::null()) { - window.update_viewport_for_scroll(-scroll_offset.x, -scroll_offset.y); - } else { - scroll_offsets.insert(OpaqueNode(node_address.0 as usize), -*scroll_offset); - } - } - window.set_scroll_offsets(scroll_offsets) - } - fn handle_new_layout(&self, new_layout_info: NewLayoutInfo, origin: MutableOrigin) { let NewLayoutInfo { parent_info, diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index 931e34c2a2b..2a1947f58a7 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -110,15 +110,6 @@ impl UntrustedNodeAddress { } } -/// Messages sent to layout from the constellation and/or compositor. -#[derive(Debug, Deserialize, Serialize)] -pub enum LayoutControlMsg { - /// Tells layout about the new scrolling offsets of each scrollable stacking context. - SetScrollStates(Vec), - /// Send the paint time for a specific epoch to layout. - PaintMetric(Epoch, u64), -} - /// The origin where a given load was initiated. /// Useful for origin checks, for example before evaluation a JS URL. #[derive(Clone, Debug, Deserialize, Serialize)] @@ -302,11 +293,6 @@ pub enum ConstellationControlMsg { SendEvent(PipelineId, CompositorEvent), /// Notifies script of the viewport. Viewport(PipelineId, Rect), - /// Notifies script of a new set of scroll offsets. - SetScrollState( - PipelineId, - Vec<(UntrustedNodeAddress, Vector2D)>, - ), /// Requests that the script thread immediately send the constellation the title of a pipeline. GetTitle(PipelineId), /// Notifies script thread of a change to one of its document's activity @@ -391,8 +377,11 @@ pub enum ConstellationControlMsg { MediaSessionAction(PipelineId, MediaSessionActionType), /// Notifies script thread that WebGPU server has started SetWebGPUPort(IpcReceiver), - /// A mesage for a layout from the constellation. - ForLayoutFromConstellation(LayoutControlMsg, PipelineId), + /// The compositor scrolled and is updating the scroll states of the nodes in the given + /// pipeline via the Constellation. + SetScrollStates(PipelineId, Vec), + /// Send the paint time for a specific epoch. + SetEpochPaintTime(PipelineId, Epoch, u64), } impl fmt::Debug for ConstellationControlMsg { @@ -409,7 +398,6 @@ impl fmt::Debug for ConstellationControlMsg { ExitScriptThread => "ExitScriptThread", SendEvent(..) => "SendEvent", Viewport(..) => "Viewport", - SetScrollState(..) => "SetScrollState", GetTitle(..) => "GetTitle", SetDocumentActivity(..) => "SetDocumentActivity", SetThrottled(..) => "SetThrottled", @@ -431,7 +419,8 @@ impl fmt::Debug for ConstellationControlMsg { ExitFullScreen(..) => "ExitFullScreen", MediaSessionAction(..) => "MediaSessionAction", SetWebGPUPort(..) => "SetWebGPUPort", - ForLayoutFromConstellation(..) => "ForLayoutFromConstellation", + SetScrollStates(..) => "SetScrollStates", + SetEpochPaintTime(..) => "SetEpochPaintTime", }; write!(formatter, "ConstellationControlMsg::{}", variant) } diff --git a/components/shared/script_layout/lib.rs b/components/shared/script_layout/lib.rs index b65d42d1731..baf885e3524 100644 --- a/components/shared/script_layout/lib.rs +++ b/components/shared/script_layout/lib.rs @@ -33,8 +33,8 @@ use net_traits::ResourceThreads; use profile_traits::mem::Report; use profile_traits::time; use script_traits::{ - ConstellationControlMsg, InitialScriptState, LayoutControlMsg, LayoutMsg, LoadData, Painter, - ScrollState, UntrustedNodeAddress, WindowSizeData, + ConstellationControlMsg, InitialScriptState, LayoutMsg, LoadData, Painter, ScrollState, + UntrustedNodeAddress, WindowSizeData, }; use serde::{Deserialize, Serialize}; use servo_arc::Arc as ServoArc; @@ -178,9 +178,6 @@ pub trait LayoutFactory: Send + Sync { } pub trait Layout { - /// Handle a single message from the Constellation. - fn handle_constellation_message(&mut self, msg: LayoutControlMsg); - /// Get a reference to this Layout's Stylo `Device` used to handle media queries and /// resolve font metrics. fn device(&self) -> &Device; @@ -228,6 +225,12 @@ pub trait Layout { painter: Box, ); + /// Set the scroll states of this layout after a compositor scroll. + fn set_scroll_states(&mut self, scroll_states: &[ScrollState]); + + /// Set the paint time for a specific epoch. + fn set_epoch_paint_time(&mut self, epoch: Epoch, paint_time: u64); + fn query_content_box(&self, node: OpaqueNode) -> Option>; fn query_content_boxes(&self, node: OpaqueNode) -> Vec>; fn query_client_rect(&self, node: OpaqueNode) -> Rect;