diff options
author | Glenn Watson <gw@intuitionlibrary.com> | 2016-03-04 06:18:34 +1000 |
---|---|---|
committer | Glenn Watson <gw@intuitionlibrary.com> | 2016-03-04 07:26:00 +1000 |
commit | 92061132f369409380c80046adb475941d805921 (patch) | |
tree | 2e491912c8f33dd75da24b7c0616abe4572e355e | |
parent | 46256b33efeb84b35cc90ae2dee03890ba7f38c7 (diff) | |
download | servo-92061132f369409380c80046adb475941d805921.tar.gz servo-92061132f369409380c80046adb475941d805921.zip |
Fix animation smoothness when using requestAnimationFrame.
Previously, the flow for ticking animations was:
Compositor -> Constellation -> Layout -> Script
However, this means that the compositor <-> layout messages can thrash, meaning layout thread is very rarely idle.
This means that the script thread (which joins on the layout thread during reflow) was unable to execute and run rAF callbacks.
With this change, the flow is now:
Compositor -> Constellation -> Script (when rAF is active).
Compositor -> Constellation -> Layout (when transitions / animations are active and no rAF is present).
This makes rAF based animation *much* smoother.
-rw-r--r-- | components/compositing/compositor.rs | 9 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 27 | ||||
-rw-r--r-- | components/compositing/headless.rs | 3 | ||||
-rw-r--r-- | components/compositing/lib.rs | 9 | ||||
-rw-r--r-- | components/layout/layout_thread.rs | 4 |
5 files changed, 37 insertions, 15 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 8921f7798eb..793c72a5c0b 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use AnimationTickType; use CompositorMsg as ConstellationMsg; use app_units::Au; use compositor_layer::{CompositorData, CompositorLayer, RcCompositorLayer, WantsScrollEventsFlag}; @@ -1550,7 +1551,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn tick_animations_for_pipeline(&mut self, pipeline_id: PipelineId) { self.schedule_delayed_composite_if_necessary(); - self.constellation_chan.send(ConstellationMsg::TickAnimation(pipeline_id)).unwrap() + let animation_callbacks_running = self.pipeline_details(pipeline_id).animation_callbacks_running; + let animation_type = if animation_callbacks_running { + AnimationTickType::Script + } else { + AnimationTickType::Layout + }; + self.constellation_chan.send(ConstellationMsg::TickAnimation(pipeline_id, animation_type)).unwrap() } fn constrain_viewport(&mut self, pipeline_id: PipelineId, constraints: ViewportConstraints) { diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 32c8170c5a6..2ff28314269 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -9,6 +9,7 @@ //! navigation context, each `Pipeline` encompassing a `ScriptThread`, //! `LayoutThread`, and `PaintThread`. +use AnimationTickType; use CompositorMsg as FromCompositorMsg; use canvas::canvas_paint_thread::CanvasPaintThread; use canvas::webgl_paint_thread::WebGLPaintThread; @@ -585,8 +586,8 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> debug!("constellation got window resize message"); self.handle_resized_window_msg(new_size); } - Request::Compositor(FromCompositorMsg::TickAnimation(pipeline_id)) => { - self.handle_tick_animation(pipeline_id) + Request::Compositor(FromCompositorMsg::TickAnimation(pipeline_id, tick_type)) => { + self.handle_tick_animation(pipeline_id, tick_type) } Request::Compositor(FromCompositorMsg::WebDriverCommand(command)) => { debug!("constellation got webdriver command message"); @@ -912,12 +913,22 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> animation_state)) } - fn handle_tick_animation(&mut self, pipeline_id: PipelineId) { - self.pipeline(pipeline_id) - .layout_chan - .0 - .send(LayoutControlMsg::TickAnimations) - .unwrap(); + fn handle_tick_animation(&mut self, pipeline_id: PipelineId, tick_type: AnimationTickType) { + match tick_type { + AnimationTickType::Script => { + self.pipeline(pipeline_id) + .script_chan + .send(ConstellationControlMsg::TickAllAnimations(pipeline_id)) + .unwrap(); + } + AnimationTickType::Layout => { + self.pipeline(pipeline_id) + .layout_chan + .0 + .send(LayoutControlMsg::TickAnimations) + .unwrap(); + } + } } fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) { diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index 78be2671f5c..c46bdd52262 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use AnimationTickType; use CompositorMsg as ConstellationMsg; use compositor_thread::{CompositorEventListener, CompositorReceiver}; use compositor_thread::{InitialCompositorState, Msg}; @@ -98,7 +99,7 @@ impl CompositorEventListener for NullCompositor { AnimationState::NoAnimationsPresent | AnimationState::NoAnimationCallbacksPresent => {} AnimationState::AnimationCallbacksPresent => { - let msg = ConstellationMsg::TickAnimation(pipeline_id); + let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script); self.constellation_chan.send(msg).unwrap() } } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index bfeecd734e3..3df97bed036 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -76,6 +76,13 @@ mod timer_scheduler; mod touch; pub mod windowing; +/// Specifies whether the script or layout thread needs to be ticked for animation. +#[derive(Deserialize, Serialize)] +pub enum AnimationTickType { + Script, + Layout, +} + /// Messages from the compositor to the constellation. #[derive(Deserialize, Serialize)] pub enum CompositorMsg { @@ -98,7 +105,7 @@ pub enum CompositorMsg { Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection), ResizedWindow(WindowSizeData), /// Requests that the constellation instruct layout to begin a new tick of the animation. - TickAnimation(PipelineId), + TickAnimation(PipelineId, AnimationTickType), /// Dispatch a webdriver command WebDriverCommand(WebDriverCommandMsg), } diff --git a/components/layout/layout_thread.rs b/components/layout/layout_thread.rs index bf4a6ac9745..33be990217d 100644 --- a/components/layout/layout_thread.rs +++ b/components/layout/layout_thread.rs @@ -1202,10 +1202,6 @@ impl LayoutThread { fn tick_all_animations<'a, 'b>(&mut self, possibly_locked_rw_data: &mut RwData<'a, 'b>) { let mut rw_data = possibly_locked_rw_data.lock(); self.tick_animations(&mut rw_data); - - self.script_chan - .send(ConstellationControlMsg::TickAllAnimations(self.id)) - .unwrap(); } pub fn tick_animations(&mut self, rw_data: &mut LayoutThreadData) { |