Skip to main content

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, new_actor_name};
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) -> &str {
27        &self.name
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 = new_actor_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(
59                self.pipeline_id,
60                self.name().into(),
61            );
62            self.script_sender.send(msg).unwrap();
63        }
64    }
65
66    pub fn take_pending_ticks(&self) -> Vec<HighResolutionStamp> {
67        mem::take(&mut self.ticks.borrow_mut())
68    }
69
70    fn start_recording(&mut self) {
71        if self.is_recording {
72            return;
73        }
74
75        self.is_recording = true;
76
77        let msg =
78            DevtoolScriptControlMsg::RequestAnimationFrame(self.pipeline_id, self.name().into());
79        self.script_sender.send(msg).unwrap();
80    }
81
82    fn stop_recording(&mut self) {
83        if !self.is_recording {
84            return;
85        }
86        self.is_recording = false;
87    }
88}
89
90impl Drop for FramerateActor {
91    fn drop(&mut self) {
92        self.stop_recording();
93    }
94}