constellation: Proxy ScrollState through the Constellation (#36062)

This will allow removing the dependency of the compositor on
`script_traits`, which should make our internal dependency chain a lot
easier to deal with.

Part of #35984.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-03-21 13:09:01 +01:00 committed by GitHub
parent ec20d9a3d7
commit 1f232eb17c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 60 additions and 33 deletions

View file

@ -16,13 +16,13 @@ use embedder_traits::{
use euclid::{Point2D, Scale, Vector2D}; use euclid::{Point2D, Scale, Vector2D};
use fnv::FnvHashSet; use fnv::FnvHashSet;
use log::{debug, warn}; use log::{debug, warn};
use script_traits::{AnimationState, ScriptThreadMessage, ScrollState, TouchEventResult}; use script_traits::{AnimationState, ScriptThreadMessage, TouchEventResult};
use webrender::Transaction; use webrender::Transaction;
use webrender_api::units::{DeviceIntPoint, DevicePoint, DeviceRect, LayoutVector2D}; use webrender_api::units::{DeviceIntPoint, DevicePoint, DeviceRect, LayoutVector2D};
use webrender_api::{ use webrender_api::{
ExternalScrollId, HitTestFlags, RenderReasons, SampledScrollOffset, ScrollLocation, ExternalScrollId, HitTestFlags, RenderReasons, SampledScrollOffset, ScrollLocation,
}; };
use webrender_traits::CompositorHitTestResult; use webrender_traits::{CompositorHitTestResult, ScrollState};
use crate::IOCompositor; use crate::IOCompositor;
use crate::compositor::{PipelineDetails, ServoRenderer}; use crate::compositor::{PipelineDetails, ServoRenderer};

View file

@ -160,7 +160,7 @@ use webgpu::{self, WebGPU, WebGPURequest, WebGPUResponse};
use webrender::RenderApi; use webrender::RenderApi;
use webrender::RenderApiSender; use webrender::RenderApiSender;
use webrender_api::{DocumentId, ImageKey}; use webrender_api::{DocumentId, ImageKey};
use webrender_traits::{CompositorHitTestResult, WebrenderExternalImageRegistry}; use webrender_traits::{CompositorHitTestResult, ScrollState, WebrenderExternalImageRegistry};
use crate::browsingcontext::{ use crate::browsingcontext::{
AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator, AllBrowsingContextsIterator, BrowsingContext, FullyActiveBrowsingContextsIterator,
@ -1406,6 +1406,9 @@ where
FromCompositorMsg::SetWebViewThrottled(webview_id, throttled) => { FromCompositorMsg::SetWebViewThrottled(webview_id, throttled) => {
self.set_webview_throttled(webview_id, throttled); self.set_webview_throttled(webview_id, throttled);
}, },
FromCompositorMsg::SetScrollStates(pipeline_id, scroll_states) => {
self.handle_set_scroll_states(pipeline_id, scroll_states)
},
} }
} }
@ -5562,4 +5565,24 @@ where
error!("Got a media session action but no active media session is registered"); error!("Got a media session action but no active media session is registered");
} }
} }
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, fields(servo_profiling = true), level = "trace")
)]
fn handle_set_scroll_states(&self, pipeline_id: PipelineId, scroll_states: Vec<ScrollState>) {
let Some(pipeline) = self.pipelines.get(&pipeline_id) else {
warn!("Discarding scroll offset update for unknown pipeline");
return;
};
if let Err(error) = pipeline
.event_loop
.send(ScriptThreadMessage::SetScrollStates(
pipeline_id,
scroll_states,
))
{
warn!("Could not send scroll offsets to pipeline: {pipeline_id:?}: {error:?}");
}
}
} }

View file

@ -86,6 +86,7 @@ mod from_compositor {
Self::ExitFullScreen(_) => target!("ExitFullScreen"), Self::ExitFullScreen(_) => target!("ExitFullScreen"),
Self::MediaSessionAction(_) => target!("MediaSessionAction"), Self::MediaSessionAction(_) => target!("MediaSessionAction"),
Self::SetWebViewThrottled(_, _) => target!("SetWebViewThrottled"), Self::SetWebViewThrottled(_, _) => target!("SetWebViewThrottled"),
Self::SetScrollStates(..) => target!("SetScrollStates"),
} }
} }
} }

View file

@ -51,8 +51,8 @@ use script_layout_interface::{
ReflowRequest, ReflowResult, TrustedNodeAddress, ReflowRequest, ReflowResult, TrustedNodeAddress,
}; };
use script_traits::{ use script_traits::{
DrawAPaintImageResult, PaintWorkletError, Painter, ScriptThreadMessage, ScrollState, DrawAPaintImageResult, PaintWorkletError, Painter, ScriptThreadMessage, UntrustedNodeAddress,
UntrustedNodeAddress, WindowSizeData, WindowSizeData,
}; };
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
use servo_config::opts::{self, DebugOptions}; use servo_config::opts::{self, DebugOptions};
@ -90,7 +90,7 @@ use stylo_atoms::Atom;
use url::Url; use url::Url;
use webrender_api::units::{DevicePixel, LayoutPixel}; use webrender_api::units::{DevicePixel, LayoutPixel};
use webrender_api::{ExternalScrollId, HitTestFlags, units}; use webrender_api::{ExternalScrollId, HitTestFlags, units};
use webrender_traits::CrossProcessCompositorApi; use webrender_traits::{CrossProcessCompositorApi, ScrollState};
// This mutex is necessary due to syncronisation issues between two different types of thread-local storage // This mutex is necessary due to syncronisation issues between two different types of thread-local storage
// which manifest themselves when the layout thread tries to layout iframes in parallel with the main page // which manifest themselves when the layout thread tries to layout iframes in parallel with the main page
@ -456,7 +456,7 @@ impl Layout for LayoutThread {
) { ) {
} }
fn set_scroll_states(&mut self, scroll_states: &[ScrollState]) { fn set_scroll_offsets(&mut self, scroll_states: &[ScrollState]) {
*self.scroll_offsets.borrow_mut() = scroll_states *self.scroll_offsets.borrow_mut() = scroll_states
.iter() .iter()
.map(|scroll_state| (scroll_state.scroll_id, scroll_state.scroll_offset)) .map(|scroll_state| (scroll_state.scroll_id, scroll_state.scroll_offset))

View file

@ -61,8 +61,7 @@ use script_layout_interface::{
}; };
use script_traits::{ use script_traits::{
DocumentState, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptMsg, ScriptThreadMessage, DocumentState, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptMsg, ScriptThreadMessage,
ScriptToConstellationChan, ScrollState, StructuredSerializedData, WindowSizeData, ScriptToConstellationChan, StructuredSerializedData, WindowSizeData, WindowSizeType,
WindowSizeType,
}; };
use selectors::attr::CaseSensitivity; use selectors::attr::CaseSensitivity;
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
@ -84,7 +83,7 @@ use stylo_atoms::Atom;
use url::Position; use url::Position;
use webrender_api::units::{DevicePixel, LayoutPixel}; use webrender_api::units::{DevicePixel, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId}; use webrender_api::{DocumentId, ExternalScrollId};
use webrender_traits::CrossProcessCompositorApi; use webrender_traits::{CrossProcessCompositorApi, ScrollState};
use super::bindings::codegen::Bindings::MessagePortBinding::StructuredSerializeOptions; use super::bindings::codegen::Bindings::MessagePortBinding::StructuredSerializeOptions;
use super::bindings::trace::HashMapTracedValues; use super::bindings::trace::HashMapTracedValues;

View file

@ -81,7 +81,7 @@ use script_traits::{
ConstellationInputEvent, DiscardBrowsingContext, DocumentActivity, InitialScriptState, ConstellationInputEvent, DiscardBrowsingContext, DocumentActivity, InitialScriptState,
JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, NewLayoutInfo, Painter, JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, NewLayoutInfo, Painter,
ProgressiveWebMetricType, ScriptMsg, ScriptThreadMessage, ScriptToConstellationChan, ProgressiveWebMetricType, ScriptMsg, ScriptThreadMessage, ScriptToConstellationChan,
ScrollState, StructuredSerializedData, UpdatePipelineIdReason, WindowSizeData, WindowSizeType, StructuredSerializedData, UpdatePipelineIdReason, WindowSizeData, WindowSizeType,
}; };
use servo_config::opts; use servo_config::opts;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
@ -93,7 +93,7 @@ use url::Position;
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webgpu::{WebGPUDevice, WebGPUMsg}; use webgpu::{WebGPUDevice, WebGPUMsg};
use webrender_api::DocumentId; use webrender_api::DocumentId;
use webrender_traits::{CompositorHitTestResult, CrossProcessCompositorApi}; use webrender_traits::{CompositorHitTestResult, CrossProcessCompositorApi, ScrollState};
use crate::document_collection::DocumentCollection; use crate::document_collection::DocumentCollection;
use crate::document_loader::DocumentLoader; use crate::document_loader::DocumentLoader;
@ -1870,7 +1870,7 @@ impl ScriptThread {
panic!("should have handled {:?} already", msg) panic!("should have handled {:?} already", msg)
}, },
ScriptThreadMessage::SetScrollStates(pipeline_id, scroll_states) => { ScriptThreadMessage::SetScrollStates(pipeline_id, scroll_states) => {
self.handle_set_scroll_states_msg(pipeline_id, scroll_states) self.handle_set_scroll_states_offsets(pipeline_id, scroll_states)
}, },
ScriptThreadMessage::SetEpochPaintTime(pipeline_id, epoch, time) => { ScriptThreadMessage::SetEpochPaintTime(pipeline_id, epoch, time) => {
self.handle_set_epoch_paint_time(pipeline_id, epoch, time) self.handle_set_epoch_paint_time(pipeline_id, epoch, time)
@ -1878,7 +1878,7 @@ impl ScriptThread {
} }
} }
fn handle_set_scroll_states_msg( fn handle_set_scroll_states_offsets(
&self, &self,
pipeline_id: PipelineId, pipeline_id: PipelineId,
scroll_states: Vec<ScrollState>, scroll_states: Vec<ScrollState>,
@ -1892,7 +1892,7 @@ impl ScriptThread {
ScriptThreadEventCategory::SetScrollState, ScriptThreadEventCategory::SetScrollState,
Some(pipeline_id), Some(pipeline_id),
|| { || {
window.layout_mut().set_scroll_states(&scroll_states); window.layout_mut().set_scroll_offsets(&scroll_states);
let mut scroll_offsets = HashMap::new(); let mut scroll_offsets = HashMap::new();
for scroll_state in scroll_states.into_iter() { for scroll_state in scroll_states.into_iter() {

View file

@ -15,7 +15,7 @@ use ipc_channel::ipc::IpcSender;
use script_traits::{AnimationTickType, LogEntry, WindowSizeData, WindowSizeType}; use script_traits::{AnimationTickType, LogEntry, WindowSizeData, WindowSizeType};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use strum_macros::IntoStaticStr; use strum_macros::IntoStaticStr;
use webrender_traits::CompositorHitTestResult; use webrender_traits::{CompositorHitTestResult, ScrollState};
/// Messages to the constellation. /// Messages to the constellation.
#[derive(IntoStaticStr)] #[derive(IntoStaticStr)]
@ -69,6 +69,9 @@ pub enum ConstellationMsg {
MediaSessionAction(MediaSessionActionType), MediaSessionAction(MediaSessionActionType),
/// Set whether to use less resources, by stopping animations and running timers at a heavily limited rate. /// Set whether to use less resources, by stopping animations and running timers at a heavily limited rate.
SetWebViewThrottled(WebViewId, bool), SetWebViewThrottled(WebViewId, bool),
/// The Servo renderer scrolled and is updating the scroll states of the nodes in the
/// given pipeline via the constellation.
SetScrollStates(PipelineId, Vec<ScrollState>),
} }
impl fmt::Debug for ConstellationMsg { impl fmt::Debug for ConstellationMsg {

View file

@ -33,7 +33,7 @@ use crossbeam_channel::{RecvTimeoutError, Sender};
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId}; use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
use embedder_traits::input_events::InputEvent; use embedder_traits::input_events::InputEvent;
use embedder_traits::{MediaSessionActionType, Theme, WebDriverScriptCommand}; use embedder_traits::{MediaSessionActionType, Theme, WebDriverScriptCommand};
use euclid::{Rect, Scale, Size2D, UnknownUnit, Vector2D}; use euclid::{Rect, Scale, Size2D, UnknownUnit};
use http::{HeaderMap, Method}; use http::{HeaderMap, Method};
use ipc_channel::Error as IpcError; use ipc_channel::Error as IpcError;
use ipc_channel::ipc::{IpcReceiver, IpcSender}; use ipc_channel::ipc::{IpcReceiver, IpcSender};
@ -56,10 +56,10 @@ use style_traits::{CSSPixel, SpeculativePainter};
use stylo_atoms::Atom; use stylo_atoms::Atom;
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webgpu::WebGPUMsg; use webgpu::WebGPUMsg;
use webrender_api::units::{DevicePixel, LayoutPixel}; use webrender_api::units::DevicePixel;
use webrender_api::{DocumentId, ExternalScrollId, ImageKey}; use webrender_api::{DocumentId, ImageKey};
use webrender_traits::{ use webrender_traits::{
CompositorHitTestResult, CrossProcessCompositorApi, CompositorHitTestResult, CrossProcessCompositorApi, ScrollState,
UntrustedNodeAddress as WebRenderUntrustedNodeAddress, UntrustedNodeAddress as WebRenderUntrustedNodeAddress,
}; };
@ -593,15 +593,6 @@ bitflags! {
} }
} }
/// The scroll state of a stacking context.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ScrollState {
/// The ID of the scroll root.
pub scroll_id: ExternalScrollId,
/// The scrolling offset of this stacking context.
pub scroll_offset: Vector2D<f32, LayoutPixel>,
}
/// Data about the window size. /// Data about the window size.
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct WindowSizeData { pub struct WindowSizeData {

View file

@ -33,7 +33,7 @@ use net_traits::image_cache::{ImageCache, PendingImageId};
use profile_traits::mem::Report; use profile_traits::mem::Report;
use profile_traits::time; use profile_traits::time;
use script_traits::{ use script_traits::{
InitialScriptState, LoadData, Painter, ScriptThreadMessage, ScrollState, UntrustedNodeAddress, InitialScriptState, LoadData, Painter, ScriptThreadMessage, UntrustedNodeAddress,
WindowSizeData, WindowSizeData,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -53,7 +53,7 @@ use style::selector_parser::{PseudoElement, RestyleDamage, Snapshot};
use style::stylesheets::Stylesheet; use style::stylesheets::Stylesheet;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use webrender_api::ImageKey; use webrender_api::ImageKey;
use webrender_traits::CrossProcessCompositorApi; use webrender_traits::{CrossProcessCompositorApi, ScrollState};
pub type GenericLayoutData = dyn Any + Send + Sync; pub type GenericLayoutData = dyn Any + Send + Sync;
@ -243,7 +243,7 @@ pub trait Layout {
); );
/// Set the scroll states of this layout after a compositor scroll. /// Set the scroll states of this layout after a compositor scroll.
fn set_scroll_states(&mut self, scroll_states: &[ScrollState]); fn set_scroll_offsets(&mut self, scroll_states: &[ScrollState]);
/// Set the paint time for a specific epoch. /// Set the paint time for a specific epoch.
fn set_epoch_paint_time(&mut self, epoch: Epoch, paint_time: CrossProcessInstant); fn set_epoch_paint_time(&mut self, epoch: Epoch, paint_time: CrossProcessInstant);

View file

@ -14,13 +14,14 @@ use std::sync::{Arc, Mutex};
use base::id::{PipelineId, WebViewId}; use base::id::{PipelineId, WebViewId};
use display_list::{CompositorDisplayListInfo, ScrollTreeNodeId}; use display_list::{CompositorDisplayListInfo, ScrollTreeNodeId};
use embedder_traits::Cursor; use embedder_traits::Cursor;
use euclid::Vector2D;
use euclid::default::Size2D as UntypedSize2D; use euclid::default::Size2D as UntypedSize2D;
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory}; use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
use libc::c_void; use libc::c_void;
use log::warn; use log::warn;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize}; use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize};
use webrender_api::units::{DevicePoint, LayoutPoint, TexelRect}; use webrender_api::units::{DevicePoint, LayoutPixel, LayoutPoint, TexelRect};
use webrender_api::{ use webrender_api::{
BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData, BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
ExternalImageHandler, ExternalImageId, ExternalImageSource, ExternalScrollId, ExternalImageHandler, ExternalImageId, ExternalImageSource, ExternalScrollId,
@ -530,3 +531,12 @@ pub struct CompositorHitTestResult {
/// The scroll tree node associated with this hit test item. /// The scroll tree node associated with this hit test item.
pub scroll_tree_node: ScrollTreeNodeId, pub scroll_tree_node: ScrollTreeNodeId,
} }
/// The scroll state of a stacking context.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ScrollState {
/// The ID of the scroll root.
pub scroll_id: ExternalScrollId,
/// The scrolling offset of this stacking context.
pub scroll_offset: Vector2D<f32, LayoutPixel>,
}