aboutsummaryrefslogtreecommitdiffstats
path: root/components/compositing/headless.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/compositing/headless.rs')
-rw-r--r--components/compositing/headless.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs
new file mode 100644
index 00000000000..d8d56e64d00
--- /dev/null
+++ b/components/compositing/headless.rs
@@ -0,0 +1,99 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * 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 compositor_task::{Msg, Exit, ChangeReadyState, SetIds};
+use compositor_task::{GetGraphicsMetadata, CreateOrUpdateRootLayer, CreateOrUpdateDescendantLayer};
+use compositor_task::{SetLayerClipRect, Paint, ScrollFragmentPoint, LoadComplete};
+use compositor_task::{ShutdownComplete, ChangeRenderState, RenderMsgDiscarded};
+
+use geom::scale_factor::ScaleFactor;
+use geom::size::TypedSize2D;
+use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, ResizedWindowMsg, WindowSizeData};
+use servo_util::memory::MemoryProfilerChan;
+use servo_util::memory;
+use servo_util::time::TimeProfilerChan;
+use servo_util::time;
+
+/// Starts the compositor, which listens for messages on the specified port.
+///
+/// This is the null compositor which doesn't draw anything to the screen.
+/// It's intended for headless testing.
+pub struct NullCompositor {
+ /// The port on which we receive messages.
+ pub port: Receiver<Msg>,
+}
+
+impl NullCompositor {
+ fn new(port: Receiver<Msg>) -> NullCompositor {
+ NullCompositor {
+ port: port,
+ }
+ }
+
+ pub fn create(port: Receiver<Msg>,
+ constellation_chan: ConstellationChan,
+ time_profiler_chan: TimeProfilerChan,
+ memory_profiler_chan: MemoryProfilerChan) {
+ let compositor = NullCompositor::new(port);
+
+ // Tell the constellation about the initial fake size.
+ {
+ let ConstellationChan(ref chan) = constellation_chan;
+ chan.send(ResizedWindowMsg(WindowSizeData {
+ initial_viewport: TypedSize2D(640_f32, 480_f32),
+ visible_viewport: TypedSize2D(640_f32, 480_f32),
+ device_pixel_ratio: ScaleFactor(1.0),
+ }));
+ }
+ compositor.handle_message(constellation_chan);
+
+ // Drain compositor port, sometimes messages contain channels that are blocking
+ // another task from finishing (i.e. SetIds)
+ loop {
+ match compositor.port.try_recv() {
+ Err(_) => break,
+ Ok(_) => {},
+ }
+ }
+
+ time_profiler_chan.send(time::ExitMsg);
+ memory_profiler_chan.send(memory::ExitMsg);
+ }
+
+ fn handle_message(&self, constellation_chan: ConstellationChan) {
+ loop {
+ match self.port.recv() {
+ Exit(chan) => {
+ debug!("shutting down the constellation");
+ let ConstellationChan(ref con_chan) = constellation_chan;
+ con_chan.send(ExitMsg);
+ chan.send(());
+ }
+
+ ShutdownComplete => {
+ debug!("constellation completed shutdown");
+ break
+ }
+
+ GetGraphicsMetadata(chan) => {
+ chan.send(None);
+ }
+
+ SetIds(_, response_chan, _) => {
+ response_chan.send(());
+ }
+
+ // Explicitly list ignored messages so that when we add a new one,
+ // we'll notice and think about whether it needs a response, like
+ // SetIds.
+
+ CreateOrUpdateRootLayer(..) |
+ CreateOrUpdateDescendantLayer(..) |
+ SetLayerClipRect(..) | Paint(..) |
+ ChangeReadyState(..) | ChangeRenderState(..) | ScrollFragmentPoint(..) |
+ LoadComplete(..) | RenderMsgDiscarded(..) => ()
+ }
+ }
+ }
+}