Skip to content

Commit

Permalink
Start using on_refresh_driver_tick servo#5681
Browse files Browse the repository at this point in the history
RequestAnimationFrame + test-wpt
Critics
  • Loading branch information
gurobokum committed May 3, 2015
1 parent f58baa4 commit e847870
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 56 deletions.
36 changes: 26 additions & 10 deletions components/compositing/compositor.rs
Expand Up @@ -168,8 +168,11 @@ struct PipelineDetails {
/// The status of this pipeline's PaintTask.
paint_state: PaintState,

/// Current animation state
animation_state: AnimationState,
/// Wether animations are running
animations_running: bool,

/// Wether there are animation callbacks
animation_callbacks_running: bool,
}

impl PipelineDetails {
Expand All @@ -178,7 +181,8 @@ impl PipelineDetails {
pipeline: None,
ready_state: ReadyState::Blank,
paint_state: PaintState::Painting,
animation_state: AnimationState::Stopped,
animations_running: false,
animation_callbacks_running: false,
}
}
}
Expand Down Expand Up @@ -425,10 +429,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
fn change_running_animations_state(&mut self,
pipeline_id: PipelineId,
animation_state: AnimationState) {
self.get_or_create_pipeline_details(pipeline_id).animation_state = animation_state.clone();

if animation_state != AnimationState::Stopped {
self.composite_if_necessary(CompositingReason::Animation);
match animation_state {
AnimationState::AnimationsPresent => {
self.get_or_create_pipeline_details(pipeline_id).animations_running = true;
self.composite_if_necessary(CompositingReason::Animation);
}
AnimationState::AnimationCallbacksPresent => {
self.get_or_create_pipeline_details(pipeline_id).animation_callbacks_running = true;
self.composite_if_necessary(CompositingReason::Animation);
}
AnimationState::NoAnimationsPresent => {
self.get_or_create_pipeline_details(pipeline_id).animations_running = false;
}
AnimationState::NoAnimationCallbacksPresent => {
self.get_or_create_pipeline_details(pipeline_id).animation_callbacks_running = false;
}
}
}

Expand Down Expand Up @@ -923,10 +938,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
/// If there are any animations running, dispatches appropriate messages to the constellation.
fn process_animations(&mut self) {
for (pipeline_id, pipeline_details) in self.pipeline_details.iter() {
if pipeline_details.animation_state == AnimationState::Stopped {
continue
if pipeline_details.animations_running ||
pipeline_details.animation_callbacks_running {

self.constellation_chan.0.send(ConstellationMsg::TickAnimation(*pipeline_id)).unwrap();
}
self.constellation_chan.0.send(ConstellationMsg::TickAnimation(*pipeline_id)).unwrap();
}
}

Expand Down
54 changes: 31 additions & 23 deletions components/devtools/actors/framerate.rs
Expand Up @@ -20,7 +20,7 @@ pub struct FramerateActor {
script_sender: Sender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>,
start_time: Option<u64>,
is_recording: bool,
is_recording: Arc<Mutex<bool>>,
ticks: Arc<Mutex<Vec<HighResolutionStamp>>>,
}

Expand Down Expand Up @@ -52,7 +52,7 @@ impl FramerateActor {
script_sender: script_sender,
devtools_sender: devtools_sender,
start_time: None,
is_recording: false,
is_recording: Arc::new(Mutex::new(false)),
ticks: Arc::new(Mutex::new(Vec::new())),
};

Expand All @@ -74,52 +74,60 @@ impl FramerateActor {
}

fn start_recording(&mut self) {
if self.is_recording {
let lock = self.is_recording.lock();
if *lock.unwrap() {
return;
}

self.start_time = Some(precise_time_ns());
self.is_recording = true;
let mut lock = self.is_recording.lock();
let is_recording = lock.as_mut();
**is_recording.unwrap() = true;

fn closure_fabric(is_recording: Box<bool>,
name: String,
pipeline: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>)
-> Box<Fn(f64, ) + Send> {
fn get_closure(is_recording: Arc<Mutex<bool>>,
name: String,
pipeline: PipelineId,
script_sender: Sender<DevtoolScriptControlMsg>,
devtools_sender: Sender<DevtoolsControlMsg>)
-> Box<Fn(f64, ) + Send> {

let closure = move |now: f64| {
let msg = DevtoolsControlMsg::FramerateTick(name.clone(), now);
devtools_sender.send(msg).unwrap();

if !*is_recording {
if !*is_recording.lock().unwrap() {
return;
}

let closure = closure_fabric(is_recording.clone(),
name.clone(),
pipeline.clone(),
script_sender.clone(),
devtools_sender.clone());
let closure = get_closure(is_recording.clone(),
name.clone(),
pipeline.clone(),
script_sender.clone(),
devtools_sender.clone());
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(pipeline, closure);
script_sender.send(msg).unwrap();
};
Box::new(closure)
};

let closure = closure_fabric(Box::new(self.is_recording),
self.name(),
self.pipeline.clone(),
self.script_sender.clone(),
self.devtools_sender.clone());
let closure = get_closure(self.is_recording.clone(),
self.name(),
self.pipeline.clone(),
self.script_sender.clone(),
self.devtools_sender.clone());
let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline, closure);
self.script_sender.send(msg).unwrap();
}

fn stop_recording(&mut self) {
if !self.is_recording {
let lock = self.is_recording.lock();
if !*lock.unwrap() {
return;
}
self.is_recording = false;

let mut lock = self.is_recording.lock();
let is_recording = lock.as_mut();
**is_recording.unwrap() = false;
self.start_time = None;
}

Expand Down
18 changes: 8 additions & 10 deletions components/devtools/lib.rs
Expand Up @@ -259,16 +259,14 @@ fn run_server(sender: Sender<DevtoolsControlMsg>,
return console_actor_name;
}

{
let sender = sender.clone();
spawn_named("DevtoolsClientAcceptor".to_owned(), move || {
// accept connections and process them, spawning a new task for each one
for stream in listener.incoming() {
// connection succeeded
sender.send(DevtoolsControlMsg::AddClient(stream.unwrap())).unwrap();
}
});
}
let sender_clone = sender.clone();
spawn_named("DevtoolsClientAcceptor".to_owned(), move || {
// accept connections and process them, spawning a new task for each one
for stream in listener.incoming() {
// connection succeeded
sender_clone.send(DevtoolsControlMsg::AddClient(stream.unwrap())).unwrap();
}
});

loop {
match receiver.recv() {
Expand Down
12 changes: 4 additions & 8 deletions components/layout/animation.rs
Expand Up @@ -52,17 +52,13 @@ pub fn process_new_animations(rw_data: &mut LayoutTaskData, pipeline_id: Pipelin
rw_data.running_animations.push(animation)
}

let animation_state;
if !rw_data.running_animations.is_empty() {
animation_state = AnimationState::Stopped;
} else {
animation_state = AnimationState::Running;
rw_data.constellation_chan
.0
.send(Msg::ChangeRunningAnimationsState(pipeline_id, AnimationState::NoAnimationsPresent))
.unwrap();
}

rw_data.constellation_chan
.0
.send(Msg::ChangeRunningAnimationsState(pipeline_id, animation_state))
.unwrap();
}

/// Recalculates style for an animation. This does *not* run with the DOM lock held.
Expand Down
7 changes: 4 additions & 3 deletions components/msg/constellation_msg.rs
Expand Up @@ -238,9 +238,10 @@ pub enum Msg {

#[derive(Clone, Eq, PartialEq)]
pub enum AnimationState {
Stopped,
Running,
RunningByCallback
AnimationsPresent,
AnimationCallbacksPresent,
NoAnimationsPresent,
NoAnimationCallbacksPresent,
}

// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API#Events
Expand Down
2 changes: 1 addition & 1 deletion components/script/dom/document.rs
Expand Up @@ -816,7 +816,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
// TODO: Should tick animation only when document is visible
let ConstellationChan(ref chan) = window.constellation_chan();
let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(),
AnimationState::RunningByCallback);
AnimationState::AnimationCallbacksPresent);
chan.send(event).unwrap();

ident
Expand Down
2 changes: 1 addition & 1 deletion components/script_traits/lib.rs
Expand Up @@ -78,7 +78,7 @@ pub enum ConstellationControlMsg {
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
FocusIFrame(PipelineId, SubpageId),
// Passes a webdriver command to the script task for execution
WebDriverCommand(PipelineId, WebDriverScriptCommand)
WebDriverCommand(PipelineId, WebDriverScriptCommand),
/// Notifies script task that all animations are done
TickAllAnimations(PipelineId),
}
Expand Down
2 changes: 2 additions & 0 deletions tests/wpt/include.ini
@@ -1,6 +1,8 @@
skip: true
[2dcontext]
skip: false
[animation-timing]
skip: false
[dom]
skip: false
[domparsing]
Expand Down
4 changes: 4 additions & 0 deletions tests/wpt/metadata/animation-timing/callback-invoked.html.ini
@@ -0,0 +1,4 @@
[callback-invoked.html]
type: testharness
[requestAnimationFrame callback is invoked at least once before the timeout]
expected: FAIL

0 comments on commit e847870

Please sign in to comment.