diff options
-rw-r--r-- | components/compositing/compositor.rs | 36 | ||||
-rw-r--r-- | components/compositing/compositor_task.rs | 9 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 8 | ||||
-rw-r--r-- | components/msg/compositor_msg.rs | 13 |
4 files changed, 44 insertions, 22 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 3ff8ba62d33..a3771b40878 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -25,7 +25,7 @@ use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; use layers::rendergl::RenderContext; use layers::rendergl; use layers::scene::Scene; -use msg::compositor_msg::{Epoch, LayerId}; +use msg::compositor_msg::{Epoch, FrameTreeId, LayerId}; use msg::compositor_msg::{ReadyState, PaintState, ScrollPolicy}; use msg::constellation_msg::AnimationState; use msg::constellation_msg::Msg as ConstellationMsg; @@ -119,8 +119,8 @@ pub struct IOCompositor<Window: WindowMethods> { /// many times for a single page. got_load_complete_message: bool, - /// Whether we have received a `SetFrameTree` message. - got_set_frame_tree_message: bool, + /// The current frame tree ID (used to reject old paint buffers) + frame_tree_id: FrameTreeId, /// The channel on which messages can be sent to the constellation. constellation_chan: ConstellationChan, @@ -269,7 +269,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { zoom_action: false, zoom_time: 0f64, got_load_complete_message: false, - got_set_frame_tree_message: false, + frame_tree_id: FrameTreeId(0), constellation_chan: constellation_chan, time_profiler_chan: time_profiler_chan, mem_profiler_chan: mem_profiler_chan, @@ -372,13 +372,14 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.set_layer_rect(pipeline_id, layer_id, &rect); } - (Msg::AssignPaintedBuffers(pipeline_id, epoch, replies), + (Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id), ShutdownState::NotShuttingDown) => { for (layer_id, new_layer_buffer_set) in replies.into_iter() { self.assign_painted_buffers(pipeline_id, layer_id, new_layer_buffer_set, - epoch); + epoch, + frame_tree_id); } self.remove_outstanding_paint_msg(); } @@ -606,7 +607,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.constellation_chan = new_constellation_chan; self.send_window_size(); - self.got_set_frame_tree_message = true; + self.frame_tree_id.next(); self.composite_if_necessary(CompositingReason::NewFrameTree); } @@ -796,10 +797,18 @@ impl<Window: WindowMethods> IOCompositor<Window> { pipeline_id: PipelineId, layer_id: LayerId, new_layer_buffer_set: Box<LayerBufferSet>, - epoch: Epoch) { - if let Some(layer) = self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) { - self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch); - return + epoch: Epoch, + frame_tree_id: FrameTreeId) { + // If the frame tree id has changed since this paint request was sent, + // reject the buffers and send them back to the paint task. If this isn't handled + // correctly, the content_age in the tile grid can get out of sync when iframes are + // loaded and the frame tree changes. This can result in the compositor thinking it + // has already drawn the most recently painted buffer, and missing a frame. + if frame_tree_id == self.frame_tree_id { + if let Some(layer) = self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) { + self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch); + return + } } let pipeline = self.get_pipeline(pipeline_id); @@ -1183,7 +1192,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { let mut num_paint_msgs_sent = 0; for (pipeline_id, requests) in pipeline_requests.into_iter() { num_paint_msgs_sent += 1; - let _ = self.get_pipeline(pipeline_id).paint_chan.send(PaintMsg::Paint(requests)); + let msg = PaintMsg::Paint(requests, self.frame_tree_id); + let _ = self.get_pipeline(pipeline_id).paint_chan.send(msg); } self.add_outstanding_paint_msg(num_paint_msgs_sent); @@ -1207,7 +1217,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { return false; } - if !self.got_set_frame_tree_message { + if self.frame_tree_id == FrameTreeId(0) { return false; } diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index bed4255e34b..31b45f90d2b 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -17,7 +17,7 @@ use geom::rect::Rect; use geom::size::Size2D; use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphicsMetadata}; use layers::layers::LayerBufferSet; -use msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState}; +use msg::compositor_msg::{Epoch, LayerId, LayerMetadata, FrameTreeId, ReadyState}; use msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy}; use msg::constellation_msg::{AnimationState, ConstellationChan, PipelineId}; use msg::constellation_msg::{Key, KeyState, KeyModifiers}; @@ -134,8 +134,9 @@ impl PaintListener for Box<CompositorProxy+'static+Send> { fn assign_painted_buffers(&mut self, pipeline_id: PipelineId, epoch: Epoch, - replies: Vec<(LayerId, Box<LayerBufferSet>)>) { - self.send(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies)); + replies: Vec<(LayerId, Box<LayerBufferSet>)>, + frame_tree_id: FrameTreeId) { + self.send(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id)); } fn initialize_layers_for_pipeline(&mut self, @@ -194,7 +195,7 @@ pub enum Msg { /// Scroll a page in a window ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>), /// Requests that the compositor assign the painted buffers to the given layers. - AssignPaintedBuffers(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>), + AssignPaintedBuffers(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>, FrameTreeId), /// Alerts the compositor to the current status of page loading. ChangeReadyState(PipelineId, ReadyState), /// Alerts the compositor to the current status of painting. diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 1ad7bf54006..74c15ad16c2 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -20,7 +20,7 @@ use layers::platform::surface::{NativeGraphicsMetadata, NativePaintingGraphicsCo use layers::platform::surface::NativeSurface; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers; -use msg::compositor_msg::{Epoch, PaintState, LayerId}; +use msg::compositor_msg::{Epoch, FrameTreeId, PaintState, LayerId}; use msg::compositor_msg::{LayerMetadata, PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; @@ -68,7 +68,7 @@ pub struct PaintRequest { pub enum Msg { PaintInit(Arc<StackingContext>), - Paint(Vec<PaintRequest>), + Paint(Vec<PaintRequest>, FrameTreeId), UnusedBuffer(Vec<Box<LayerBuffer>>), PaintPermissionGranted, PaintPermissionRevoked, @@ -210,7 +210,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { self.epoch.next(); self.initialize_layers(); } - Msg::Paint(requests) => { + Msg::Paint(requests, frame_tree_id) => { if !self.paint_permission { debug!("PaintTask: paint ready msg"); let ConstellationChan(ref mut c) = self.constellation_chan; @@ -238,7 +238,7 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { } debug!("PaintTask: returning surfaces"); - self.compositor.assign_painted_buffers(self.id, self.epoch, replies); + self.compositor.assign_painted_buffers(self.id, self.epoch, replies, frame_tree_id); } Msg::UnusedBuffer(unused_buffers) => { debug!("PaintTask: Received {} unused buffers", unused_buffers.len()); diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 7712481d146..9d6c8fc7069 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -43,6 +43,16 @@ impl Epoch { } } +#[derive(PartialEq, Eq, Debug, Copy, Clone)] +pub struct FrameTreeId(pub u32); + +impl FrameTreeId { + pub fn next(&mut self) { + let FrameTreeId(ref mut u) = *self; + *u += 1; + } +} + #[derive(Clone, PartialEq, Eq, Copy)] pub struct LayerId(pub usize, pub u32); @@ -99,7 +109,8 @@ pub trait PaintListener { fn assign_painted_buffers(&mut self, pipeline_id: PipelineId, epoch: Epoch, - replies: Vec<(LayerId, Box<LayerBufferSet>)>); + replies: Vec<(LayerId, Box<LayerBufferSet>)>, + frame_tree_id: FrameTreeId); fn paint_msg_discarded(&mut self); fn set_paint_state(&mut self, PipelineId, PaintState); |