Wait for actual paint before setting paint related metrics

This commit is contained in:
Fernando Jiménez Moreno 2017-07-26 20:24:42 +02:00
parent 1059ef4fde
commit 1b123400eb
16 changed files with 203 additions and 72 deletions

View file

@ -186,6 +186,13 @@ pub struct IOCompositor<Window: WindowMethods> {
/// GL functions interface (may be GL or GLES)
gl: Rc<gl::Gl>,
/// Map of the pending paint metrics per layout thread.
/// The layout thread for each specific pipeline expects the compositor to
/// paint frames with specific given IDs (epoch). Once the compositor paints
/// these frames, it records the paint time for each of them and sends the
/// metric to the corresponding layout thread.
pending_paint_metrics: HashMap<PipelineId, Epoch>,
}
#[derive(Copy, Clone)]
@ -371,6 +378,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
webrender: state.webrender,
webrender_document: state.webrender_document,
webrender_api: state.webrender_api,
pending_paint_metrics: HashMap::new(),
}
}
@ -593,6 +601,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.set_fullscreen_state(top_level_browsing_context_id, state);
}
(Msg::PendingPaintMetric(pipeline_id, epoch), _) => {
self.pending_paint_metrics.insert(pipeline_id, epoch);
}
// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.
@ -1427,6 +1439,38 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.webrender.render(self.frame_size);
});
// If there are pending paint metrics, we check if any of the painted epochs is
// one of the ones that the paint metrics recorder is expecting . In that case,
// we get the current time, inform the layout thread about it and remove the
// pending metric from the list.
if !self.pending_paint_metrics.is_empty() {
let paint_time = precise_time_ns() as f64;
let mut to_remove = Vec::new();
// For each pending paint metrics pipeline id
for (id, pending_epoch) in &self.pending_paint_metrics {
// we get the last painted frame id from webrender
if let Some(webrender_api::Epoch(epoch)) = self.webrender.current_epoch(id.to_webrender()) {
// and check if it is the one the layout thread is expecting,
let epoch = Epoch(epoch);
if *pending_epoch != epoch {
continue;
}
// in which case, we remove it from the list of pending metrics,
to_remove.push(id.clone());
if let Some(pipeline) = self.pipeline(*id) {
// and inform the layout thread with the measured paint time.
let msg = LayoutControlMsg::PaintMetric(epoch, paint_time);
if let Err(e) = pipeline.layout_chan.send(msg) {
warn!("Sending PaintMetric message to layout failed ({}).", e);
}
}
}
}
for id in to_remove.iter() {
self.pending_paint_metrics.remove(id);
}
}
let rv = match target {
CompositeTarget::Window => None,
CompositeTarget::WindowAndPng => {