mirror of
https://github.com/servo/servo.git
synced 2025-08-23 06:15:35 +01:00
Auto merge of #6031 - glennw:reftest-race-conditions, r=larsberg,jdm
The basic idea is it's safe to output an image for reftest by testing: - That the compositor doesn't have any animations active. - That the compositor is not waiting on any outstanding paint messages to arrive. - That the script tasks are "idle" and therefore won't cause reflow. - This currently means page loaded, onload fired, reftest-wait not active, first reflow triggered. - It could easily be expanded to handle pending timers etc. - That the "epoch" that the layout tasks have last laid out after script went idle, is reflected by the compositor in all visible layers for that pipeline. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6031) <!-- Reviewable:end -->
This commit is contained in:
commit
5e61ebaa05
17 changed files with 363 additions and 390 deletions
|
@ -20,8 +20,8 @@ use layers::platform::surface::{NativeGraphicsMetadata, NativePaintingGraphicsCo
|
|||
use layers::platform::surface::NativeSurface;
|
||||
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
|
||||
use layers;
|
||||
use msg::compositor_msg::{Epoch, FrameTreeId, PaintState, LayerId};
|
||||
use msg::compositor_msg::{LayerMetadata, PaintListener, ScrollPolicy};
|
||||
use msg::compositor_msg::{Epoch, FrameTreeId, LayerId};
|
||||
use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
|
||||
use msg::constellation_msg::PipelineExitType;
|
||||
|
@ -67,7 +67,7 @@ pub struct PaintRequest {
|
|||
}
|
||||
|
||||
pub enum Msg {
|
||||
PaintInit(Arc<StackingContext>),
|
||||
PaintInit(Epoch, Arc<StackingContext>),
|
||||
Paint(Vec<PaintRequest>, FrameTreeId),
|
||||
UnusedBuffer(Vec<Box<LayerBuffer>>),
|
||||
PaintPermissionGranted,
|
||||
|
@ -112,8 +112,8 @@ pub struct PaintTask<C> {
|
|||
/// Permission to send paint messages to the compositor
|
||||
paint_permission: bool,
|
||||
|
||||
/// A counter for epoch messages
|
||||
epoch: Epoch,
|
||||
/// The current epoch counter is passed by the layout task
|
||||
current_epoch: Option<Epoch>,
|
||||
|
||||
/// A data structure to store unused LayerBuffers
|
||||
buffer_map: BufferMap,
|
||||
|
@ -165,7 +165,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
native_graphics_context: native_graphics_context,
|
||||
root_stacking_context: None,
|
||||
paint_permission: false,
|
||||
epoch: Epoch(0),
|
||||
current_epoch: None,
|
||||
buffer_map: BufferMap::new(10000000),
|
||||
worker_threads: worker_threads,
|
||||
used_buffer_count: 0,
|
||||
|
@ -197,7 +197,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
let mut waiting_for_compositor_buffers_to_exit = false;
|
||||
loop {
|
||||
match self.port.recv().unwrap() {
|
||||
Msg::PaintInit(stacking_context) => {
|
||||
Msg::PaintInit(epoch, stacking_context) => {
|
||||
self.current_epoch = Some(epoch);
|
||||
self.root_stacking_context = Some(stacking_context.clone());
|
||||
|
||||
if !self.paint_permission {
|
||||
|
@ -207,7 +208,6 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
continue;
|
||||
}
|
||||
|
||||
self.epoch.next();
|
||||
self.initialize_layers();
|
||||
}
|
||||
Msg::Paint(requests, frame_tree_id) => {
|
||||
|
@ -215,30 +215,26 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
debug!("PaintTask: paint ready msg");
|
||||
let ConstellationChan(ref mut c) = self.constellation_chan;
|
||||
c.send(ConstellationMsg::PainterReady(self.id)).unwrap();
|
||||
self.compositor.paint_msg_discarded();
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut replies = Vec::new();
|
||||
self.compositor.set_paint_state(self.id, PaintState::Painting);
|
||||
for PaintRequest { buffer_requests, scale, layer_id, epoch }
|
||||
in requests.into_iter() {
|
||||
if self.epoch == epoch {
|
||||
if self.current_epoch == Some(epoch) {
|
||||
self.paint(&mut replies, buffer_requests, scale, layer_id);
|
||||
} else {
|
||||
debug!("painter epoch mismatch: {:?} != {:?}", self.epoch, epoch);
|
||||
debug!("painter epoch mismatch: {:?} != {:?}", self.current_epoch, epoch);
|
||||
}
|
||||
}
|
||||
|
||||
self.compositor.set_paint_state(self.id, PaintState::Idle);
|
||||
|
||||
for reply in replies.iter() {
|
||||
let &(_, ref buffer_set) = reply;
|
||||
self.used_buffer_count += (*buffer_set).buffers.len();
|
||||
}
|
||||
|
||||
debug!("PaintTask: returning surfaces");
|
||||
self.compositor.assign_painted_buffers(self.id, self.epoch, replies, frame_tree_id);
|
||||
self.compositor.assign_painted_buffers(self.id, self.current_epoch.unwrap(), replies, frame_tree_id);
|
||||
}
|
||||
Msg::UnusedBuffer(unused_buffers) => {
|
||||
debug!("PaintTask: Received {} unused buffers", unused_buffers.len());
|
||||
|
@ -258,7 +254,6 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
self.paint_permission = true;
|
||||
|
||||
if self.root_stacking_context.is_some() {
|
||||
self.epoch.next();
|
||||
self.initialize_layers();
|
||||
}
|
||||
}
|
||||
|
@ -379,11 +374,11 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
Some(ref root_stacking_context) => root_stacking_context,
|
||||
};
|
||||
|
||||
let mut metadata = Vec::new();
|
||||
build(&mut metadata, &**root_stacking_context, &ZERO_POINT);
|
||||
self.compositor.initialize_layers_for_pipeline(self.id, metadata, self.epoch);
|
||||
let mut properties = Vec::new();
|
||||
build(&mut properties, &**root_stacking_context, &ZERO_POINT);
|
||||
self.compositor.initialize_layers_for_pipeline(self.id, properties, self.current_epoch.unwrap());
|
||||
|
||||
fn build(metadata: &mut Vec<LayerMetadata>,
|
||||
fn build(properties: &mut Vec<LayerProperties>,
|
||||
stacking_context: &StackingContext,
|
||||
page_position: &Point2D<Au>) {
|
||||
let page_position = stacking_context.bounds.origin + *page_position;
|
||||
|
@ -392,20 +387,20 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
|
|||
// the compositor is concerned.
|
||||
let overflow_relative_page_position = page_position + stacking_context.overflow.origin;
|
||||
let layer_position =
|
||||
Rect(Point2D(overflow_relative_page_position.x.to_nearest_px() as i32,
|
||||
overflow_relative_page_position.y.to_nearest_px() as i32),
|
||||
Size2D(stacking_context.overflow.size.width.to_nearest_px() as i32,
|
||||
stacking_context.overflow.size.height.to_nearest_px() as i32));
|
||||
metadata.push(LayerMetadata {
|
||||
Rect(Point2D(overflow_relative_page_position.x.to_nearest_px() as f32,
|
||||
overflow_relative_page_position.y.to_nearest_px() as f32),
|
||||
Size2D(stacking_context.overflow.size.width.to_nearest_px() as f32,
|
||||
stacking_context.overflow.size.height.to_nearest_px() as f32));
|
||||
properties.push(LayerProperties {
|
||||
id: paint_layer.id,
|
||||
position: layer_position,
|
||||
rect: layer_position,
|
||||
background_color: paint_layer.background_color,
|
||||
scroll_policy: paint_layer.scroll_policy,
|
||||
})
|
||||
}
|
||||
|
||||
for kid in stacking_context.display_list.children.iter() {
|
||||
build(metadata, &**kid, &page_position)
|
||||
build(properties, &**kid, &page_position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue