Send status messages to the compositor

This commit is contained in:
Tim Kuehn 2013-06-07 16:43:03 -07:00 committed by Patrick Walton
parent 1fbfd7d45e
commit 7b28462193
8 changed files with 80 additions and 11 deletions

View file

@ -9,6 +9,8 @@ use windowing::{ApplicationMethods, WindowMethods, WindowMouseEvent, WindowClick
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent}; use windowing::{WindowMouseDownEvent, WindowMouseUpEvent};
use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent}; use script::dom::event::{Event, ClickEvent, MouseDownEvent, MouseUpEvent};
use script::compositor_interface::{ReadyState, CompositorInterface};
use script::compositor_interface;
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods}; use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::cell::Cell; use core::cell::Cell;
@ -36,6 +38,13 @@ pub struct CompositorTask {
chan: SharedChan<Msg>, chan: SharedChan<Msg>,
} }
impl CompositorInterface for CompositorTask {
fn send_compositor_msg(&self, msg: ReadyState) {
let msg = ChangeReadyState(msg);
self.chan.send(msg);
}
}
impl CompositorTask { impl CompositorTask {
/// Starts the compositor. Returns an interface that can be used to communicate with the /// Starts the compositor. Returns an interface that can be used to communicate with the
/// compositor and a port which allows notification when the compositor shuts down. /// compositor and a port which allows notification when the compositor shuts down.
@ -63,10 +72,12 @@ impl CompositorTask {
/// Messages to the compositor. /// Messages to the compositor.
pub enum Msg { pub enum Msg {
/// Requests that the compositor paint the given layer buffer set for the given page size.
Paint(LayerBufferSet, Size2D<uint>),
/// Requests that the compositor shut down. /// Requests that the compositor shut down.
Exit, Exit,
/// Requests that the compositor paint the given layer buffer set for the given page size.
Paint(LayerBufferSet, Size2D<uint>),
/// Alerts the compositor to the current status of page loading
ChangeReadyState(ReadyState),
} }
/// Azure surface wrapping to work with the layers infrastructure. /// Azure surface wrapping to work with the layers infrastructure.
@ -134,12 +145,19 @@ fn run_main_loop(port: Port<Msg>,
let check_for_messages: @fn() = || { let check_for_messages: @fn() = || {
// Periodically check if the script task responded to our last resize event // Periodically check if the script task responded to our last resize event
resize_rate_limiter.check_resize_response(); resize_rate_limiter.check_resize_response();
// Handle messages // Handle messages
while port.peek() { while port.peek() {
match port.recv() { match port.recv() {
Exit => *done = true, Exit => *done = true,
ChangeReadyState(ready_state) => {
let window_title = match ready_state {
compositor_interface::FinishedLoading => ~"Servo",
_ => fmt!("%? — Servo", ready_state),
};
window.set_title(window_title);
}
Paint(new_layer_buffer_set, new_size) => { Paint(new_layer_buffer_set, new_size) => {
debug!("osmain: received new frame"); debug!("osmain: received new frame");

View file

@ -10,6 +10,7 @@ use core::comm::{Port, SharedChan};
use gfx::opts::Opts; use gfx::opts::Opts;
use gfx::render_task::RenderTask; use gfx::render_task::RenderTask;
use gfx::render_task; use gfx::render_task;
use script::compositor_interface::{CompositorInterface, ReadyState};
use script::engine_interface::{EngineTask, ExitMsg, LoadUrlMsg, Msg}; use script::engine_interface::{EngineTask, ExitMsg, LoadUrlMsg, Msg};
use script::layout_interface::LayoutTask; use script::layout_interface::LayoutTask;
use script::layout_interface; use script::layout_interface;
@ -48,13 +49,15 @@ impl Engine {
profiler_chan: ProfilerChan) profiler_chan: ProfilerChan)
-> EngineTask { -> EngineTask {
let (script_port, script_chan) = (Cell(script_port), Cell(script_chan)); let (script_port, script_chan) = (Cell(script_port), Cell(script_chan));
let (request_port, request_chan) = comm::stream(); let (engine_port, engine_chan) = comm::stream();
let (request_port, request_chan) = (Cell(request_port), SharedChan::new(request_chan)); let (engine_port, engine_chan) = (Cell(engine_port), SharedChan::new(engine_chan));
let request_chan_clone = request_chan.clone(); let engine_chan_clone = engine_chan.clone();
let compositor = Cell(compositor);
let profiler_port = Cell(profiler_port); let profiler_port = Cell(profiler_port);
let opts = Cell(copy *opts); let opts = Cell(copy *opts);
do task::spawn { do task::spawn {
let compositor = compositor.take();
let render_task = RenderTask::new(compositor.clone(), let render_task = RenderTask::new(compositor.clone(),
opts.with_ref(|o| copy *o), opts.with_ref(|o| copy *o),
profiler_chan.clone()); profiler_chan.clone());
@ -70,16 +73,20 @@ impl Engine {
opts, opts,
profiler_task.chan.clone()); profiler_task.chan.clone());
let compositor_clone = compositor.clone();
let script_task = ScriptTask::new(script_port.take(), let script_task = ScriptTask::new(script_port.take(),
script_chan.take(), script_chan.take(),
request_chan_clone.clone(), engine_chan_clone.clone(),
|msg: ReadyState| {
compositor_clone.send_compositor_msg(msg)
},
layout_task.clone(), layout_task.clone(),
resource_task.clone(), resource_task.clone(),
image_cache_task.clone()); image_cache_task.clone());
Engine { Engine {
request_port: request_port.take(), request_port: engine_port.take(),
compositor: compositor.clone(), compositor: compositor.clone(),
render_task: render_task, render_task: render_task,
resource_task: resource_task.clone(), resource_task: resource_task.clone(),
@ -89,7 +96,7 @@ impl Engine {
profiler_task: profiler_task, profiler_task: profiler_task,
}.run(); }.run();
} }
request_chan.clone() engine_chan.clone()
} }
fn run(&self) { fn run(&self) {

View file

@ -162,6 +162,10 @@ impl WindowMethods<Application> for Window {
pub fn set_needs_display(@mut self) { pub fn set_needs_display(@mut self) {
glut::post_redisplay() glut::post_redisplay()
} }
pub fn set_title(@mut self, title: &str) {
glut::set_window_title(self.glut_window, title);
}
} }
impl Window { impl Window {

View file

@ -61,5 +61,7 @@ pub trait WindowMethods<A> {
pub fn check_loop(@mut self); pub fn check_loop(@mut self);
/// Schedules a redisplay at the next turn of the event loop. /// Schedules a redisplay at the next turn of the event loop.
pub fn set_needs_display(@mut self); pub fn set_needs_display(@mut self);
/// Sets the title of the window
pub fn set_title(@mut self, title: &str);
} }

View file

@ -0,0 +1,19 @@
/* 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/. */
//! The high-level interface from script to compositor. Using this abstract interface helps reduce
/// coupling between these two components
pub enum ReadyState {
/// Informs the compositor that a page is loading. Used for setting status
Loading,
/// Informs the compositor that a page is rendering. Used for setting status
Rendering,
/// Informs the compositor that a page is finished loading. Used for setting status
FinishedLoading,
}
pub trait CompositorInterface: Clone {
fn send_compositor_msg(&self, ReadyState);
}

View file

@ -4,6 +4,7 @@
use dom::bindings::utils::WrapperCache; use dom::bindings::utils::WrapperCache;
use dom::bindings::window; use dom::bindings::window;
use layout_interface::ReflowForScriptQuery; use layout_interface::ReflowForScriptQuery;
use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext}; use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};

View file

@ -64,7 +64,8 @@ pub mod html {
pub mod hubbub_html_parser; pub mod hubbub_html_parser;
} }
pub mod layout_interface; pub mod compositor_interface;
pub mod engine_interface; pub mod engine_interface;
pub mod layout_interface;
pub mod script_task; pub mod script_task;

View file

@ -5,6 +5,7 @@
/// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing /// The script task is the task that owns the DOM in memory, runs JavaScript, and spawns parsing
/// and layout tasks. /// and layout tasks.
use compositor_interface::{ReadyState, Loading, Rendering, FinishedLoading};
use dom::bindings::utils::GlobalStaticData; use dom::bindings::utils::GlobalStaticData;
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
@ -68,12 +69,14 @@ impl ScriptTask {
pub fn new(script_port: Port<ScriptMsg>, pub fn new(script_port: Port<ScriptMsg>,
script_chan: SharedChan<ScriptMsg>, script_chan: SharedChan<ScriptMsg>,
engine_task: EngineTask, engine_task: EngineTask,
//FIXME(rust #5192): workaround for lack of working ~Trait
compositor_task: ~fn(ReadyState),
layout_task: LayoutTask, layout_task: LayoutTask,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask) image_cache_task: ImageCacheTask)
-> ScriptTask { -> ScriptTask {
let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port)); let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port));
let compositor_task = Cell(compositor_task);
// FIXME: rust#6399 // FIXME: rust#6399
let mut the_task = task(); let mut the_task = task();
the_task.sched_mode(SingleThreaded); the_task.sched_mode(SingleThreaded);
@ -82,6 +85,7 @@ impl ScriptTask {
script_port.take(), script_port.take(),
script_chan_copy.clone(), script_chan_copy.clone(),
engine_task.clone(), engine_task.clone(),
compositor_task.take(),
resource_task.clone(), resource_task.clone(),
image_cache_task.clone()); image_cache_task.clone());
script_context.start(); script_context.start();
@ -123,6 +127,8 @@ pub struct ScriptContext {
/// For communicating load url messages to the engine /// For communicating load url messages to the engine
engine_task: EngineTask, engine_task: EngineTask,
/// For communicating loading messages to the compositor
compositor_task: ~fn(ReadyState),
/// The JavaScript runtime. /// The JavaScript runtime.
js_runtime: js::rust::rt, js_runtime: js::rust::rt,
@ -176,6 +182,7 @@ impl ScriptContext {
script_port: Port<ScriptMsg>, script_port: Port<ScriptMsg>,
script_chan: SharedChan<ScriptMsg>, script_chan: SharedChan<ScriptMsg>,
engine_task: EngineTask, engine_task: EngineTask,
compositor_task: ~fn(ReadyState),
resource_task: ResourceTask, resource_task: ResourceTask,
img_cache_task: ImageCacheTask) img_cache_task: ImageCacheTask)
-> @mut ScriptContext { -> @mut ScriptContext {
@ -200,6 +207,7 @@ impl ScriptContext {
script_chan: script_chan, script_chan: script_chan,
engine_task: engine_task, engine_task: engine_task,
compositor_task: compositor_task,
js_runtime: js_runtime, js_runtime: js_runtime,
js_context: js_context, js_context: js_context,
@ -308,6 +316,12 @@ impl ScriptContext {
self.layout_task.chan.send(layout_interface::ExitMsg) self.layout_task.chan.send(layout_interface::ExitMsg)
} }
// tells the compositor when loading starts and finishes
// FIXME ~compositor_interface doesn't work right now, which is why this is necessary
fn send_compositor_msg(&self, msg: ReadyState) {
(self.compositor_task)(msg);
}
/// The entry point to document loading. Defines bindings, sets up the window and document /// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout. /// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&mut self, url: Url) { fn load(&mut self, url: Url) {
@ -319,6 +333,7 @@ impl ScriptContext {
self.bindings_initialized = true self.bindings_initialized = true
} }
self.send_compositor_msg(Loading);
// Parse HTML. // Parse HTML.
// //
// Note: We can parse the next document in parallel with any previous documents. // Note: We can parse the next document in parallel with any previous documents.
@ -359,6 +374,7 @@ impl ScriptContext {
url: url url: url
}); });
self.send_compositor_msg(Rendering);
// Perform the initial reflow. // Perform the initial reflow.
self.damage = Some(DocumentDamage { self.damage = Some(DocumentDamage {
root: root_node, root: root_node,
@ -376,6 +392,7 @@ impl ScriptContext {
~"???", ~"???",
1); 1);
} }
self.send_compositor_msg(FinishedLoading);
} }
/// Sends a ping to layout and waits for the response. The response will arrive when the /// Sends a ping to layout and waits for the response. The response will arrive when the