devtools/actors/
framerate.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::mem;
6
7use atomic_refcell::AtomicRefCell;
8use devtools_traits::DevtoolScriptControlMsg;
9use malloc_size_of_derive::MallocSizeOf;
10use servo_base::generic_channel::GenericSender;
11use servo_base::id::PipelineId;
12
13use crate::actor::{Actor, ActorRegistry};
14use crate::actors::timeline::HighResolutionStamp;
15
16#[derive(MallocSizeOf)]
17pub(crate) struct FramerateActor {
18    name: String,
19    pipeline_id: PipelineId,
20    script_sender: GenericSender<DevtoolScriptControlMsg>,
21    is_recording: bool,
22    ticks: AtomicRefCell<Vec<HighResolutionStamp>>,
23}
24
25impl Actor for FramerateActor {
26    fn name(&self) -> String {
27        self.name.clone()
28    }
29}
30
31impl FramerateActor {
32    /// Return name of actor
33    pub fn create(
34        registry: &ActorRegistry,
35        pipeline_id: PipelineId,
36        script_sender: GenericSender<DevtoolScriptControlMsg>,
37    ) -> String {
38        let actor_name = registry.new_name::<Self>();
39        let mut actor = FramerateActor {
40            name: actor_name.clone(),
41            pipeline_id,
42            script_sender,
43            is_recording: false,
44            ticks: Default::default(),
45        };
46
47        actor.start_recording();
48        registry.register(actor);
49        actor_name
50    }
51
52    pub fn add_tick(&self, tick: f64) {
53        self.ticks
54            .borrow_mut()
55            .push(HighResolutionStamp::wrap(tick));
56
57        if self.is_recording {
58            let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline_id, self.name());
59            self.script_sender.send(msg).unwrap();
60        }
61    }
62
63    pub fn take_pending_ticks(&self) -> Vec<HighResolutionStamp> {
64        mem::take(&mut self.ticks.borrow_mut())
65    }
66
67    fn start_recording(&mut self) {
68        if self.is_recording {
69            return;
70        }
71
72        self.is_recording = true;
73
74        let msg = DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline_id, self.name());
75        self.script_sender.send(msg).unwrap();
76    }
77
78    fn stop_recording(&mut self) {
79        if !self.is_recording {
80            return;
81        }
82        self.is_recording = false;
83    }
84}
85
86impl Drop for FramerateActor {
87    fn drop(&mut self) {
88        self.stop_recording();
89    }
90}