diff --git a/components/layout/query.rs b/components/layout/query.rs index a8d5913e3db..476a68afafe 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -17,7 +17,6 @@ use inline::LAST_FRAGMENT_OF_ELEMENT; use ipc_channel::ipc::IpcSender; use msg::constellation_msg::PipelineId; use opaque_node::OpaqueNodeMethods; -use script_layout_interface::PendingImage; use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse}; use script_layout_interface::rpc::{HitTestResponse, LayoutRPC}; use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse}; @@ -28,7 +27,6 @@ use script_traits::LayoutMsg as ConstellationMsg; use script_traits::UntrustedNodeAddress; use sequential; use std::cmp::{min, max}; -use std::mem; use std::ops::Deref; use std::sync::{Arc, Mutex}; use style::computed_values; @@ -89,14 +87,8 @@ pub struct LayoutThreadData { /// Index in a text fragment. We need this do determine the insertion point. pub text_index_response: TextIndexResponse, - /// A list of images requests that need to be initiated. - pub pending_images: Vec, - /// A queued response for the list of nodes at a given point. pub nodes_from_point_response: Vec, - - /// A list of nodes that have just started a CSS transition. - pub newly_transitioning_nodes: Vec, } pub struct LayoutRPCImpl(pub Arc>); @@ -201,18 +193,6 @@ impl LayoutRPC for LayoutRPCImpl { let rw_data = rw_data.lock().unwrap(); rw_data.text_index_response.clone() } - - fn pending_images(&self) -> Vec { - let &LayoutRPCImpl(ref rw_data) = self; - let mut rw_data = rw_data.lock().unwrap(); - mem::replace(&mut rw_data.pending_images, vec![]) - } - - fn newly_transitioning_nodes(&self) -> Vec { - let &LayoutRPCImpl(ref rw_data) = self; - let mut rw_data = rw_data.lock().unwrap(); - mem::replace(&mut rw_data.newly_transitioning_nodes, vec![]) - } } struct UnioningFragmentBorderBoxIterator { diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 32b47d57a22..7a3bf5cb9ab 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -81,7 +81,8 @@ use profile_traits::mem::{self, Report, ReportKind, ReportsChan}; use profile_traits::time::{self, TimerMetadata, profile}; use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType}; use script::layout_wrapper::{ServoLayoutElement, ServoLayoutDocument, ServoLayoutNode}; -use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow}; +use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType}; +use script_layout_interface::message::{ScriptReflow, ReflowComplete}; use script_layout_interface::reporter::CSSErrorReporter; use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowResponse, OffsetParentResponse}; use script_layout_interface::rpc::TextIndexResponse; @@ -292,6 +293,37 @@ impl LayoutThreadFactory for LayoutThread { } } +struct ScriptReflowResult { + script_reflow: ScriptReflow, + result: RefCell>, +} + +impl Deref for ScriptReflowResult { + type Target = ScriptReflow; + fn deref(&self) -> &ScriptReflow { + &self.script_reflow + } +} + +impl ScriptReflowResult { + fn new(script_reflow: ScriptReflow) -> ScriptReflowResult { + ScriptReflowResult { + script_reflow: script_reflow, + result: RefCell::new(Some(Default::default())), + } + } +} + +impl Drop for ScriptReflowResult { + fn drop(&mut self) { + self.script_reflow.script_join_chan.send( + self.result + .borrow_mut() + .take() + .unwrap()).unwrap(); + } +} + /// The `LayoutThread` `rw_data` lock must remain locked until the first reflow, /// as RPC calls don't make sense until then. Use this in combination with /// `LayoutThread::lock_rw_data` and `LayoutThread::return_rw_data`. @@ -476,9 +508,7 @@ impl LayoutThread { margin_style_response: MarginStyleResponse::empty(), stacking_context_scroll_offsets: HashMap::new(), text_index_response: TextIndexResponse(None), - pending_images: vec![], nodes_from_point_response: vec![], - newly_transitioning_nodes: vec![], })), error_reporter: CSSErrorReporter { pipelineid: id, @@ -616,10 +646,11 @@ impl LayoutThread { Box).unwrap(); }, Msg::Reflow(data) => { + let mut data = ScriptReflowResult::new(data); profile(time::ProfilerCategory::LayoutPerform, self.profiler_metadata(), self.time_profiler_chan.clone(), - || self.handle_reflow(&data, possibly_locked_rw_data)); + || self.handle_reflow(&mut data, possibly_locked_rw_data)); }, Msg::TickAnimations => self.tick_all_animations(possibly_locked_rw_data), Msg::SetStackingContextScrollStates(new_scroll_states) => { @@ -955,7 +986,7 @@ impl LayoutThread { /// The high-level routine that performs layout threads. fn handle_reflow<'a, 'b>(&mut self, - data: &ScriptReflow, + data: &mut ScriptReflowResult, possibly_locked_rw_data: &mut RwData<'a, 'b>) { let document = unsafe { ServoLayoutNode::new(&data.document) }; let document = document.as_document().unwrap(); @@ -1240,24 +1271,26 @@ impl LayoutThread { self.respond_to_query_if_necessary(&data.query_type, &mut *rw_data, - &mut layout_context); + &mut layout_context, + data.result.borrow_mut().as_mut().unwrap()); } fn respond_to_query_if_necessary(&self, query_type: &ReflowQueryType, rw_data: &mut LayoutThreadData, - context: &mut LayoutContext) { + context: &mut LayoutContext, + reflow_result: &mut ReflowComplete) { let pending_images = match context.pending_images { Some(ref pending) => std_mem::replace(&mut *pending.lock().unwrap(), vec![]), None => vec![], }; - rw_data.pending_images = pending_images; + reflow_result.pending_images = pending_images; let newly_transitioning_nodes = match context.newly_transitioning_nodes { Some(ref nodes) => std_mem::replace(&mut *nodes.lock().unwrap(), vec![]), None => vec![], }; - rw_data.newly_transitioning_nodes = newly_transitioning_nodes; + reflow_result.newly_transitioning_nodes = newly_transitioning_nodes; let mut root_flow = match self.root_flow.borrow().clone() { Some(root_flow) => root_flow, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index a783c15531b..3d55a0e82aa 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1214,16 +1214,16 @@ impl Window { debug!("script: layout forked"); - match join_port.try_recv() { + let complete = match join_port.try_recv() { Err(Empty) => { info!("script: waiting on layout"); - join_port.recv().unwrap(); + join_port.recv().unwrap() } - Ok(_) => {} + Ok(reflow_complete) => reflow_complete, Err(Disconnected) => { panic!("Layout thread failed while script was waiting for a result."); } - } + }; debug!("script: layout joined"); @@ -1237,8 +1237,7 @@ impl Window { self.emit_timeline_marker(marker.end()); } - let pending_images = self.layout_rpc.pending_images(); - for image in pending_images { + for image in complete.pending_images { let id = image.id; let js_runtime = self.js_runtime.borrow(); let js_runtime = js_runtime.as_ref().unwrap(); @@ -1262,8 +1261,7 @@ impl Window { } } - let newly_transitioning_nodes = self.layout_rpc.newly_transitioning_nodes(); - ScriptThread::note_newly_transitioning_nodes(newly_transitioning_nodes); + ScriptThread::note_newly_transitioning_nodes(complete.newly_transitioning_nodes); true } diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs index 8b04a131404..9c2f94b0dc0 100644 --- a/components/script_layout_interface/message.rs +++ b/components/script_layout_interface/message.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use {OpaqueStyleAndLayoutData, TrustedNodeAddress}; +use {OpaqueStyleAndLayoutData, TrustedNodeAddress, PendingImage}; use app_units::Au; use euclid::point::Point2D; use euclid::rect::Rect; @@ -12,7 +12,7 @@ use msg::constellation_msg::PipelineId; use net_traits::image_cache::ImageCache; use profile_traits::mem::ReportsChan; use rpc::LayoutRPC; -use script_traits::{ConstellationControlMsg, LayoutControlMsg}; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, UntrustedNodeAddress}; use script_traits::{LayoutMsg as ConstellationMsg, StackingContextScrollState, WindowSizeData}; use servo_url::ServoUrl; use std::sync::Arc; @@ -109,6 +109,15 @@ pub struct Reflow { pub page_clip_rect: Rect, } +/// Information derived from a layout pass that needs to be returned to the script thread. +#[derive(Default)] +pub struct ReflowComplete { + /// The list of images that were encountered that are in progress. + pub pending_images: Vec, + /// The list of nodes that initiated a CSS transition. + pub newly_transitioning_nodes: Vec, +} + /// Information needed for a script-initiated reflow. pub struct ScriptReflow { /// General reflow data. @@ -122,19 +131,13 @@ pub struct ScriptReflow { /// The current window size. pub window_size: WindowSizeData, /// The channel that we send a notification to. - pub script_join_chan: Sender<()>, + pub script_join_chan: Sender, /// The type of query if any to perform during this reflow. pub query_type: ReflowQueryType, /// The number of objects in the dom #10110 pub dom_count: u32, } -impl Drop for ScriptReflow { - fn drop(&mut self) { - self.script_join_chan.send(()).unwrap(); - } -} - pub struct NewLayoutThreadInfo { pub id: PipelineId, pub url: ServoUrl, diff --git a/components/script_layout_interface/rpc.rs b/components/script_layout_interface/rpc.rs index 1c694a7ff8c..a39e51d3633 100644 --- a/components/script_layout_interface/rpc.rs +++ b/components/script_layout_interface/rpc.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use PendingImage; use app_units::Au; use euclid::point::Point2D; use euclid::rect::Rect; @@ -38,12 +37,8 @@ pub trait LayoutRPC { fn offset_parent(&self) -> OffsetParentResponse; /// Query layout for the resolve values of the margin properties for an element. fn margin_style(&self) -> MarginStyleResponse; - /// Requests the list of not-yet-loaded images that were encountered in the last reflow. - fn pending_images(&self) -> Vec; /// Requests the list of nodes from the given point. fn nodes_from_point_response(&self) -> Vec; - /// Requests the list of nodes that have just started CSS transitions in the last reflow. - fn newly_transitioning_nodes(&self) -> Vec; fn text_index(&self) -> TextIndexResponse; }