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 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 core::cell::Cell;
@ -36,6 +38,13 @@ pub struct CompositorTask {
chan: SharedChan<Msg>,
}
impl CompositorInterface for CompositorTask {
fn send_compositor_msg(&self, msg: ReadyState) {
let msg = ChangeReadyState(msg);
self.chan.send(msg);
}
}
impl CompositorTask {
/// 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.
@ -63,10 +72,12 @@ impl CompositorTask {
/// Messages to the compositor.
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.
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.
@ -134,12 +145,19 @@ fn run_main_loop(port: Port<Msg>,
let check_for_messages: @fn() = || {
// Periodically check if the script task responded to our last resize event
resize_rate_limiter.check_resize_response();
// Handle messages
while port.peek() {
match port.recv() {
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) => {
debug!("osmain: received new frame");

View file

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

View file

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

View file

@ -61,5 +61,7 @@ pub trait WindowMethods<A> {
pub fn check_loop(@mut self);
/// Schedules a redisplay at the next turn of the event loop.
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::window;
use layout_interface::ReflowForScriptQuery;
use script_task::{ExitMsg, FireTimerMsg, ScriptMsg, ScriptContext};

View file

@ -64,7 +64,8 @@ pub mod html {
pub mod hubbub_html_parser;
}
pub mod layout_interface;
pub mod compositor_interface;
pub mod engine_interface;
pub mod layout_interface;
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
/// and layout tasks.
use compositor_interface::{ReadyState, Loading, Rendering, FinishedLoading};
use dom::bindings::utils::GlobalStaticData;
use dom::document::Document;
use dom::element::Element;
@ -68,12 +69,14 @@ impl ScriptTask {
pub fn new(script_port: Port<ScriptMsg>,
script_chan: SharedChan<ScriptMsg>,
engine_task: EngineTask,
//FIXME(rust #5192): workaround for lack of working ~Trait
compositor_task: ~fn(ReadyState),
layout_task: LayoutTask,
resource_task: ResourceTask,
image_cache_task: ImageCacheTask)
-> ScriptTask {
let (script_chan_copy, script_port) = (script_chan.clone(), Cell(script_port));
let compositor_task = Cell(compositor_task);
// FIXME: rust#6399
let mut the_task = task();
the_task.sched_mode(SingleThreaded);
@ -82,6 +85,7 @@ impl ScriptTask {
script_port.take(),
script_chan_copy.clone(),
engine_task.clone(),
compositor_task.take(),
resource_task.clone(),
image_cache_task.clone());
script_context.start();
@ -123,6 +127,8 @@ pub struct ScriptContext {
/// For communicating load url messages to the engine
engine_task: EngineTask,
/// For communicating loading messages to the compositor
compositor_task: ~fn(ReadyState),
/// The JavaScript runtime.
js_runtime: js::rust::rt,
@ -176,6 +182,7 @@ impl ScriptContext {
script_port: Port<ScriptMsg>,
script_chan: SharedChan<ScriptMsg>,
engine_task: EngineTask,
compositor_task: ~fn(ReadyState),
resource_task: ResourceTask,
img_cache_task: ImageCacheTask)
-> @mut ScriptContext {
@ -200,6 +207,7 @@ impl ScriptContext {
script_chan: script_chan,
engine_task: engine_task,
compositor_task: compositor_task,
js_runtime: js_runtime,
js_context: js_context,
@ -308,6 +316,12 @@ impl ScriptContext {
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
/// objects, parses HTML and CSS, and kicks off initial layout.
fn load(&mut self, url: Url) {
@ -319,6 +333,7 @@ impl ScriptContext {
self.bindings_initialized = true
}
self.send_compositor_msg(Loading);
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
@ -359,6 +374,7 @@ impl ScriptContext {
url: url
});
self.send_compositor_msg(Rendering);
// Perform the initial reflow.
self.damage = Some(DocumentDamage {
root: root_node,
@ -376,6 +392,7 @@ impl ScriptContext {
~"???",
1);
}
self.send_compositor_msg(FinishedLoading);
}
/// Sends a ping to layout and waits for the response. The response will arrive when the