mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Make script thread initiate requests for images needed by layout.
In support of this goal, the layout thread collects information about CSS images that are missing image data and hands it off to the script thread after layout completes. The script thread stores a list of nodes that will need to be reflowed after the associated network request is complete. The script thread ensures that the nodes are not GCed while a request is ongoing, which the layout thread is incapable of guaranteeing. The image cache's API has also been redesigned in support of this work. No network requests are made by the new image cache, since it does not possess the document-specific information necessary to initiate them. Instead, there is now a single, synchronous query operation that optionally reserves a slot when a cache entry for a URL cannot be found. This reserved slot is then the responsibility of the queryer to populate with the contents of the network response for the URL once it is complete. Any subsequent queries for the same URL will be informed that the response is pending until that occurs. The changes to layout also remove the synchronous image loading code path, which means that reftests now test the same code that non-test binaries execute. The decision to take a screenshot now considers whether there are any outstanding image requests for layout in order to avoid intermittent failures in reftests that use CSS images.
This commit is contained in:
parent
78e8c31a4d
commit
c890c9143c
18 changed files with 528 additions and 388 deletions
|
@ -75,7 +75,7 @@ use layout::wrapper::LayoutNodeLayoutData;
|
|||
use layout::wrapper::drop_style_and_layout_data;
|
||||
use layout_traits::LayoutThreadFactory;
|
||||
use msg::constellation_msg::{FrameId, PipelineId};
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||
use net_traits::image_cache_thread::ImageCacheThread;
|
||||
use net_traits::image_cache_thread::UsePlaceholder;
|
||||
use parking_lot::RwLock;
|
||||
use profile_traits::mem::{self, Report, ReportKind, ReportsChan};
|
||||
|
@ -98,6 +98,7 @@ use servo_url::ServoUrl;
|
|||
use std::borrow::ToOwned;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::mem as std_mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::process;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
@ -137,12 +138,6 @@ pub struct LayoutThread {
|
|||
/// The port on which we receive messages from the constellation.
|
||||
pipeline_port: Receiver<LayoutControlMsg>,
|
||||
|
||||
/// The port on which we receive messages from the image cache
|
||||
image_cache_receiver: Receiver<ImageCacheResult>,
|
||||
|
||||
/// The channel on which the image cache can send messages to ourself.
|
||||
image_cache_sender: ImageCacheChan,
|
||||
|
||||
/// The port on which we receive messages from the font cache thread.
|
||||
font_cache_receiver: Receiver<()>,
|
||||
|
||||
|
@ -404,11 +399,6 @@ impl LayoutThread {
|
|||
// Proxy IPC messages from the pipeline to the layout thread.
|
||||
let pipeline_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(pipeline_port);
|
||||
|
||||
// Ask the router to proxy IPC messages from the image cache thread to the layout thread.
|
||||
let (ipc_image_cache_sender, ipc_image_cache_receiver) = ipc::channel().unwrap();
|
||||
let image_cache_receiver =
|
||||
ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_image_cache_receiver);
|
||||
|
||||
// Ask the router to proxy IPC messages from the font cache thread to the layout thread.
|
||||
let (ipc_font_cache_sender, ipc_font_cache_receiver) = ipc::channel().unwrap();
|
||||
let font_cache_receiver =
|
||||
|
@ -437,8 +427,6 @@ impl LayoutThread {
|
|||
image_cache_thread: image_cache_thread,
|
||||
font_cache_thread: font_cache_thread,
|
||||
first_reflow: true,
|
||||
image_cache_receiver: image_cache_receiver,
|
||||
image_cache_sender: ImageCacheChan(ipc_image_cache_sender),
|
||||
font_cache_receiver: font_cache_receiver,
|
||||
font_cache_sender: ipc_font_cache_sender,
|
||||
parallel_traversal: parallel_traversal,
|
||||
|
@ -470,6 +458,7 @@ impl LayoutThread {
|
|||
margin_style_response: MarginStyleResponse::empty(),
|
||||
stacking_context_scroll_offsets: HashMap::new(),
|
||||
text_index_response: TextIndexResponse(None),
|
||||
pending_images: vec![],
|
||||
})),
|
||||
error_reporter: CSSErrorReporter {
|
||||
pipelineid: id,
|
||||
|
@ -530,9 +519,9 @@ impl LayoutThread {
|
|||
default_computed_values: Arc::new(ComputedValues::initial_values().clone()),
|
||||
},
|
||||
image_cache_thread: Mutex::new(self.image_cache_thread.clone()),
|
||||
image_cache_sender: Mutex::new(self.image_cache_sender.clone()),
|
||||
font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
|
||||
webrender_image_cache: self.webrender_image_cache.clone(),
|
||||
pending_images: Mutex::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,14 +530,12 @@ impl LayoutThread {
|
|||
enum Request {
|
||||
FromPipeline(LayoutControlMsg),
|
||||
FromScript(Msg),
|
||||
FromImageCache,
|
||||
FromFontCache,
|
||||
}
|
||||
|
||||
let request = {
|
||||
let port_from_script = &self.port;
|
||||
let port_from_pipeline = &self.pipeline_port;
|
||||
let port_from_image_cache = &self.image_cache_receiver;
|
||||
let port_from_font_cache = &self.font_cache_receiver;
|
||||
select! {
|
||||
msg = port_from_pipeline.recv() => {
|
||||
|
@ -557,10 +544,6 @@ impl LayoutThread {
|
|||
msg = port_from_script.recv() => {
|
||||
Request::FromScript(msg.unwrap())
|
||||
},
|
||||
msg = port_from_image_cache.recv() => {
|
||||
msg.unwrap();
|
||||
Request::FromImageCache
|
||||
},
|
||||
msg = port_from_font_cache.recv() => {
|
||||
msg.unwrap();
|
||||
Request::FromFontCache
|
||||
|
@ -590,9 +573,6 @@ impl LayoutThread {
|
|||
Request::FromScript(msg) => {
|
||||
self.handle_request_helper(msg, possibly_locked_rw_data)
|
||||
},
|
||||
Request::FromImageCache => {
|
||||
self.repaint(possibly_locked_rw_data)
|
||||
},
|
||||
Request::FromFontCache => {
|
||||
let _rw_data = possibly_locked_rw_data.lock();
|
||||
self.outstanding_web_fonts.fetch_sub(1, Ordering::SeqCst);
|
||||
|
@ -603,37 +583,6 @@ impl LayoutThread {
|
|||
}
|
||||
}
|
||||
|
||||
/// Repaint the scene, without performing style matching. This is typically
|
||||
/// used when an image arrives asynchronously and triggers a relayout and
|
||||
/// repaint.
|
||||
/// TODO: In the future we could detect if the image size hasn't changed
|
||||
/// since last time and avoid performing a complete layout pass.
|
||||
fn repaint<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) -> bool {
|
||||
let mut rw_data = possibly_locked_rw_data.lock();
|
||||
|
||||
if let Some(mut root_flow) = self.root_flow.clone() {
|
||||
let flow = flow::mut_base(FlowRef::deref_mut(&mut root_flow));
|
||||
flow.restyle_damage.insert(REPAINT);
|
||||
}
|
||||
|
||||
let reflow_info = Reflow {
|
||||
goal: ReflowGoal::ForDisplay,
|
||||
page_clip_rect: max_rect(),
|
||||
};
|
||||
let mut layout_context = self.build_layout_context(&*rw_data,
|
||||
false,
|
||||
reflow_info.goal);
|
||||
|
||||
self.perform_post_style_recalc_layout_passes(&reflow_info,
|
||||
None,
|
||||
None,
|
||||
&mut *rw_data,
|
||||
&mut layout_context);
|
||||
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Receives and dispatches messages from other threads.
|
||||
fn handle_request_helper<'a, 'b>(&mut self,
|
||||
request: Msg,
|
||||
|
@ -1247,6 +1196,9 @@ impl LayoutThread {
|
|||
query_type: &ReflowQueryType,
|
||||
rw_data: &mut LayoutThreadData,
|
||||
context: &mut LayoutContext) {
|
||||
rw_data.pending_images =
|
||||
std_mem::replace(&mut context.pending_images.lock().unwrap(), vec![]);
|
||||
|
||||
let mut root_flow = match self.root_flow.clone() {
|
||||
Some(root_flow) => root_flow,
|
||||
None => return,
|
||||
|
@ -1387,6 +1339,14 @@ impl LayoutThread {
|
|||
None,
|
||||
&mut *rw_data,
|
||||
&mut layout_context);
|
||||
|
||||
let mut pending_images = layout_context.pending_images.lock().unwrap();
|
||||
if pending_images.len() > 0 {
|
||||
//XXXjdm we drop all the images on the floor, but there's no guarantee that
|
||||
// the node references are valid since the script thread isn't paused.
|
||||
// need to figure out what to do here!
|
||||
pending_images.truncate(0);
|
||||
}
|
||||
}
|
||||
|
||||
fn reflow_with_newly_loaded_web_font<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue