layout: Keep track of whether we've deferred the painting of the document due to

a script query.

This will, rather unfortunately, mean that we might repaint two times if we've
deferred a paint, then get an out-of-band reflow. Still seemed better than not
suppressing paints at all.

Fixes #13131
This commit is contained in:
Emilio Cobos Álvarez 2016-08-30 16:37:37 -07:00
parent 1fcc447941
commit fd9cd2f103
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
6 changed files with 106 additions and 52 deletions

View file

@ -85,7 +85,7 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCach
use profile_traits::mem::{self, Report, ReportKind, ReportsChan};
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use profile_traits::time::{self, TimerMetadata, profile};
use script::layout_wrapper::ServoLayoutNode;
use script::layout_wrapper::{ServoLayoutDocument, ServoLayoutNode};
use script_layout_interface::message::{Msg, NewLayoutThreadInfo, Reflow, ReflowQueryType, ScriptReflow};
use script_layout_interface::reporter::CSSErrorReporter;
use script_layout_interface::restyle_damage::{REPAINT, STORE_OVERFLOW, REFLOW_OUT_OF_FLOW, REFLOW};
@ -629,6 +629,7 @@ impl LayoutThread {
reflow_info.goal);
self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
&mut *rw_data,
&mut layout_context);
@ -901,6 +902,7 @@ impl LayoutThread {
fn compute_abs_pos_and_build_display_list(&mut self,
data: &Reflow,
document: Option<&ServoLayoutDocument>,
layout_root: &mut Flow,
shared_layout_context: &mut SharedLayoutContext,
rw_data: &mut LayoutThreadData) {
@ -962,59 +964,69 @@ impl LayoutThread {
Some(Arc::new(DisplayList::new(root_stacking_context, display_list_entries)))
}
if data.goal == ReflowGoal::ForDisplay {
let display_list = (*rw_data.display_list.as_ref().unwrap()).clone();
if data.goal != ReflowGoal::ForDisplay {
// Defer the paint step until the next ForDisplay.
//
// We need to tell the document about this so it doesn't
// incorrectly suppress reflows. See #13131.
document.expect("No document in a non-display reflow?")
.needs_paint_from_layout();
return;
}
if let Some(document) = document {
document.will_paint();
}
let display_list = (*rw_data.display_list.as_ref().unwrap()).clone();
if opts::get().dump_display_list {
display_list.print();
}
if opts::get().dump_display_list_json {
println!("{}", serde_json::to_string_pretty(&display_list).unwrap());
}
if opts::get().dump_display_list {
display_list.print();
}
if opts::get().dump_display_list_json {
println!("{}", serde_json::to_string_pretty(&display_list).unwrap());
}
debug!("Layout done!");
debug!("Layout done!");
self.epoch.next();
self.epoch.next();
if let Some(ref mut webrender_api) = self.webrender_api {
// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
let Epoch(epoch_number) = self.epoch;
let epoch = webrender_traits::Epoch(epoch_number);
let pipeline_id = self.id.to_webrender();
if let Some(ref mut webrender_api) = self.webrender_api {
// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
let Epoch(epoch_number) = self.epoch;
let epoch = webrender_traits::Epoch(epoch_number);
let pipeline_id = self.id.to_webrender();
// TODO(gw) For now only create a root scrolling layer!
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
let root_scroll_layer_id = frame_builder.next_scroll_layer_id();
let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
webrender_api,
pipeline_id,
epoch,
Some(root_scroll_layer_id),
&mut frame_builder);
let root_background_color = get_root_flow_background_color(layout_root);
let root_background_color =
webrender_traits::ColorF::new(root_background_color.r,
root_background_color.g,
root_background_color.b,
root_background_color.a);
// TODO(gw) For now only create a root scrolling layer!
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
let root_scroll_layer_id = frame_builder.next_scroll_layer_id();
let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
webrender_api,
pipeline_id,
epoch,
Some(root_scroll_layer_id),
&mut frame_builder);
let root_background_color = get_root_flow_background_color(layout_root);
let root_background_color =
webrender_traits::ColorF::new(root_background_color.r,
root_background_color.g,
root_background_color.b,
root_background_color.a);
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px());
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px());
webrender_api.set_root_stacking_context(
sc_id,
root_background_color,
epoch,
pipeline_id,
viewport_size,
frame_builder.stacking_contexts,
frame_builder.display_lists,
frame_builder.auxiliary_lists_builder.finalize());
} else {
self.paint_chan
.send(LayoutToPaintMsg::PaintInit(self.epoch, display_list))
.unwrap();
}
webrender_api.set_root_stacking_context(
sc_id,
root_background_color,
epoch,
pipeline_id,
viewport_size,
frame_builder.stacking_contexts,
frame_builder.display_lists,
frame_builder.auxiliary_lists_builder.finalize());
} else {
self.paint_chan
.send(LayoutToPaintMsg::PaintInit(self.epoch, display_list))
.unwrap();
}
});
}
@ -1205,6 +1217,7 @@ impl LayoutThread {
// Perform post-style recalculation layout passes.
self.perform_post_style_recalc_layout_passes(&data.reflow_info,
Some(&document),
&mut rw_data,
&mut shared_layout_context);
@ -1327,7 +1340,7 @@ impl LayoutThread {
false,
reflow_info.goal);
self.perform_post_main_layout_passes(&reflow_info, &mut *rw_data, &mut layout_context);
self.perform_post_main_layout_passes(&reflow_info, None, &mut *rw_data, &mut layout_context);
true
}
@ -1385,6 +1398,7 @@ impl LayoutThread {
}
self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
&mut *rw_data,
&mut layout_context);
}
@ -1407,12 +1421,14 @@ impl LayoutThread {
return
}
self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
&mut *rw_data,
&mut layout_context);
}
fn perform_post_style_recalc_layout_passes(&mut self,
data: &Reflow,
document: Option<&ServoLayoutDocument>,
rw_data: &mut LayoutThreadData,
layout_context: &mut SharedLayoutContext) {
if let Some(mut root_flow) = self.root_flow.clone() {
@ -1487,17 +1503,19 @@ impl LayoutThread {
flow_ref::deref_mut(&mut root_flow) as &mut Flow);
});
self.perform_post_main_layout_passes(data, rw_data, layout_context);
self.perform_post_main_layout_passes(data, document, rw_data, layout_context);
}
}
fn perform_post_main_layout_passes(&mut self,
data: &Reflow,
document: Option<&ServoLayoutDocument>,
rw_data: &mut LayoutThreadData,
layout_context: &mut SharedLayoutContext) {
// Build the display list if necessary, and send it to the painter.
if let Some(mut root_flow) = self.root_flow.clone() {
self.compute_abs_pos_and_build_display_list(data,
document,
flow_ref::deref_mut(&mut root_flow),
&mut *layout_context,
rw_data);