devtools/actors/
framerate.rs1use 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 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}