aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-01-14 19:12:59 -0500
committerGitHub <noreply@github.com>2019-01-14 19:12:59 -0500
commit2e439fa7cbfdd6f97d178ea617e8eb402e1db759 (patch)
tree6c67d7a73db73f026ecbcfa1440685788b3785d0
parent2cf9a00c9983bf23eff23d56321973d36a14f977 (diff)
parent49a100ca8baa22beba79d2187153e0f821d09561 (diff)
downloadservo-2e439fa7cbfdd6f97d178ea617e8eb402e1db759.tar.gz
servo-2e439fa7cbfdd6f97d178ea617e8eb402e1db759.zip
Auto merge of #22396 - jdm:no-spam-iframe-size, r=asajeffrey
Reduce unnecessary iframe size messages This should be an improvement on pages that include iframes, since we currently run two layout jobs for every display-oriented layout request. When building the display list, we send a message to the constellation that includes the sizes of all iframes present, and the constellation sends resize messages to the script thread. This results in a mouse event on the outer page causing all frames to be re-laid out even if no changes occurred to the iframe sizes, which is ridiculous. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #22394 - [x] These changes do not require tests because there is no way to test this internal detail. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22396) <!-- Reviewable:end -->
-rw-r--r--components/constellation/constellation.rs13
-rw-r--r--components/layout/display_list/builder.rs13
-rw-r--r--components/layout_thread/lib.rs46
-rw-r--r--components/script_traits/lib.rs4
-rw-r--r--components/script_traits/script_msg.rs21
5 files changed, 76 insertions, 21 deletions
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 80214a67a99..ec4c1f94273 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -146,9 +146,9 @@ use script_traits::{DocumentActivity, DocumentState, LayoutControlMsg, LoadData}
use script_traits::{
IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState, TimerSchedulerMsg,
};
+use script_traits::{IFrameSizeMsg, WindowSizeData, WindowSizeType};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WebDriverCommandMsg};
-use script_traits::{WindowSizeData, WindowSizeType};
use serde::{Deserialize, Serialize};
use servo_config::opts;
use servo_config::prefs::PREFS;
@@ -1837,17 +1837,14 @@ where
}
}
- fn handle_iframe_size_msg(
- &mut self,
- iframe_sizes: Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>,
- ) {
- for (browsing_context_id, size) in iframe_sizes {
+ fn handle_iframe_size_msg(&mut self, iframe_sizes: Vec<IFrameSizeMsg>) {
+ for IFrameSizeMsg { data, type_ } in iframe_sizes {
let window_size = WindowSizeData {
- initial_viewport: size,
+ initial_viewport: data.size,
device_pixel_ratio: self.window_size.device_pixel_ratio,
};
- self.resize_browsing_context(window_size, WindowSizeType::Initial, browsing_context_id);
+ self.resize_browsing_context(window_size, type_, data.id);
}
}
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs
index 18fb0980fcd..a6e77fe78b8 100644
--- a/components/layout/display_list/builder.rs
+++ b/components/layout/display_list/builder.rs
@@ -37,9 +37,10 @@ use gfx::text::glyph::ByteIndex;
use gfx::text::TextRun;
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
use ipc_channel::ipc;
-use msg::constellation_msg::{BrowsingContextId, PipelineId};
+use msg::constellation_msg::PipelineId;
use net_traits::image_cache::UsePlaceholder;
use range::Range;
+use script_traits::IFrameSize;
use servo_config::opts;
use servo_geometry::MaxRect;
use std::default::Default;
@@ -61,7 +62,6 @@ use style::values::generics::background::BackgroundSize;
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
use style::values::{Either, RGBA};
use style_traits::cursor::CursorKind;
-use style_traits::CSSPixel;
use style_traits::ToCss;
use webrender_api::{
self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF, ColorU,
@@ -318,7 +318,7 @@ pub struct DisplayListBuildState<'a> {
/// Vector containing iframe sizes, used to inform the constellation about
/// new iframe sizes
- pub iframe_sizes: Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>,
+ pub iframe_sizes: Vec<IFrameSize>,
/// Stores text runs to answer text queries used to place a cursor inside text.
pub indexable_text: IndexableText,
@@ -1785,9 +1785,10 @@ impl Fragment {
}));
let size = Size2D::new(item.bounds().size.width, item.bounds().size.height);
- state
- .iframe_sizes
- .push((browsing_context_id, TypedSize2D::from_untyped(&size)));
+ state.iframe_sizes.push(IFrameSize {
+ id: browsing_context_id,
+ size: TypedSize2D::from_untyped(&size),
+ });
state.add_display_item(item);
}
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index d0c4cd9e4da..ecc4153ab71 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -68,8 +68,8 @@ use metrics::{PaintTimeMetrics, ProfilerMetadataFactory, ProgressiveWebMetric};
use msg::constellation_msg::{
BackgroundHangMonitor, BackgroundHangMonitorRegister, HangAnnotation,
};
+use msg::constellation_msg::{BrowsingContextId, MonitoredComponentId, TopLevelBrowsingContextId};
use msg::constellation_msg::{LayoutHangAnnotation, MonitoredComponentType, PipelineId};
-use msg::constellation_msg::{MonitoredComponentId, TopLevelBrowsingContextId};
use net_traits::image_cache::{ImageCache, UsePlaceholder};
use parking_lot::RwLock;
use profile_traits::mem::{self as profile_mem, Report, ReportKind, ReportsChan};
@@ -82,7 +82,7 @@ use script_layout_interface::rpc::{LayoutRPC, OffsetParentResponse, StyleRespons
use script_layout_interface::wrapper_traits::LayoutNode;
use script_traits::Painter;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
-use script_traits::{DrawAPaintImageResult, PaintWorkletError};
+use script_traits::{DrawAPaintImageResult, IFrameSizeMsg, PaintWorkletError, WindowSizeType};
use script_traits::{ScrollState, UntrustedNodeAddress};
use selectors::Element;
use servo_arc::Arc as ServoArc;
@@ -241,6 +241,9 @@ pub struct LayoutThread {
/// The time a layout query has waited before serviced by layout thread.
layout_query_waiting_time: Histogram,
+
+ /// The sizes of all iframes encountered during the last layout operation.
+ last_iframe_sizes: RefCell<HashMap<BrowsingContextId, TypedSize2D<f32, CSSPixel>>>,
}
impl LayoutThreadFactory for LayoutThread {
@@ -544,6 +547,7 @@ impl LayoutThread {
},
paint_time_metrics: paint_time_metrics,
layout_query_waiting_time: Histogram::new(),
+ last_iframe_sizes: Default::default(),
}
}
@@ -1054,9 +1058,41 @@ impl LayoutThread {
// it with an empty vector
let iframe_sizes =
std::mem::replace(&mut build_state.iframe_sizes, vec![]);
- let msg = ConstellationMsg::IFrameSizes(iframe_sizes);
- if let Err(e) = self.constellation_chan.send(msg) {
- warn!("Layout resize to constellation failed ({}).", e);
+ // Collect the last frame's iframe sizes to compute any differences.
+ // Every frame starts with a fresh collection so that any removed
+ // iframes do not linger.
+ let last_iframe_sizes = std::mem::replace(
+ &mut *self.last_iframe_sizes.borrow_mut(),
+ HashMap::default(),
+ );
+ let mut size_messages = vec![];
+ for new_size in iframe_sizes {
+ // Only notify the constellation about existing iframes
+ // that have a new size, or iframes that did not previously
+ // exist.
+ if let Some(old_size) = last_iframe_sizes.get(&new_size.id) {
+ if *old_size != new_size.size {
+ size_messages.push(IFrameSizeMsg {
+ data: new_size,
+ type_: WindowSizeType::Resize,
+ });
+ }
+ } else {
+ size_messages.push(IFrameSizeMsg {
+ data: new_size,
+ type_: WindowSizeType::Initial,
+ });
+ }
+ self.last_iframe_sizes
+ .borrow_mut()
+ .insert(new_size.id, new_size.size);
+ }
+
+ if !size_messages.is_empty() {
+ let msg = ConstellationMsg::IFrameSizes(size_messages);
+ if let Err(e) = self.constellation_chan.send(msg) {
+ warn!("Layout resize to constellation failed ({}).", e);
+ }
}
}
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index b97544f9223..c033b491e35 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -61,7 +61,9 @@ use webvr_traits::{WebVREvent, WebVRMsg};
pub use crate::script_msg::{
DOMMessage, SWManagerMsg, SWManagerSenders, ScopeThings, ServiceWorkerMsg,
};
-pub use crate::script_msg::{EventResult, LayoutMsg, LogEntry, ScriptMsg};
+pub use crate::script_msg::{
+ EventResult, IFrameSize, IFrameSizeMsg, LayoutMsg, LogEntry, ScriptMsg,
+};
/// The address of a node. Layout sends these back. They must be validated via
/// `from_untrusted_node_address` before they can be used, because we do not trust layout.
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index a63462fd83f..7d5ce79e2f6 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -9,6 +9,7 @@ use crate::IFrameLoadInfo;
use crate::IFrameLoadInfoWithData;
use crate::LayoutControlMsg;
use crate::LoadData;
+use crate::WindowSizeType;
use crate::WorkerGlobalScopeInit;
use crate::WorkerScriptLoadOrigin;
use canvas_traits::canvas::{CanvasId, CanvasMsg};
@@ -30,13 +31,31 @@ use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webrender_api::{DeviceIntPoint, DeviceIntSize};
+/// A particular iframe's size, associated with a browsing context.
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+pub struct IFrameSize {
+ /// The child browsing context for this iframe.
+ pub id: BrowsingContextId,
+ /// The size of the iframe.
+ pub size: TypedSize2D<f32, CSSPixel>,
+}
+
+/// An iframe sizing operation.
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+pub struct IFrameSizeMsg {
+ /// The iframe sizing data.
+ pub data: IFrameSize,
+ /// The kind of sizing operation.
+ pub type_: WindowSizeType,
+}
+
/// Messages from the layout to the constellation.
#[derive(Deserialize, Serialize)]
pub enum LayoutMsg {
/// Indicates whether this pipeline is currently running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState),
/// Inform the constellation of the size of the iframe's viewport.
- IFrameSizes(Vec<(BrowsingContextId, TypedSize2D<f32, CSSPixel>)>),
+ IFrameSizes(Vec<IFrameSizeMsg>),
/// Requests that the constellation inform the compositor that it needs to record
/// the time when the frame with the given ID (epoch) is painted.
PendingPaintMetric(PipelineId, Epoch),